import { AccountNamespace, Idl, InstructionNamespace, Program, AnchorProvider, RpcNamespace, } from "@project-serum/anchor"; import { AllInstructions } from "@project-serum/anchor/dist/cjs/program/namespace/types"; import { Wallet } from "@project-serum/anchor/dist/cjs/provider"; import { PublicKey, Signer, TransactionInstruction, Commitment, Finality } from "@solana/web3.js"; import { TypedAccountParser } from "./accountFetchCache"; import { BigInstructionResult, InstructionResult, sendInstructions, sendMultipleInstructions } from "./transaction"; export abstract class AnchorSdk { program: Program; provider: AnchorProvider; programId: PublicKey; rpc: RpcNamespace>; instruction: InstructionNamespace; wallet: Wallet; account: AccountNamespace; errors: Map | undefined; static ID: PublicKey; constructor(args: { provider: AnchorProvider; program: Program }) { this.program = args.program; this.provider = args.provider; this.programId = args.program.programId; this.rpc = args.program.rpc; this.instruction = args.program.instruction; this.wallet = args.provider.wallet; this.account = args.program.account; this.errors = args.program.idl.errors?.reduce((acc, err) => { acc.set(err.code, `${err.name}: ${err.msg}`); return acc; }, new Map()); } protected async getAccount( key: PublicKey, decoder: TypedAccountParser ): Promise { const account = await this.provider.connection.getAccountInfo(key); if (account) { return decoder(key, account); } return null; } async sendInstructions( instructions: TransactionInstruction[], signers: Signer[], payer?: PublicKey, commitment?: Commitment ): Promise { try { return await sendInstructions( this.errors || new Map(), this.provider, instructions, signers, payer, commitment ); } catch (e: any) { // If all compute was consumed, this can often mean that the bonding price moved too much, causing // our root estimates to be off. if ( e.logs && e.logs.some((l: string) => l.endsWith("consumed 200000 of 200000 compute units") ) ) { throw new Error( "Consumed all of the compute units. It's possible the price has moved too much, please try again." ); } throw e; } } async execute( command: Promise>, payer: PublicKey = this.wallet.publicKey, commitment?: Commitment ): Promise { const { instructions, signers, output } = await command; if (instructions.length > 0) { const txid = await this.sendInstructions( instructions, signers, payer, commitment ); return { txid, ...output }; } return output; } async executeBig( command: Promise>, payer: PublicKey = this.wallet.publicKey, finality?: Finality ): Promise { const { instructions, signers, output } = await command; if (instructions.length > 0) { const txids = await sendMultipleInstructions( this.errors || new Map(), this.provider, instructions, signers, payer || this.wallet.publicKey, finality ); return { ...output, txids: Array.from(txids), } } return output; } }