Accounts dynamically attached to program client
This commit is contained in:
parent
4d42da0146
commit
263f0a223c
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,9 +77,10 @@ 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 = {};
|
||||||
|
const accountFns: Accounts = {};
|
||||||
idl.instructions.forEach(idlIx => {
|
idl.instructions.forEach(idlIx => {
|
||||||
// Function to create a raw `TransactionInstruction`.
|
// Function to create a raw `TransactionInstruction`.
|
||||||
const ix = RpcFactory.buildIx(
|
const ix = RpcFactory.buildIx(
|
||||||
|
@ -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) {
|
||||||
|
|
11
ts/test.js
11
ts/test.js
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue