UNPKG

@solana/instructions

Version:

Helpers for creating transaction instructions

1 lines 12.6 kB
{"version":3,"sources":["../src/instruction.ts","../src/roles.ts"],"names":["SolanaError","SOLANA_ERROR__INSTRUCTION__PROGRAM_ID_MISMATCH","SOLANA_ERROR__INSTRUCTION__EXPECTED_TO_HAVE_ACCOUNTS","SOLANA_ERROR__INSTRUCTION__EXPECTED_TO_HAVE_DATA","AccountRole"],"mappings":";;;;;AA+CO,SAAS,uBAAA,CACZ,aACA,cAAA,EAC0E;AAC1E,EAAA,OAAO,YAAY,cAAA,KAAmB,cAAA;AAC1C;AAEO,SAAS,6BAAA,CACZ,aACA,cAAA,EACkF;AAClF,EAAA,IAAI,WAAA,CAAY,mBAAmB,cAAA,EAAgB;AAC/C,IAAA,MAAM,IAAIA,mBAAYC,qDAAA,EAAgD;AAAA,MAClE,sBAAsB,WAAA,CAAY,cAAA;AAAA,MAClC,sBAAA,EAAwB;AAAA,KAC3B,CAAA;AAAA,EACL;AACJ;AAEO,SAAS,0BAGd,WAAA,EAA6F;AAC3F,EAAA,OAAO,YAAY,QAAA,KAAa,MAAA;AACpC;AAEO,SAAS,gCAGd,WAAA,EAAqG;AACnG,EAAA,IAAI,WAAA,CAAY,aAAa,MAAA,EAAW;AACpC,IAAA,MAAM,IAAID,mBAAYE,2DAAA,EAAsD;AAAA,MACxE,MAAM,WAAA,CAAY,IAAA;AAAA,MAClB,gBAAgB,WAAA,CAAY;AAAA,KAC/B,CAAA;AAAA,EACL;AACJ;AA4BO,SAAS,sBAGd,WAAA,EAAqF;AACnF,EAAA,OAAO,YAAY,IAAA,KAAS,MAAA;AAChC;AAEO,SAAS,4BAGd,WAAA,EAA6F;AAC3F,EAAA,IAAI,WAAA,CAAY,SAAS,MAAA,EAAW;AAChC,IAAA,MAAM,IAAIF,mBAAYG,uDAAA,EAAkD;AAAA,MACpE,kBAAkB,WAAA,CAAY,QAAA,EAAU,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA;AAAA,MAC1D,gBAAgB,WAAA,CAAY;AAAA,KAC/B,CAAA;AAAA,EACL;AACJ;;;AClHO,IAAK,WAAA,qBAAAC,YAAAA,KAAL;AAEH,EAAAA,YAAAA,CAAAA,YAAAA,CAAA,iBAAA,CAAA;AAAA,EAA0B,CAAA,CAAA,GAA1B,iBAAA;AACA,EAAAA,YAAAA,CAAAA,YAAAA,CAAA,iBAAA,CAAA;AAAA,EAA0B,CAAA,CAAA,GAA1B,iBAAA;AACA,EAAAA,YAAAA,CAAAA,YAAAA,CAAA,UAAA,CAAA;AAAA,EAA0B,CAAA,CAAA,GAA1B,UAAA;AACA,EAAAA,YAAAA,CAAAA,YAAAA,CAAA,UAAA,CAAA;AAAA,EAA0B,CAAA,CAAA,GAA1B,UAAA;AALQ,EAAA,OAAAA,YAAAA;AAAA,CAAA,EAAA,WAAA,IAAA,EAAA;AASZ,IAAM,iBAAA,GAAoB,CAAA;AAC1B,IAAM,mBAAA,GAAsB,CAAA;AAQrB,SAAS,yBAAyB,IAAA,EAAgC;AACrE,EAAA,OAAO,OAAO,CAAC,iBAAA;AACnB;AAQO,SAAS,wBAAwB,IAAA,EAAgC;AACpE,EAAA,OAAO,OAAO,CAAC,mBAAA;AACnB;AAMO,SAAS,aAAa,IAAA,EAAsF;AAC/G,EAAA,OAAO,IAAA,IAAQ,CAAA;AACnB;AAMO,SAAS,eAAe,IAAA,EAA+E;AAC1G,EAAA,OAAA,CAAQ,OAAO,mBAAA,MAAyB,CAAA;AAC5C;AAsBO,SAAS,UAAA,CAAW,OAAoB,KAAA,EAAiC;AAC5E,EAAA,OAAO,KAAA,GAAQ,KAAA;AACnB;AAQO,SAAS,oBAAoB,IAAA,EAAgC;AAChE,EAAA,OAAO,IAAA,GAAO,iBAAA;AAClB;AAQO,SAAS,sBAAsB,IAAA,EAAgC;AAClE,EAAA,OAAO,IAAA,GAAO,mBAAA;AAClB","file":"index.browser.cjs","sourcesContent":["import { Address } from '@solana/addresses';\nimport { ReadonlyUint8Array } from '@solana/codecs-core';\nimport {\n SOLANA_ERROR__INSTRUCTION__EXPECTED_TO_HAVE_ACCOUNTS,\n SOLANA_ERROR__INSTRUCTION__EXPECTED_TO_HAVE_DATA,\n SOLANA_ERROR__INSTRUCTION__PROGRAM_ID_MISMATCH,\n SolanaError,\n} from '@solana/errors';\n\nimport { AccountLookupMeta, AccountMeta } from './accounts';\n\n/**\n * An instruction destined for a given program.\n *\n * @example\n * ```ts\n * type StakeProgramInstruction = Instruction<'StakeConfig11111111111111111111111111111111'>;\n * ```\n */\nexport interface Instruction<\n TProgramAddress extends string = string,\n TAccounts extends readonly (AccountLookupMeta | AccountMeta)[] = readonly (AccountLookupMeta | AccountMeta)[],\n> {\n readonly accounts?: TAccounts;\n readonly data?: ReadonlyUint8Array;\n readonly programAddress: Address<TProgramAddress>;\n}\n\n/**\n * An instruction that loads certain accounts.\n *\n * @example\n * ```ts\n * type InstructionWithTwoAccounts = InstructionWithAccounts<\n * [\n * WritableAccount, // First account\n * RentSysvar, // Second account\n * ]\n * >;\n * ```\n */\nexport interface InstructionWithAccounts<\n TAccounts extends readonly (AccountLookupMeta | AccountMeta)[],\n> extends Instruction {\n readonly accounts: TAccounts;\n}\n\nexport function isInstructionForProgram<TProgramAddress extends string, TInstruction extends Instruction>(\n instruction: TInstruction,\n programAddress: Address<TProgramAddress>,\n): instruction is TInstruction & { programAddress: Address<TProgramAddress> } {\n return instruction.programAddress === programAddress;\n}\n\nexport function assertIsInstructionForProgram<TProgramAddress extends string, TInstruction extends Instruction>(\n instruction: TInstruction,\n programAddress: Address<TProgramAddress>,\n): asserts instruction is TInstruction & { programAddress: Address<TProgramAddress> } {\n if (instruction.programAddress !== programAddress) {\n throw new SolanaError(SOLANA_ERROR__INSTRUCTION__PROGRAM_ID_MISMATCH, {\n actualProgramAddress: instruction.programAddress,\n expectedProgramAddress: programAddress,\n });\n }\n}\n\nexport function isInstructionWithAccounts<\n TAccounts extends readonly (AccountLookupMeta | AccountMeta)[] = readonly (AccountLookupMeta | AccountMeta)[],\n TInstruction extends Instruction = Instruction,\n>(instruction: TInstruction): instruction is InstructionWithAccounts<TAccounts> & TInstruction {\n return instruction.accounts !== undefined;\n}\n\nexport function assertIsInstructionWithAccounts<\n TAccounts extends readonly (AccountLookupMeta | AccountMeta)[] = readonly (AccountLookupMeta | AccountMeta)[],\n TInstruction extends Instruction = Instruction,\n>(instruction: TInstruction): asserts instruction is InstructionWithAccounts<TAccounts> & TInstruction {\n if (instruction.accounts === undefined) {\n throw new SolanaError(SOLANA_ERROR__INSTRUCTION__EXPECTED_TO_HAVE_ACCOUNTS, {\n data: instruction.data,\n programAddress: instruction.programAddress,\n });\n }\n}\n\n/**\n * An instruction whose data conforms to a certain type.\n *\n * This is most useful when you have a branded `Uint8Array` that represents a particular\n * instruction's data.\n *\n * @example A type for the \\`AdvanceNonce\\` instruction of the System program\n * ```ts\n * type AdvanceNonceAccountInstruction<\n * TNonceAccountAddress extends string = string,\n * TNonceAuthorityAddress extends string = string,\n * > = Instruction<'11111111111111111111111111111111'> &\n * InstructionWithAccounts<\n * [\n * WritableAccount<TNonceAccountAddress>,\n * ReadonlyAccount<'SysvarRecentB1ockHashes11111111111111111111'>,\n * ReadonlySignerAccount<TNonceAuthorityAddress>,\n * ]\n * > &\n * InstructionWithData<AdvanceNonceAccountInstructionData>;\n * ```\n */\nexport interface InstructionWithData<TData extends ReadonlyUint8Array> extends Instruction {\n readonly data: TData;\n}\n\nexport function isInstructionWithData<\n TData extends ReadonlyUint8Array = ReadonlyUint8Array,\n TInstruction extends Instruction = Instruction,\n>(instruction: TInstruction): instruction is InstructionWithData<TData> & TInstruction {\n return instruction.data !== undefined;\n}\n\nexport function assertIsInstructionWithData<\n TData extends ReadonlyUint8Array = ReadonlyUint8Array,\n TInstruction extends Instruction = Instruction,\n>(instruction: TInstruction): asserts instruction is InstructionWithData<TData> & TInstruction {\n if (instruction.data === undefined) {\n throw new SolanaError(SOLANA_ERROR__INSTRUCTION__EXPECTED_TO_HAVE_DATA, {\n accountAddresses: instruction.accounts?.map(a => a.address),\n programAddress: instruction.programAddress,\n });\n }\n}\n","/**\n * Describes the purpose for which an account participates in a transaction.\n *\n * Every account that participates in a transaction can be read from, but only ones that you mark as\n * writable may be written to, and only ones that you indicate must sign the transaction will gain\n * the privileges associated with signers at runtime.\n *\n * | | `isSigner` | `isWritable` |\n * | ----------------------------- | ---------- | ------------ |\n * | `AccountRole.READONLY` | &#x274c; | &#x274c; |\n * | `AccountRole.WRITABLE` | &#x274c; | &#x2705; |\n * | `AccountRole.READONLY_SIGNER` | &#x2705; | &#x274c; |\n * | `AccountRole.WRITABLE_SIGNER` | &#x2705; | &#x2705; |\n */\nexport enum AccountRole {\n // Bitflag guide: is signer ⌄⌄ is writable\n WRITABLE_SIGNER = /* 3 */ 0b11, // prettier-ignore\n READONLY_SIGNER = /* 2 */ 0b10, // prettier-ignore\n WRITABLE = /* 1 */ 0b01, // prettier-ignore\n READONLY = /* 0 */ 0b00, // prettier-ignore\n}\n\n// Quick primer on bitwise operations: https://stackoverflow.com/a/1436448/802047\nconst IS_SIGNER_BITMASK = 0b10;\nconst IS_WRITABLE_BITMASK = 0b01;\n\n/**\n * @returns An {@link AccountRole} representing the non-signer variant of the supplied role.\n */\nexport function downgradeRoleToNonSigner(role: AccountRole.READONLY_SIGNER): AccountRole.READONLY;\nexport function downgradeRoleToNonSigner(role: AccountRole.WRITABLE_SIGNER): AccountRole.WRITABLE;\nexport function downgradeRoleToNonSigner(role: AccountRole): AccountRole;\nexport function downgradeRoleToNonSigner(role: AccountRole): AccountRole {\n return role & ~IS_SIGNER_BITMASK;\n}\n\n/**\n * @returns An {@link AccountRole} representing the read-only variant of the supplied role.\n */\nexport function downgradeRoleToReadonly(role: AccountRole.WRITABLE): AccountRole.READONLY;\nexport function downgradeRoleToReadonly(role: AccountRole.WRITABLE_SIGNER): AccountRole.READONLY_SIGNER;\nexport function downgradeRoleToReadonly(role: AccountRole): AccountRole;\nexport function downgradeRoleToReadonly(role: AccountRole): AccountRole {\n return role & ~IS_WRITABLE_BITMASK;\n}\n\n/**\n * Returns `true` if the {@link AccountRole} given represents that of a signer. Also refines the\n * TypeScript type of the supplied role.\n */\nexport function isSignerRole(role: AccountRole): role is AccountRole.READONLY_SIGNER | AccountRole.WRITABLE_SIGNER {\n return role >= AccountRole.READONLY_SIGNER;\n}\n\n/**\n * Returns `true` if the {@link AccountRole} given represents that of a writable account. Also\n * refines the TypeScript type of the supplied role.\n */\nexport function isWritableRole(role: AccountRole): role is AccountRole.WRITABLE | AccountRole.WRITABLE_SIGNER {\n return (role & IS_WRITABLE_BITMASK) !== 0;\n}\n\n/**\n * Given two {@link AccountRole | AccountRoles}, will return the {@link AccountRole} that grants the\n * highest privileges of both.\n *\n * @example\n * ```ts\n * // Returns `AccountRole.WRITABLE_SIGNER`\n * mergeRoles(AccountRole.READONLY_SIGNER, AccountRole.WRITABLE);\n * ```\n */\nexport function mergeRoles(roleA: AccountRole.WRITABLE, roleB: AccountRole.READONLY_SIGNER): AccountRole.WRITABLE_SIGNER; // prettier-ignore\nexport function mergeRoles(roleA: AccountRole.READONLY_SIGNER, roleB: AccountRole.WRITABLE): AccountRole.WRITABLE_SIGNER; // prettier-ignore\nexport function mergeRoles(roleA: AccountRole, roleB: AccountRole.WRITABLE_SIGNER): AccountRole.WRITABLE_SIGNER; // prettier-ignore\nexport function mergeRoles(roleA: AccountRole.WRITABLE_SIGNER, roleB: AccountRole): AccountRole.WRITABLE_SIGNER; // prettier-ignore\nexport function mergeRoles(roleA: AccountRole, roleB: AccountRole.READONLY_SIGNER): AccountRole.READONLY_SIGNER; // prettier-ignore\nexport function mergeRoles(roleA: AccountRole.READONLY_SIGNER, roleB: AccountRole): AccountRole.READONLY_SIGNER; // prettier-ignore\nexport function mergeRoles(roleA: AccountRole, roleB: AccountRole.WRITABLE): AccountRole.WRITABLE; // prettier-ignore\nexport function mergeRoles(roleA: AccountRole.WRITABLE, roleB: AccountRole): AccountRole.WRITABLE; // prettier-ignore\nexport function mergeRoles(roleA: AccountRole.READONLY, roleB: AccountRole.READONLY): AccountRole.READONLY; // prettier-ignore\nexport function mergeRoles(roleA: AccountRole, roleB: AccountRole): AccountRole; // prettier-ignore\nexport function mergeRoles(roleA: AccountRole, roleB: AccountRole): AccountRole {\n return roleA | roleB;\n}\n\n/**\n * @returns An {@link AccountRole} representing the signer variant of the supplied role.\n */\nexport function upgradeRoleToSigner(role: AccountRole.READONLY): AccountRole.READONLY_SIGNER;\nexport function upgradeRoleToSigner(role: AccountRole.WRITABLE): AccountRole.WRITABLE_SIGNER;\nexport function upgradeRoleToSigner(role: AccountRole): AccountRole;\nexport function upgradeRoleToSigner(role: AccountRole): AccountRole {\n return role | IS_SIGNER_BITMASK;\n}\n\n/**\n * @returns An {@link AccountRole} representing the writable variant of the supplied role.\n */\nexport function upgradeRoleToWritable(role: AccountRole.READONLY): AccountRole.WRITABLE;\nexport function upgradeRoleToWritable(role: AccountRole.READONLY_SIGNER): AccountRole.WRITABLE_SIGNER;\nexport function upgradeRoleToWritable(role: AccountRole): AccountRole;\nexport function upgradeRoleToWritable(role: AccountRole): AccountRole {\n return role | IS_WRITABLE_BITMASK;\n}\n"]}