123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- import { PublicKey, TransactionInstruction } from "@solana/web3.js";
- import { IdlAccount, IdlInstruction, IdlAccountItem } from "../../idl";
- import { IdlError } from "../../error";
- import Coder from "../../coder";
- import { toInstruction, validateAccounts } from "../common";
- import { RpcAccounts, splitArgsAndCtx } from "../context";
- /**
- * Dynamically generated instruction namespace.
- */
- export interface Ixs {
- [key: string]: IxFn;
- }
- /**
- * Ix is a function to create a `TransactionInstruction` generated from an IDL.
- */
- export type IxFn = IxProps & ((...args: any[]) => any);
- type IxProps = {
- accounts: (ctx: RpcAccounts) => any;
- };
- export default class InstructionNamespace {
- // Builds the instuction namespace.
- public static build(
- idlIx: IdlInstruction,
- coder: Coder,
- programId: PublicKey
- ): IxFn {
- if (idlIx.name === "_inner") {
- throw new IdlError("the _inner name is reserved");
- }
- const ix = (...args: any[]): TransactionInstruction => {
- const [ixArgs, ctx] = splitArgsAndCtx(idlIx, [...args]);
- validateAccounts(idlIx.accounts, ctx.accounts);
- validateInstruction(idlIx, ...args);
- const keys = InstructionNamespace.accountsArray(
- ctx.accounts,
- idlIx.accounts
- );
- if (ctx.remainingAccounts !== undefined) {
- keys.push(...ctx.remainingAccounts);
- }
- if (ctx.__private && ctx.__private.logAccounts) {
- console.log("Outgoing account metas:", keys);
- }
- return new TransactionInstruction({
- keys,
- programId,
- data: coder.instruction.encode(
- idlIx.name,
- toInstruction(idlIx, ...ixArgs)
- ),
- });
- };
- // Utility fn for ordering the accounts for this instruction.
- ix["accounts"] = (accs: RpcAccounts) => {
- return InstructionNamespace.accountsArray(accs, idlIx.accounts);
- };
- return ix;
- }
- public static accountsArray(
- ctx: RpcAccounts,
- accounts: IdlAccountItem[]
- ): any {
- return accounts
- .map((acc: IdlAccountItem) => {
- // Nested accounts.
- // @ts-ignore
- const nestedAccounts: IdlAccountItem[] | undefined = acc.accounts;
- if (nestedAccounts !== undefined) {
- const rpcAccs = ctx[acc.name] as RpcAccounts;
- return InstructionNamespace.accountsArray(
- rpcAccs,
- nestedAccounts
- ).flat();
- } else {
- const account: IdlAccount = acc as IdlAccount;
- return {
- pubkey: ctx[acc.name],
- isWritable: account.isMut,
- isSigner: account.isSigner,
- };
- }
- })
- .flat();
- }
- }
- // Throws error if any argument required for the `ix` is not given.
- function validateInstruction(ix: IdlInstruction, ...args: any[]) {
- // todo
- }
|