import { KeyedAccountInfo, PublicKey, SystemProgram } from '@solana/web3.js'; import { BN } from '@staratlas/anchor'; import { Account, AccountStatic, AsyncSigner, DecodedAccountData, FixedSizeArray, InstructionReturn, arrayDeepEquals, byteArrayToString, decodeAccount, staticImplements, stringToByteArray, } from '@staratlas/data-source'; import { SageIDL, SageIDLProgram, StarAccount } from './constants'; export enum StarType { /// White dwarf WhiteDwarf = 0, /// Red dwarf RedDwarf = 1, /// Solar Solar = 2, /// Hot blue HotBlue = 3, /// Red giant RedGiant = 4, } export interface RegisterStarInput { name: string; size: BN; subCoordinates: FixedSizeArray; starType: StarType; keyIndex: number; } export interface UpdateStarInput { name?: string; size?: BN; starType?: StarType; keyIndex: number; } /** * Check if two `StarAccount` instances are equal * @param data1 - first StarAccount * @param data2 - second StarAccount * @returns a boolean */ export function starDataEquals( data1: StarAccount, data2: StarAccount, ): boolean { return ( data1.version === data2.version && arrayDeepEquals(data1.sector, data2.sector, (a, b) => a.eq(b)) && data1.gameId.equals(data2.gameId) && data1.size.eq(data2.size) && arrayDeepEquals(data1.name, data2.name, (a, b) => a === b) && arrayDeepEquals(data1.subCoordinates, data2.subCoordinates, (a, b) => a.eq(b), ) && data1.starType === data2.starType ); } @staticImplements>() export class Star implements Account { static readonly ACCOUNT_NAME: NonNullable< SageIDL['accounts'] >[number]['name'] = 'star'; static readonly MIN_DATA_SIZE = 8 + // discriminator 1 + // version 64 + // name 32 + // gameId 8 * 2 + // sector 8 * 2 + // subCoordinates 1 + // starType 8; // size constructor(private _data: StarAccount, private _key: PublicKey) {} get data(): Readonly { return this._data; } get key(): PublicKey { return this._key; } get prettyName(): string { return byteArrayToString(this.data.name); } /** * Register a Star * @param params - the params to this functions * @param params.program - SAGE program * @param params.key - the key authorized to run this instruction * @param params.profile - the profile with the required permissions for the instruction * @param params.star - the star * @param params.sector - the sector in which the new star will be located * @param params.gameId - the SAGE game id * @param params.input - instruction input params * @returns InstructionReturn */ static registerStar(params: { program: SageIDLProgram; key: AsyncSigner; profile: PublicKey; star: AsyncSigner; sector: PublicKey; gameId: PublicKey; input: RegisterStarInput; }): InstructionReturn { const { program, key, profile, star, sector, gameId, input } = params; return async (funder) => [ { instruction: await program.methods .registerStar({ ...input, name: stringToByteArray(input.name, 64), starType: input.starType as never, }) .accountsStrict({ gameAndProfile: { key: key.publicKey(), profile, gameId, }, funder: funder.publicKey(), star: star.publicKey(), sector, systemProgram: SystemProgram.programId, }) .instruction(), signers: [key, funder, star], }, ]; } /** * Update a Star * @param params - the params to this functions * @param params.program - SAGE program * @param params.key - the key authorized to run this instruction * @param params.profile - the profile with the required permissions for the instruction * @param params.star - the star * @param params.gameId - the SAGE game id * @param params.input - instruction input params * @returns InstructionReturn */ static updateStar(params: { program: SageIDLProgram; key: AsyncSigner; profile: PublicKey; star: PublicKey; gameId: PublicKey; input: UpdateStarInput; }): InstructionReturn { const { profile, key, program, star, gameId, input } = params; return async () => [ { instruction: await program.methods .updateStar({ keyIndex: input.keyIndex, name: input.name == null ? null : stringToByteArray(input.name, 64), size: input.size == null ? null : input.size, starType: input.starType == null ? null : (input.starType as never), }) .accountsStrict({ gameAndProfile: { key: key.publicKey(), profile, gameId, }, star, }) .instruction(), signers: [key], }, ]; } static decodeData( account: KeyedAccountInfo, program: SageIDLProgram, ): DecodedAccountData { return decodeAccount(account, program, Star); } }