From 627c275e9cdf3dafafcf44473ba8146cc7979d44 Mon Sep 17 00:00:00 2001 From: Armani Ferrante Date: Wed, 10 Feb 2021 23:36:02 +0800 Subject: [PATCH] ts: Add instruction method to state namespace --- CHANGELOG.md | 1 + ts/src/rpc.ts | 55 ++++++++++++++++++++++++++++++--------------------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66e54b5ee..ad91b52e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ incremented for features. * spl: Add shared memory api. * lang/attribute/access-control: Allow specifying multiple modifier functions. * lang/syn: Allow state structs that don't have a ctor or impl block (just trait implementations). +* ts: Add instruction method to state namespace. ## [0.2.0] - 2021-02-08 diff --git a/ts/src/rpc.ts b/ts/src/rpc.ts index c4bc06fdc..a259916b9 100644 --- a/ts/src/rpc.ts +++ b/ts/src/rpc.ts @@ -24,8 +24,6 @@ import { import { IdlError, ProgramError } from "./error"; import Coder, { ACCOUNT_DISCRIMINATOR_SIZE, - SIGHASH_STATE_NAMESPACE, - SIGHASH_GLOBAL_NAMESPACE, accountDiscriminator, stateDiscriminator, accountSize, @@ -68,8 +66,7 @@ export type RpcFn = (...args: any[]) => Promise; /** * Ix is a function to create a `TransactionInstruction` generated from an IDL. */ -export type IxFn = IxProps & ((...args: any[]) => TransactionInstruction); - +export type IxFn = IxProps & ((...args: any[]) => any); type IxProps = { accounts: (ctx: RpcAccounts) => any; }; @@ -220,23 +217,36 @@ export class RpcFactory { // Namespace with all rpc functions. const rpc: Rpcs = {}; + const ix: Ixs = {}; + idl.state.methods.forEach((m: IdlStateMethod) => { - rpc[m.name] = async (...args: any[]): Promise => { - const [ixArgs, ctx] = splitArgsAndCtx(m, [...args]); - const keys = await stateInstructionKeys(programId, provider, m, ctx); - const tx = new Transaction(); - tx.add( - new TransactionInstruction({ - keys: keys.concat( - RpcFactory.accountsArray(ctx.accounts, m.accounts) - ), - programId, - data: coder.instruction.encodeState( - m.name, - toInstruction(m, ...ixArgs) - ), - }) + const accounts = async (accounts: RpcAccounts): Promise => { + const keys = await stateInstructionKeys( + programId, + provider, + m, + accounts ); + return keys.concat(RpcFactory.accountsArray(accounts, m.accounts)); + }; + const ixFn = async (...args: any[]): Promise => { + const [ixArgs, ctx] = splitArgsAndCtx(m, [...args]); + return new TransactionInstruction({ + keys: await accounts(ctx.accounts), + programId, + data: coder.instruction.encodeState( + m.name, + toInstruction(m, ...ixArgs) + ), + }); + }; + ixFn["accounts"] = accounts; + ix[m.name] = ixFn; + + rpc[m.name] = async (...args: any[]): Promise => { + const [_, ctx] = splitArgsAndCtx(m, [...args]); + const tx = new Transaction(); + tx.add(await ix[m.name](...args)); try { const txSig = await provider.send(tx, ctx.signers, ctx.options); return txSig; @@ -249,8 +259,9 @@ export class RpcFactory { } }; }); - state["rpc"] = rpc; + state["rpc"] = rpc; + state["instruction"] = ix; // Calculates the address of the program's global state object account. state["address"] = async (): Promise => programStateAddress(programId); @@ -655,7 +666,7 @@ async function stateInstructionKeys( programId: PublicKey, provider: Provider, m: IdlStateMethod, - ctx: RpcContext + accounts: RpcAccounts ) { if (m.name === "new") { // Ctor `new` method. @@ -689,7 +700,7 @@ async function stateInstructionKeys( }, ]; } else { - validateAccounts(m.accounts, ctx.accounts); + validateAccounts(m.accounts, accounts); return [ { pubkey: await programStateAddress(programId),