@solana/instructions
Version:
Helpers for creating transaction instructions
1 lines • 12.4 kB
Source Map (JSON)
{"version":3,"sources":["../src/instruction.ts","../src/roles.ts"],"names":["AccountRole"],"mappings":";;;AA8CO,SAAS,uBAAA,CACZ,aACA,cAC0E,EAAA;AAC1E,EAAA,OAAO,YAAY,cAAmB,KAAA,cAAA;AAC1C;AAEO,SAAS,6BAAA,CACZ,aACA,cACkF,EAAA;AAClF,EAAI,IAAA,WAAA,CAAY,mBAAmB,cAAgB,EAAA;AAC/C,IAAM,MAAA,IAAI,YAAY,8CAAgD,EAAA;AAAA,MAClE,sBAAsB,WAAY,CAAA,cAAA;AAAA,MAClC,sBAAwB,EAAA;AAAA,KAC3B,CAAA;AAAA;AAET;AAEO,SAAS,0BAGd,WAA6F,EAAA;AAC3F,EAAA,OAAO,YAAY,QAAa,KAAA,MAAA;AACpC;AAEO,SAAS,gCAGd,WAAqG,EAAA;AACnG,EAAI,IAAA,WAAA,CAAY,aAAa,MAAW,EAAA;AACpC,IAAM,MAAA,IAAI,YAAY,oDAAsD,EAAA;AAAA,MACxE,MAAM,WAAY,CAAA,IAAA;AAAA,MAClB,gBAAgB,WAAY,CAAA;AAAA,KAC/B,CAAA;AAAA;AAET;AA4BO,SAAS,sBAGd,WAAqF,EAAA;AACnF,EAAA,OAAO,YAAY,IAAS,KAAA,MAAA;AAChC;AAEO,SAAS,4BAGd,WAA6F,EAAA;AAC3F,EAAI,IAAA,WAAA,CAAY,SAAS,MAAW,EAAA;AAChC,IAAM,MAAA,IAAI,YAAY,gDAAkD,EAAA;AAAA,MACpE,kBAAkB,WAAY,CAAA,QAAA,EAAU,GAAI,CAAA,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA;AAAA,MAC1D,gBAAgB,WAAY,CAAA;AAAA,KAC/B,CAAA;AAAA;AAET;;;ACjHY,IAAA,WAAA,qBAAAA,YAAL,KAAA;AAEH,EAAAA,YAAA,CAAA,YAAA,CAAA,iBAAA,CAAA;AAAA,EAA0B,CAA1B,CAAA,GAAA,iBAAA;AACA,EAAAA,YAAA,CAAA,YAAA,CAAA,iBAAA,CAAA;AAAA,EAA0B,CAA1B,CAAA,GAAA,iBAAA;AACA,EAAAA,YAAA,CAAA,YAAA,CAAA,UAAA,CAAA;AAAA,EAA0B,CAA1B,CAAA,GAAA,UAAA;AACA,EAAAA,YAAA,CAAA,YAAA,CAAA,UAAA,CAAA;AAAA,EAA0B,CAA1B,CAAA,GAAA,UAAA;AALQ,EAAAA,OAAAA,YAAAA;AAAA,CAAA,EAAA,WAAA,IAAA,EAAA;AASZ,IAAM,iBAAoB,GAAA,CAAA;AAC1B,IAAM,mBAAsB,GAAA,CAAA;AAQrB,SAAS,yBAAyB,IAAgC,EAAA;AACrE,EAAA,OAAO,OAAO,EAAC;AACnB;AAQO,SAAS,wBAAwB,IAAgC,EAAA;AACpE,EAAA,OAAO,OAAO,EAAC;AACnB;AAMO,SAAS,aAAa,IAAsF,EAAA;AAC/G,EAAA,OAAO,IAAQ,IAAA,CAAA;AACnB;AAMO,SAAS,eAAe,IAA+E,EAAA;AAC1G,EAAA,OAAA,CAAQ,OAAO,mBAAyB,MAAA,CAAA;AAC5C;AAsBO,SAAS,UAAA,CAAW,OAAoB,KAAiC,EAAA;AAC5E,EAAA,OAAO,KAAQ,GAAA,KAAA;AACnB;AAQO,SAAS,oBAAoB,IAAgC,EAAA;AAChE,EAAA,OAAO,IAAO,GAAA,iBAAA;AAClB;AAQO,SAAS,sBAAsB,IAAgC,EAAA;AAClE,EAAA,OAAO,IAAO,GAAA,mBAAA;AAClB","file":"index.browser.mjs","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<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` | ❌ | ❌ |\n * | `AccountRole.WRITABLE` | ❌ | ✅ |\n * | `AccountRole.READONLY_SIGNER` | ✅ | ❌ |\n * | `AccountRole.WRITABLE_SIGNER` | ✅ | ✅ |\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"]}