123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- import {
- createAddEntityInstruction,
- createInitializeComponentInstruction,
- createInitializeNewWorldInstruction,
- FindComponentPda,
- FindEntityPda,
- FindWorldPda,
- FindRegistryPda,
- Registry,
- SerializeArgs,
- SYSVAR_INSTRUCTIONS_PUBKEY,
- World,
- } from "../index";
- import BN from "bn.js";
- import type web3 from "@solana/web3.js";
- import {
- type Connection,
- type PublicKey,
- Transaction,
- type TransactionInstruction,
- } from "@solana/web3.js";
- import type WorldProgram from "../generated";
- import { PROGRAM_ID, worldIdl } from "../generated";
- import { type Idl, Program } from "@coral-xyz/anchor";
- const MAX_COMPONENTS = 5;
- /**
- * Create the transaction to Initialize a new world
- * @param payer
- * @param connection
- * @constructor
- */
- export async function InitializeNewWorld({
- payer,
- connection,
- }: {
- payer: PublicKey;
- connection: Connection;
- }): Promise<{
- instruction: TransactionInstruction;
- transaction: Transaction;
- worldPda: PublicKey;
- worldId: BN;
- }> {
- const registryPda = FindRegistryPda({});
- const registry = await Registry.fromAccountAddress(connection, registryPda);
- const worldId = new BN(registry.worlds);
- const worldPda = FindWorldPda({ worldId });
- const initializeWorldIx = createInitializeNewWorldInstruction({
- world: worldPda,
- registry: registryPda,
- payer,
- });
- return {
- instruction: initializeWorldIx,
- transaction: new Transaction().add(initializeWorldIx),
- worldPda,
- worldId,
- };
- }
- /**
- * Create the transaction to Add a new authority
- * @param authority
- * @param newAuthority
- * @param world
- * @param connection
- * @constructor
- */
- export async function AddAuthority({
- authority,
- newAuthority,
- world,
- connection,
- }: {
- authority: PublicKey;
- newAuthority: PublicKey;
- world: PublicKey;
- connection: Connection;
- }): Promise<{
- instruction: TransactionInstruction;
- transaction: Transaction;
- }> {
- const program = new Program(
- worldIdl as Idl,
- ) as unknown as Program<WorldProgram>;
- const worldInstance = await World.fromAccountAddress(connection, world);
- const worldId = new BN(worldInstance.id);
- const addAuthorityIx = await program.methods
- .addAuthority(worldId)
- .accounts({
- authority,
- newAuthority,
- world,
- })
- .instruction();
- return {
- instruction: addAuthorityIx,
- transaction: new Transaction().add(addAuthorityIx),
- };
- }
- /**
- * Create the transaction to Remove an authority
- * @param authority
- * @param authorityToDelete
- * @param world
- * @param connection
- * @constructor
- */
- export async function RemoveAuthority({
- authority,
- authorityToDelete,
- world,
- connection,
- }: {
- authority: PublicKey;
- authorityToDelete: PublicKey;
- world: PublicKey;
- connection: Connection;
- }): Promise<{
- instruction: TransactionInstruction;
- transaction: Transaction;
- }> {
- const program = new Program(
- worldIdl as Idl,
- ) as unknown as Program<WorldProgram>;
- const worldInstance = await World.fromAccountAddress(connection, world);
- const worldId = new BN(worldInstance.id);
- const removeAuthorityIx = await program.methods
- .removeAuthority(worldId)
- .accounts({
- authority,
- authorityToDelete,
- world,
- })
- .instruction();
- return {
- instruction: removeAuthorityIx,
- transaction: new Transaction().add(removeAuthorityIx),
- };
- }
- /**
- * Create the transaction to Approve a system
- * @param authority
- * @param systemToApprove
- * @param world
- * @constructor
- */
- export async function ApproveSystem({
- authority,
- systemToApprove,
- world,
- }: {
- authority: PublicKey;
- systemToApprove: PublicKey;
- world: PublicKey;
- }): Promise<{
- instruction: TransactionInstruction;
- transaction: Transaction;
- }> {
- const program = new Program(
- worldIdl as Idl,
- ) as unknown as Program<WorldProgram>;
- const approveSystemIx = await program.methods
- .approveSystem()
- .accounts({
- authority,
- system: systemToApprove,
- world,
- })
- .instruction();
- return {
- instruction: approveSystemIx,
- transaction: new Transaction().add(approveSystemIx),
- };
- }
- /**
- * Create the transaction to Remove a system
- * @param authority
- * @param systemToRemove
- * @param world
- * @constructor
- */
- export async function RemoveSystem({
- authority,
- systemToRemove,
- world,
- }: {
- authority: PublicKey;
- systemToRemove: PublicKey;
- world: PublicKey;
- }): Promise<{
- instruction: TransactionInstruction;
- transaction: Transaction;
- }> {
- const program = new Program(
- worldIdl as Idl,
- ) as unknown as Program<WorldProgram>;
- const removeSystemIx = await program.methods
- .removeSystem()
- .accounts({
- authority,
- system: systemToRemove,
- world,
- })
- .instruction();
- return {
- instruction: removeSystemIx,
- transaction: new Transaction().add(removeSystemIx),
- };
- }
- /**
- * Create the transaction to Add a new entity
- * @param payer
- * @param worldPda
- * @param connection
- * @constructor
- */
- export async function AddEntity({
- payer,
- world,
- seed,
- connection,
- }: {
- payer: PublicKey;
- world: PublicKey;
- seed?: Uint8Array;
- connection: Connection;
- }): Promise<{
- instruction: TransactionInstruction;
- transaction: Transaction;
- entityPda: PublicKey;
- }> {
- const worldInstance = await World.fromAccountAddress(connection, world);
- const worldId = new BN(worldInstance.id);
- const entityPda =
- seed !== undefined
- ? FindEntityPda({ worldId, seed })
- : FindEntityPda({ worldId, entityId: new BN(worldInstance.entities) });
- const addEntityIx = createAddEntityInstruction(
- {
- world,
- payer,
- entity: entityPda,
- },
- { extraSeed: seed ?? null },
- );
- return {
- instruction: addEntityIx,
- transaction: new Transaction().add(addEntityIx),
- entityPda,
- };
- }
- /**
- * Create the transaction to Initialize a new component
- * @param payer
- * @param entityPda
- * @param componentId
- * @param seeds
- * @param authority
- * @param anchorRemainingAccounts
- * @constructor
- */
- export async function InitializeComponent({
- payer,
- entity,
- componentId,
- seed = "",
- authority,
- anchorRemainingAccounts,
- }: {
- payer: PublicKey;
- entity: PublicKey;
- componentId: PublicKey;
- seed?: string;
- authority?: web3.PublicKey;
- anchorRemainingAccounts?: web3.AccountMeta[];
- }): Promise<{
- instruction: TransactionInstruction;
- transaction: Transaction;
- componentPda: PublicKey;
- }> {
- const componentPda = FindComponentPda({ componentId, entity, seed });
- const initializeComponentIx = createInitializeComponentInstruction({
- payer,
- entity,
- data: componentPda,
- componentProgram: componentId,
- authority: authority ?? PROGRAM_ID,
- instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
- anchorRemainingAccounts,
- });
- return {
- instruction: initializeComponentIx,
- transaction: new Transaction().add(initializeComponentIx),
- componentPda,
- };
- }
- interface ApplySystemInstruction {
- authority: PublicKey;
- systemId: PublicKey;
- entities: ApplySystemEntity[];
- world: PublicKey;
- extraAccounts?: web3.AccountMeta[];
- args?: object;
- }
- function getApplyInstructionFunctionName(componentsCount: number) {
- return `apply${componentsCount > 1 ? componentsCount : ""}`;
- }
- function getBoltComponentName(index: number, componentsCount: number) {
- if (componentsCount === 1) return "boltComponent";
- return `boltComponent${index + 1}`;
- }
- function getBoltComponentProgramName(index: number, componentsCount: number) {
- if (componentsCount === 1) return "componentProgram";
- return `componentProgram${index + 1}`;
- }
- async function createApplySystemInstruction({
- authority,
- systemId,
- entities,
- world,
- extraAccounts,
- args,
- }: ApplySystemInstruction): Promise<web3.TransactionInstruction> {
- const program = new Program(
- worldIdl as Idl,
- ) as unknown as Program<WorldProgram>;
- let componentCount = 0;
- entities.forEach(function (entity) {
- componentCount += entity.components.length;
- });
- if (componentCount <= 0) {
- throw new Error("No components provided");
- }
- if (componentCount > MAX_COMPONENTS) {
- throw new Error(
- `Not implemented for component counts outside 1-${MAX_COMPONENTS}`,
- );
- }
- const applyAccounts = {
- authority: authority ?? PROGRAM_ID,
- boltSystem: systemId,
- instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
- world,
- };
- let componentIndex = 0;
- entities.forEach(function (entity) {
- entity.components.forEach(function (component) {
- const componentPda = FindComponentPda({
- componentId: component.componentId,
- entity: entity.entity,
- seed: component.seed,
- });
- applyAccounts[
- getBoltComponentProgramName(componentIndex, componentCount)
- ] = component.componentId;
- applyAccounts[getBoltComponentName(componentIndex, componentCount)] =
- componentPda;
- componentIndex++;
- });
- });
- return program.methods[getApplyInstructionFunctionName(componentCount)](
- SerializeArgs(args),
- )
- .accounts(applyAccounts)
- .remainingAccounts(extraAccounts ?? [])
- .instruction();
- }
- interface ApplySystemEntity {
- entity: PublicKey;
- components: ApplySystemComponent[];
- }
- interface ApplySystemComponent {
- componentId: PublicKey;
- seed?: string;
- }
- /**
- * Apply a system to a set of components
- * @param authority
- * @param systemId
- * @param entities
- * @param extraAccounts
- * @param args
- * @constructor
- */
- export async function ApplySystem({
- authority,
- systemId,
- entities,
- world,
- extraAccounts,
- args,
- }: {
- authority: PublicKey;
- systemId: PublicKey;
- entities: ApplySystemEntity[];
- world: PublicKey;
- extraAccounts?: web3.AccountMeta[];
- args?: object;
- }): Promise<{ instruction: TransactionInstruction; transaction: Transaction }> {
- const applySystemIx = await createApplySystemInstruction({
- authority,
- systemId,
- entities,
- world,
- extraAccounts,
- args,
- });
- return {
- instruction: applySystemIx,
- transaction: new Transaction().add(applySystemIx),
- };
- }
|