Skip to content

Commit

Permalink
ts: Add instruction method to state namespace
Browse files Browse the repository at this point in the history
  • Loading branch information
armaniferrante committed Feb 10, 2021
1 parent 9fb42ce commit 627c275
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 21 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
53 changes: 32 additions & 21 deletions ts/src/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ import {
import { IdlError, ProgramError } from "./error";
import Coder, {
ACCOUNT_DISCRIMINATOR_SIZE,
SIGHASH_STATE_NAMESPACE,
SIGHASH_GLOBAL_NAMESPACE,
accountDiscriminator,
stateDiscriminator,
accountSize,
Expand Down Expand Up @@ -68,8 +66,7 @@ export type RpcFn = (...args: any[]) => Promise<TransactionSignature>;
/**
* 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;
};
Expand Down Expand Up @@ -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<TransactionSignature> => {
const accounts = async (accounts: RpcAccounts): Promise<any> => {
const keys = await stateInstructionKeys(
programId,
provider,
m,
accounts
);
return keys.concat(RpcFactory.accountsArray(accounts, m.accounts));
};
const ixFn = async (...args: any[]): Promise<TransactionInstruction> => {
const [ixArgs, ctx] = splitArgsAndCtx(m, [...args]);
const keys = await stateInstructionKeys(programId, provider, m, ctx);
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<TransactionSignature> => {
const [_, ctx] = splitArgsAndCtx(m, [...args]);
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)
),
})
);
tx.add(await ix[m.name](...args));
try {
const txSig = await provider.send(tx, ctx.signers, ctx.options);
return txSig;
Expand All @@ -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<PublicKey> =>
programStateAddress(programId);
Expand Down Expand Up @@ -655,7 +666,7 @@ async function stateInstructionKeys(
programId: PublicKey,
provider: Provider,
m: IdlStateMethod,
ctx: RpcContext
accounts: RpcAccounts
) {
if (m.name === "new") {
// Ctor `new` method.
Expand Down Expand Up @@ -689,7 +700,7 @@ async function stateInstructionKeys(
},
];
} else {
validateAccounts(m.accounts, ctx.accounts);
validateAccounts(m.accounts, accounts);
return [
{
pubkey: await programStateAddress(programId),
Expand Down

0 comments on commit 627c275

Please sign in to comment.