Accounts dynamically attached to program client

This commit is contained in:
armaniferrante 2021-01-01 15:10:26 -08:00
parent 4d42da0146
commit 263f0a223c
No known key found for this signature in database
GPG Key ID: 58BEF301E91F7828
6 changed files with 63 additions and 14 deletions

View File

@ -38,7 +38,7 @@ mod example {
let leaf = &mut ctx.accounts.leaf; let leaf = &mut ctx.accounts.leaf;
leaf.account.data = data; leaf.account.data = data;
if let Some(custom) = custom { if let Some(custom) = custom {
leaf.custom = custom; leaf.account.custom = custom;
} }
Ok(()) Ok(())
} }

View File

@ -1,6 +1,7 @@
//! DSL syntax tokens. //! DSL syntax tokens.
pub mod codegen; pub mod codegen;
#[cfg(target_arch = "x86")]
pub mod idl; pub mod idl;
pub mod parser; pub mod parser;

View File

@ -1,3 +1,4 @@
pub mod anchor; pub mod anchor;
#[cfg(target_arch = "x86")]
pub mod file; pub mod file;
pub mod program; pub mod program;

View File

@ -2,7 +2,7 @@ import { PublicKey } from '@solana/web3.js';
import { RpcFactory } from './rpc'; import { RpcFactory } from './rpc';
import { Idl } from './idl'; import { Idl } from './idl';
import Coder from './coder'; import Coder from './coder';
import { Rpcs, Ixs } from './rpc'; import { Rpcs, Ixs, Accounts } from './rpc';
/** /**
* Program is the IDL deserialized representation of a Solana program. * Program is the IDL deserialized representation of a Solana program.
@ -24,6 +24,11 @@ export class Program {
*/ */
readonly rpc: Rpcs; readonly rpc: Rpcs;
/**
* Async functions to fetch deserialized program accounts from a cluster.
*/
readonly account: Accounts;
/** /**
* Functions to build `TransactionInstruction` objects. * Functions to build `TransactionInstruction` objects.
*/ */
@ -37,8 +42,9 @@ export class Program {
const coder = new Coder(idl); const coder = new Coder(idl);
// Build the dynamic RPC functions. // Build the dynamic RPC functions.
const [rpcs, ixs] = RpcFactory.build(idl, coder, programId); const [rpcs, ixs, accounts] = RpcFactory.build(idl, coder, programId);
this.rpc = rpcs; this.rpc = rpcs;
this.instruction = ixs; this.instruction = ixs;
this.account = accounts;
} }
} }

View File

@ -9,25 +9,38 @@ import { getProvider } from './';
* Rpcs is a dynamically generated object with rpc methods attached. * Rpcs is a dynamically generated object with rpc methods attached.
*/ */
export interface Rpcs { export interface Rpcs {
[key: string]: Rpc; [key: string]: RpcFn;
} }
/** /**
* Ixs is a dynamically generated object with ix functions attached. * Ixs is a dynamically generated object with ix functions attached.
*/ */
export interface Ixs { export interface Ixs {
[key: string]: Ix; [key: string]: IxFn;
} }
/** /**
* Rpc is a single rpc method. * Accounts is a dynamically generated object to fetch any given account
* of a program.
*/ */
export type Rpc = (ctx: RpcContext, ...args: any[]) => Promise<any>; export interface Accounts {
[key: string]: AccountFn;
}
/**
* RpcFn is a single rpc method.
*/
export type RpcFn = (ctx: RpcContext, ...args: any[]) => Promise<any>;
/** /**
* Ix is a function to create a `TransactionInstruction`. * Ix is a function to create a `TransactionInstruction`.
*/ */
export type Ix = (ctx: RpcContext, ...args: any[]) => TransactionInstruction; export type IxFn = (ctx: RpcContext, ...args: any[]) => TransactionInstruction;
/**
* Account is a function returning a deserialized account, given an address.
*/
export type AccountFn = (address: PublicKey) => any;
/** /**
* Options for an RPC invocation. * Options for an RPC invocation.
@ -64,10 +77,11 @@ export class RpcFactory {
* *
* @returns an object with all the RPC methods attached. * @returns an object with all the RPC methods attached.
*/ */
public static build(idl: Idl, coder: Coder, programId: PublicKey): [Rpcs, Ixs] { public static build(idl: Idl, coder: Coder, programId: PublicKey): [Rpcs, Ixs, Accounts] {
const rpcs: Rpcs = {}; const rpcs: Rpcs = {};
const ixFns: Ixs = {}; const ixFns: Ixs = {};
idl.instructions.forEach(idlIx=> { const accountFns: Accounts = {};
idl.instructions.forEach(idlIx => {
// Function to create a raw `TransactionInstruction`. // Function to create a raw `TransactionInstruction`.
const ix = RpcFactory.buildIx( const ix = RpcFactory.buildIx(
idlIx, idlIx,
@ -81,10 +95,28 @@ export class RpcFactory {
rpcs[name] = rpc; rpcs[name] = rpc;
ixFns[name] = ix; ixFns[name] = ix;
}); });
return [rpcs, ixFns];
idl.accounts.forEach(idlAccount => {
// todo
const accountFn = async (address: PublicKey): Promise<void> => {
const provider = getProvider();
if (provider === null) {
throw new Error('Provider not set');
}
const accountInfo = await provider.connection.getAccountInfo(address);
if (accountInfo === null) {
throw new Error(`Entity does not exist ${address}`);
}
coder.accounts.decode(idlAccount.name, accountInfo.data);
};
const name = camelCase(idlAccount.name);
accountFns[name] = accountFn;
});
return [rpcs, ixFns, accountFns];
} }
private static buildIx(idlIx: IdlInstruction, coder: Coder, programId: PublicKey): Ix { private static buildIx(idlIx: IdlInstruction, coder: Coder, programId: PublicKey): IxFn {
if (idlIx.name === '_inner') { if (idlIx.name === '_inner') {
throw new IdlError('the _inner name is reserved'); throw new IdlError('the _inner name is reserved');
} }
@ -109,7 +141,7 @@ export class RpcFactory {
return ix; return ix;
} }
private static buildRpc(ixFn: Ix): Rpc { private static buildRpc(ixFn: IxFn): RpcFn {
const rpc = async (ctx: RpcContext, ...args: any[]): Promise<TransactionSignature> => { const rpc = async (ctx: RpcContext, ...args: any[]): Promise<TransactionSignature> => {
const tx = new Transaction(); const tx = new Transaction();
if (ctx.instructions !== undefined) { if (ctx.instructions !== undefined) {

View File

@ -3,10 +3,19 @@ const anchor = require('.');
function test() { function test() {
const fs = require('fs'); const fs = require('fs');
const idl = JSON.parse(fs.readFileSync('../examples/basic/idl.json', 'utf8')); const idl = JSON.parse(fs.readFileSync('../examples/basic/idl.json', 'utf8'));
const program = new anchor.Program(idl); const pid = '9gzNv4hUB1F3jQQNNcZxxjn1bCjgaTCrucDjFh2i8vc6';
const program = new anchor.Program(idl, pid);
/*
const ctx = {
authority:
};
program.rpc.updateLeaf();
*/
console.log('RPCS', program.rpc); console.log('RPCS', program.rpc);
console.log('IXS', program.instruction); console.log('IXS', program.instruction);
console.log('Accounts', program.account);
} }
test(); test();