ts: Add instruction method to state namespace

This commit is contained in:
Armani Ferrante 2021-02-10 23:36:02 +08:00
parent 9fb42ce572
commit 627c275e9c
No known key found for this signature in database
GPG Key ID: D597A80BCF8E12B7
2 changed files with 34 additions and 22 deletions

View File

@ -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

View File

@ -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<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;
};
@ -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 [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<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]);
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(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<PublicKey> =>
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),