Run prettier
This commit is contained in:
parent
263f0a223c
commit
7f9a521d30
|
@ -1,13 +1,12 @@
|
|||
import { Layout } from 'buffer-layout';
|
||||
import * as borsh from '@project-serum/borsh';
|
||||
import { Idl, IdlField, IdlTypeDef } from './idl';
|
||||
import { IdlError } from './error';
|
||||
import { Layout } from "buffer-layout";
|
||||
import * as borsh from "@project-serum/borsh";
|
||||
import { Idl, IdlField, IdlTypeDef } from "./idl";
|
||||
import { IdlError } from "./error";
|
||||
|
||||
/**
|
||||
* Coder provides a facade for encoding and decoding all IDL related objects.
|
||||
*/
|
||||
export default class Coder {
|
||||
|
||||
/**
|
||||
* Instruction coder.
|
||||
*/
|
||||
|
@ -28,7 +27,6 @@ export default class Coder {
|
|||
* Encodes and decodes program instructions.
|
||||
*/
|
||||
class InstructionCoder<T = any> {
|
||||
|
||||
/**
|
||||
* Instruction enum layout.
|
||||
*/
|
||||
|
@ -49,8 +47,10 @@ class InstructionCoder<T = any> {
|
|||
}
|
||||
|
||||
private static parseIxLayout(idl: Idl): Layout {
|
||||
let ixLayouts = idl.instructions.map(ix => {
|
||||
let fieldLayouts = ix.args.map(arg => IdlCoder.fieldLayout(arg, idl.types));
|
||||
let ixLayouts = idl.instructions.map((ix) => {
|
||||
let fieldLayouts = ix.args.map((arg) =>
|
||||
IdlCoder.fieldLayout(arg, idl.types)
|
||||
);
|
||||
return borsh.struct(fieldLayouts, ix.name);
|
||||
});
|
||||
return borsh.rustEnum(ixLayouts);
|
||||
|
@ -61,7 +61,6 @@ class InstructionCoder<T = any> {
|
|||
* Encodes and decodes account objects.
|
||||
*/
|
||||
class AccountsCoder {
|
||||
|
||||
/**
|
||||
* Maps account type identifier to a layout.
|
||||
*/
|
||||
|
@ -72,9 +71,7 @@ class AccountsCoder {
|
|||
this.accountLayouts = new Map();
|
||||
return;
|
||||
}
|
||||
const layouts = idl
|
||||
.accounts
|
||||
.map(acc => {
|
||||
const layouts = idl.accounts.map((acc) => {
|
||||
return [acc.name, IdlCoder.typeDefLayout(acc, idl.types)];
|
||||
});
|
||||
|
||||
|
@ -126,24 +123,30 @@ class IdlCoder {
|
|||
default: {
|
||||
// @ts-ignore
|
||||
if (field.type.option) {
|
||||
return borsh.option(IdlCoder.fieldLayout({
|
||||
return borsh.option(
|
||||
IdlCoder.fieldLayout(
|
||||
{
|
||||
name: undefined,
|
||||
// @ts-ignore
|
||||
type: field.type.option,
|
||||
}, types), field.name)
|
||||
},
|
||||
types
|
||||
),
|
||||
field.name
|
||||
);
|
||||
// @ts-ignore
|
||||
} else if (field.type.defined) {
|
||||
// User defined type.
|
||||
if (types === undefined) {
|
||||
throw new IdlError('User defined types not provided');
|
||||
throw new IdlError("User defined types not provided");
|
||||
}
|
||||
// @ts-ignore
|
||||
const name = field.type.defined;
|
||||
const filtered = types.filter(t => t.name === name);
|
||||
const filtered = types.filter((t) => t.name === name);
|
||||
if (filtered.length !== 1) {
|
||||
console.log(types);
|
||||
console.log(name);
|
||||
throw new IdlError('Type not found');
|
||||
throw new IdlError("Type not found");
|
||||
}
|
||||
return IdlCoder.typeDefLayout(filtered[0], types, name);
|
||||
} else {
|
||||
|
@ -153,16 +156,19 @@ class IdlCoder {
|
|||
}
|
||||
}
|
||||
|
||||
public static typeDefLayout(typeDef: IdlTypeDef, types: IdlTypeDef[], name?: string): Layout {
|
||||
if (typeDef.type.kind === 'struct') {
|
||||
const fieldLayouts = typeDef
|
||||
.type
|
||||
.fields
|
||||
.map(field => IdlCoder.fieldLayout(field, types));
|
||||
public static typeDefLayout(
|
||||
typeDef: IdlTypeDef,
|
||||
types: IdlTypeDef[],
|
||||
name?: string
|
||||
): Layout {
|
||||
if (typeDef.type.kind === "struct") {
|
||||
const fieldLayouts = typeDef.type.fields.map((field) =>
|
||||
IdlCoder.fieldLayout(field, types)
|
||||
);
|
||||
return borsh.struct(fieldLayouts, name);
|
||||
} else {
|
||||
// TODO: enums
|
||||
throw new Error('Enums not yet implemented');
|
||||
throw new Error("Enums not yet implemented");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,24 +4,24 @@ export type Idl = {
|
|||
instructions: IdlInstruction[];
|
||||
accounts?: IdlTypeDef[];
|
||||
types?: IdlTypeDef[];
|
||||
}
|
||||
};
|
||||
|
||||
export type IdlInstruction = {
|
||||
name: string;
|
||||
accounts: IdlAccount[];
|
||||
args: IdlField[];
|
||||
}
|
||||
};
|
||||
|
||||
export type IdlAccount = {
|
||||
name: string;
|
||||
isMut: boolean;
|
||||
isSigner: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export type IdlField = {
|
||||
name: string;
|
||||
type: IdlType;
|
||||
}
|
||||
};
|
||||
|
||||
export type IdlTypeDef = {
|
||||
name: string;
|
||||
|
@ -41,7 +41,8 @@ type IdlTypeDefEnum = {
|
|||
variants: IdlEnumVariant;
|
||||
};
|
||||
|
||||
type IdlType = "bool"
|
||||
type IdlType =
|
||||
| "bool"
|
||||
| "u8"
|
||||
| "i8"
|
||||
| "u16"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Program } from './program';
|
||||
import Coder from './coder';
|
||||
import { Provider } from '@project-serum/common';
|
||||
import { Program } from "./program";
|
||||
import Coder from "./coder";
|
||||
import { Provider } from "@project-serum/common";
|
||||
|
||||
let _provider: Provider | null = null;
|
||||
|
||||
|
@ -12,9 +12,4 @@ function getProvider(): Provider {
|
|||
return _provider;
|
||||
}
|
||||
|
||||
export {
|
||||
Program,
|
||||
Coder,
|
||||
setProvider,
|
||||
getProvider,
|
||||
};
|
||||
export { Program, Coder, setProvider, getProvider, Provider };
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { PublicKey } from '@solana/web3.js';
|
||||
import { RpcFactory } from './rpc';
|
||||
import { Idl } from './idl';
|
||||
import Coder from './coder';
|
||||
import { Rpcs, Ixs, Accounts } from './rpc';
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import { RpcFactory } from "./rpc";
|
||||
import { Idl } from "./idl";
|
||||
import Coder from "./coder";
|
||||
import { Rpcs, Ixs, Accounts } from "./rpc";
|
||||
|
||||
/**
|
||||
* Program is the IDL deserialized representation of a Solana program.
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
import camelCase from 'camelcase';
|
||||
import { Account, PublicKey, ConfirmOptions, Transaction, TransactionSignature, TransactionInstruction } from '@solana/web3.js';
|
||||
import { Idl, IdlInstruction } from './idl';
|
||||
import { IdlError } from './error';
|
||||
import Coder from './coder';
|
||||
import { getProvider } from './';
|
||||
import camelCase from "camelcase";
|
||||
import {
|
||||
Account,
|
||||
PublicKey,
|
||||
ConfirmOptions,
|
||||
Transaction,
|
||||
TransactionSignature,
|
||||
TransactionInstruction,
|
||||
} from "@solana/web3.js";
|
||||
import { Idl, IdlInstruction } from "./idl";
|
||||
import { IdlError } from "./error";
|
||||
import Coder from "./coder";
|
||||
import { getProvider } from "./";
|
||||
|
||||
/**
|
||||
* Rpcs is a dynamically generated object with rpc methods attached.
|
||||
|
@ -57,7 +64,7 @@ type RpcContext = {
|
|||
// Instructions to run *before* the specified rpc instruction.
|
||||
instructions?: TransactionInstruction[];
|
||||
signers?: Array<Account>;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Dynamic object representing a set of accounts given to an rpc/ix invocation.
|
||||
|
@ -65,29 +72,28 @@ type RpcContext = {
|
|||
*/
|
||||
type RpcAccounts = {
|
||||
[key: string]: PublicKey;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* RpcFactory builds an Rpcs object for a given IDL.
|
||||
*/
|
||||
export class RpcFactory {
|
||||
|
||||
/**
|
||||
* build dynamically generates RPC methods.
|
||||
*
|
||||
* @returns an object with all the RPC methods attached.
|
||||
*/
|
||||
public static build(idl: Idl, coder: Coder, programId: PublicKey): [Rpcs, Ixs, Accounts] {
|
||||
public static build(
|
||||
idl: Idl,
|
||||
coder: Coder,
|
||||
programId: PublicKey
|
||||
): [Rpcs, Ixs, Accounts] {
|
||||
const rpcs: Rpcs = {};
|
||||
const ixFns: Ixs = {};
|
||||
const accountFns: Accounts = {};
|
||||
idl.instructions.forEach(idlIx => {
|
||||
idl.instructions.forEach((idlIx) => {
|
||||
// Function to create a raw `TransactionInstruction`.
|
||||
const ix = RpcFactory.buildIx(
|
||||
idlIx,
|
||||
coder,
|
||||
programId,
|
||||
);
|
||||
const ix = RpcFactory.buildIx(idlIx, coder, programId);
|
||||
// Function to invoke an RPC against a cluster.
|
||||
const rpc = RpcFactory.buildRpc(ix);
|
||||
|
||||
|
@ -96,12 +102,12 @@ export class RpcFactory {
|
|||
ixFns[name] = ix;
|
||||
});
|
||||
|
||||
idl.accounts.forEach(idlAccount => {
|
||||
idl.accounts.forEach((idlAccount) => {
|
||||
// todo
|
||||
const accountFn = async (address: PublicKey): Promise<void> => {
|
||||
const provider = getProvider();
|
||||
if (provider === null) {
|
||||
throw new Error('Provider not set');
|
||||
throw new Error("Provider not set");
|
||||
}
|
||||
const accountInfo = await provider.connection.getAccountInfo(address);
|
||||
if (accountInfo === null) {
|
||||
|
@ -116,19 +122,25 @@ export class RpcFactory {
|
|||
return [rpcs, ixFns, accountFns];
|
||||
}
|
||||
|
||||
private static buildIx(idlIx: IdlInstruction, coder: Coder, programId: PublicKey): IxFn {
|
||||
if (idlIx.name === '_inner') {
|
||||
throw new IdlError('the _inner name is reserved');
|
||||
private static buildIx(
|
||||
idlIx: IdlInstruction,
|
||||
coder: Coder,
|
||||
programId: PublicKey
|
||||
): IxFn {
|
||||
if (idlIx.name === "_inner") {
|
||||
throw new IdlError("the _inner name is reserved");
|
||||
}
|
||||
|
||||
const ix = (ctx: RpcContext, ...args: any[]): TransactionInstruction => {
|
||||
validateAccounts(idlIx, ctx.accounts);
|
||||
validateInstruction(idlIx, args)
|
||||
validateInstruction(idlIx, args);
|
||||
|
||||
const keys = idlIx
|
||||
.accounts
|
||||
.map(acc => {
|
||||
return { pubkey: ctx.accounts[acc.name], isWritable: acc.isMut, isSigner: acc.isSigner, }
|
||||
const keys = idlIx.accounts.map((acc) => {
|
||||
return {
|
||||
pubkey: ctx.accounts[acc.name],
|
||||
isWritable: acc.isMut,
|
||||
isSigner: acc.isSigner,
|
||||
};
|
||||
});
|
||||
|
||||
return new TransactionInstruction({
|
||||
|
@ -142,7 +154,10 @@ export class RpcFactory {
|
|||
}
|
||||
|
||||
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();
|
||||
if (ctx.instructions !== undefined) {
|
||||
tx.add(...ctx.instructions);
|
||||
|
@ -150,10 +165,10 @@ export class RpcFactory {
|
|||
tx.add(ixFn(ctx, ...args));
|
||||
const provider = getProvider();
|
||||
if (provider === null) {
|
||||
throw new Error('Provider not found');
|
||||
throw new Error("Provider not found");
|
||||
}
|
||||
|
||||
const txSig = await provider.send(tx, ctx.signers);
|
||||
const txSig = await provider.send(tx, ctx.signers, ctx.options);
|
||||
return txSig;
|
||||
};
|
||||
|
||||
|
@ -163,11 +178,11 @@ export class RpcFactory {
|
|||
|
||||
function toInstruction(idlIx: IdlInstruction, ...args: any[]) {
|
||||
if (idlIx.args.length != args.length) {
|
||||
throw new Error('Invalid argument length');
|
||||
throw new Error("Invalid argument length");
|
||||
}
|
||||
const ix: { [key: string]: any } = {};
|
||||
let idx = 0;
|
||||
idlIx.args.forEach(ixArg => {
|
||||
idlIx.args.forEach((ixArg) => {
|
||||
ix[ixArg.name] = args[idx];
|
||||
idx += 1;
|
||||
});
|
||||
|
@ -176,7 +191,7 @@ function toInstruction(idlIx: IdlInstruction, ...args: any[]) {
|
|||
|
||||
// Throws error if any account required for the `ix` is not given.
|
||||
function validateAccounts(ix: IdlInstruction, accounts: RpcAccounts) {
|
||||
ix.accounts.forEach(acc => {
|
||||
ix.accounts.forEach((acc) => {
|
||||
if (accounts[acc.name] === undefined) {
|
||||
throw new Error(`Invalid arguments: ${acc.name} not provided.`);
|
||||
}
|
||||
|
|
25
ts/test.js
25
ts/test.js
|
@ -1,21 +1,16 @@
|
|||
const web3 = require('@solana/web3.js');
|
||||
const anchor = require('.');
|
||||
anchor.setProvider(anchor.Provider.local());
|
||||
|
||||
function test() {
|
||||
const fs = require('fs');
|
||||
const idl = JSON.parse(fs.readFileSync('../examples/basic/idl.json', 'utf8'));
|
||||
const pid = '9gzNv4hUB1F3jQQNNcZxxjn1bCjgaTCrucDjFh2i8vc6';
|
||||
const idl = JSON.parse(require('fs').readFileSync('../examples/basic/idl.json', 'utf8'));
|
||||
const pid = new web3.PublicKey('9gzNv4hUB1F3jQQNNcZxxjn1bCjgaTCrucDjFh2i8vc6');
|
||||
|
||||
async function test() {
|
||||
const program = new anchor.Program(idl, pid);
|
||||
|
||||
/*
|
||||
const ctx = {
|
||||
authority:
|
||||
};
|
||||
program.rpc.updateLeaf();
|
||||
*/
|
||||
|
||||
console.log('RPCS', program.rpc);
|
||||
console.log('IXS', program.instruction);
|
||||
console.log('Accounts', program.account);
|
||||
const sig = await program.rpc.createRoot(
|
||||
new PublicKey(''),
|
||||
1234,
|
||||
);
|
||||
}
|
||||
|
||||
test();
|
||||
|
|
Loading…
Reference in New Issue