ts: Improve TypeScript types (#739)
This commit is contained in:
parent
8eec4d3e3d
commit
90df0b1976
|
@ -5,7 +5,7 @@
|
||||||
"main": "dist/cjs/index.js",
|
"main": "dist/cjs/index.js",
|
||||||
"module": "dist/esm/index.js",
|
"module": "dist/esm/index.js",
|
||||||
"license": "(MIT OR Apache-2.0)",
|
"license": "(MIT OR Apache-2.0)",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/cjs/index.d.ts",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
},
|
},
|
||||||
|
@ -58,6 +58,6 @@
|
||||||
"ts-jest": "^26.4.3",
|
"ts-jest": "^26.4.3",
|
||||||
"ts-node": "^9.0.0",
|
"ts-node": "^9.0.0",
|
||||||
"typedoc": "^0.20.36",
|
"typedoc": "^0.20.36",
|
||||||
"typescript": "^4.0.5"
|
"typescript": "^4.4.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,9 @@ export class AccountsCoder {
|
||||||
): Promise<Buffer> {
|
): Promise<Buffer> {
|
||||||
const buffer = Buffer.alloc(1000); // TODO: use a tighter buffer.
|
const buffer = Buffer.alloc(1000); // TODO: use a tighter buffer.
|
||||||
const layout = this.accountLayouts.get(accountName);
|
const layout = this.accountLayouts.get(accountName);
|
||||||
|
if (!layout) {
|
||||||
|
throw new Error(`Unknown account: ${accountName}`);
|
||||||
|
}
|
||||||
const len = layout.encode(account, buffer);
|
const len = layout.encode(account, buffer);
|
||||||
let accountData = buffer.slice(0, len);
|
let accountData = buffer.slice(0, len);
|
||||||
let discriminator = await accountDiscriminator(accountName);
|
let discriminator = await accountDiscriminator(accountName);
|
||||||
|
@ -45,6 +48,9 @@ export class AccountsCoder {
|
||||||
// Chop off the discriminator before decoding.
|
// Chop off the discriminator before decoding.
|
||||||
const data = ix.slice(8);
|
const data = ix.slice(8);
|
||||||
const layout = this.accountLayouts.get(accountName);
|
const layout = this.accountLayouts.get(accountName);
|
||||||
|
if (!layout) {
|
||||||
|
throw new Error(`Unknown account: ${accountName}`);
|
||||||
|
}
|
||||||
return layout.decode(data);
|
return layout.decode(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,29 +3,21 @@ import { sha256 } from "js-sha256";
|
||||||
import { Idl, IdlField, IdlTypeDef, IdlEnumVariant, IdlType } from "../idl";
|
import { Idl, IdlField, IdlTypeDef, IdlEnumVariant, IdlType } from "../idl";
|
||||||
import { IdlError } from "../error";
|
import { IdlError } from "../error";
|
||||||
|
|
||||||
export function accountSize(
|
export function accountSize(idl: Idl, idlAccount: IdlTypeDef): number {
|
||||||
idl: Idl,
|
|
||||||
idlAccount: IdlTypeDef
|
|
||||||
): number | undefined {
|
|
||||||
if (idlAccount.type.kind === "enum") {
|
if (idlAccount.type.kind === "enum") {
|
||||||
let variantSizes = idlAccount.type.variants.map(
|
let variantSizes = idlAccount.type.variants.map(
|
||||||
(variant: IdlEnumVariant) => {
|
(variant: IdlEnumVariant) => {
|
||||||
if (variant.fields === undefined) {
|
if (variant.fields === undefined) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (
|
return variant.fields
|
||||||
variant.fields
|
.map((f: IdlField | IdlType) => {
|
||||||
// @ts-ignore
|
if (!(typeof f === "object" && "name" in f)) {
|
||||||
.map((f: IdlField | IdlType) => {
|
throw new Error("Tuple enum variants not yet implemented.");
|
||||||
// @ts-ignore
|
}
|
||||||
if (f.name === undefined) {
|
return typeSize(idl, f.type);
|
||||||
throw new Error("Tuple enum variants not yet implemented.");
|
})
|
||||||
}
|
.reduce((a: number, b: number) => a + b);
|
||||||
// @ts-ignore
|
|
||||||
return typeSize(idl, f.type);
|
|
||||||
})
|
|
||||||
.reduce((a: number, b: number) => a + b)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return Math.max(...variantSizes) + 1;
|
return Math.max(...variantSizes) + 1;
|
||||||
|
@ -71,19 +63,14 @@ function typeSize(idl: Idl, ty: IdlType): number {
|
||||||
case "publicKey":
|
case "publicKey":
|
||||||
return 32;
|
return 32;
|
||||||
default:
|
default:
|
||||||
// @ts-ignore
|
if ("vec" in ty) {
|
||||||
if (ty.vec !== undefined) {
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
if ("option" in ty) {
|
||||||
if (ty.option !== undefined) {
|
|
||||||
// @ts-ignore
|
|
||||||
return 1 + typeSize(idl, ty.option);
|
return 1 + typeSize(idl, ty.option);
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
if ("defined" in ty) {
|
||||||
if (ty.defined !== undefined) {
|
const filtered = idl.types?.filter((t) => t.name === ty.defined) ?? [];
|
||||||
// @ts-ignore
|
|
||||||
const filtered = idl.types.filter((t) => t.name === ty.defined);
|
|
||||||
if (filtered.length !== 1) {
|
if (filtered.length !== 1) {
|
||||||
throw new IdlError(`Type not found: ${JSON.stringify(ty)}`);
|
throw new IdlError(`Type not found: ${JSON.stringify(ty)}`);
|
||||||
}
|
}
|
||||||
|
@ -91,13 +78,9 @@ function typeSize(idl: Idl, ty: IdlType): number {
|
||||||
|
|
||||||
return accountSize(idl, typeDef);
|
return accountSize(idl, typeDef);
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
if ("array" in ty) {
|
||||||
if (ty.array !== undefined) {
|
|
||||||
// @ts-ignore
|
|
||||||
let arrayTy = ty.array[0];
|
let arrayTy = ty.array[0];
|
||||||
// @ts-ignore
|
|
||||||
let arraySize = ty.array[1];
|
let arraySize = ty.array[1];
|
||||||
// @ts-ignore
|
|
||||||
return typeSize(idl, arrayTy) * arraySize;
|
return typeSize(idl, arrayTy) * arraySize;
|
||||||
}
|
}
|
||||||
throw new Error(`Invalid type ${JSON.stringify(ty)}`);
|
throw new Error(`Invalid type ${JSON.stringify(ty)}`);
|
||||||
|
|
|
@ -46,7 +46,7 @@ export class EventCoder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public decode(log: string): Event | null {
|
public decode<T = Record<string, unknown>>(log: string): Event<T> | null {
|
||||||
let logArr: Buffer;
|
let logArr: Buffer;
|
||||||
// This will throw if log length is not a multiple of 4.
|
// This will throw if log length is not a multiple of 4.
|
||||||
try {
|
try {
|
||||||
|
@ -63,7 +63,10 @@ export class EventCoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
const layout = this.layouts.get(eventName);
|
const layout = this.layouts.get(eventName);
|
||||||
const data = layout.decode(logArr.slice(8));
|
if (!layout) {
|
||||||
|
throw new Error(`Unknown event: ${eventName}`);
|
||||||
|
}
|
||||||
|
const data = layout.decode(logArr.slice(8)) as T;
|
||||||
return { data, name: eventName };
|
return { data, name: eventName };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,10 @@ import { IdlField, IdlTypeDef, IdlEnumVariant, IdlType } from "../idl";
|
||||||
import { IdlError } from "../error";
|
import { IdlError } from "../error";
|
||||||
|
|
||||||
export class IdlCoder {
|
export class IdlCoder {
|
||||||
public static fieldLayout(field: IdlField, types?: IdlTypeDef[]): Layout {
|
public static fieldLayout(
|
||||||
|
field: { name?: string } & Pick<IdlField, "type">,
|
||||||
|
types?: IdlTypeDef[]
|
||||||
|
): Layout {
|
||||||
const fieldName =
|
const fieldName =
|
||||||
field.name !== undefined ? camelCase(field.name) : undefined;
|
field.name !== undefined ? camelCase(field.name) : undefined;
|
||||||
switch (field.type) {
|
switch (field.type) {
|
||||||
|
@ -52,8 +55,7 @@ export class IdlCoder {
|
||||||
return borsh.publicKey(fieldName);
|
return borsh.publicKey(fieldName);
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
// @ts-ignore
|
if ("vec" in field.type) {
|
||||||
if (field.type.vec) {
|
|
||||||
return borsh.vec(
|
return borsh.vec(
|
||||||
IdlCoder.fieldLayout(
|
IdlCoder.fieldLayout(
|
||||||
{
|
{
|
||||||
|
@ -65,36 +67,30 @@ export class IdlCoder {
|
||||||
),
|
),
|
||||||
fieldName
|
fieldName
|
||||||
);
|
);
|
||||||
// @ts-ignore
|
} else if ("option" in field.type) {
|
||||||
} else if (field.type.option) {
|
|
||||||
return borsh.option(
|
return borsh.option(
|
||||||
IdlCoder.fieldLayout(
|
IdlCoder.fieldLayout(
|
||||||
{
|
{
|
||||||
name: undefined,
|
name: undefined,
|
||||||
// @ts-ignore
|
|
||||||
type: field.type.option,
|
type: field.type.option,
|
||||||
},
|
},
|
||||||
types
|
types
|
||||||
),
|
),
|
||||||
fieldName
|
fieldName
|
||||||
);
|
);
|
||||||
// @ts-ignore
|
} else if ("defined" in field.type) {
|
||||||
} else if (field.type.defined) {
|
const defined = field.type.defined;
|
||||||
// User defined type.
|
// User defined type.
|
||||||
if (types === undefined) {
|
if (types === undefined) {
|
||||||
throw new IdlError("User defined types not provided");
|
throw new IdlError("User defined types not provided");
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
const filtered = types.filter((t) => t.name === defined);
|
||||||
const filtered = types.filter((t) => t.name === field.type.defined);
|
|
||||||
if (filtered.length !== 1) {
|
if (filtered.length !== 1) {
|
||||||
throw new IdlError(`Type not found: ${JSON.stringify(field)}`);
|
throw new IdlError(`Type not found: ${JSON.stringify(field)}`);
|
||||||
}
|
}
|
||||||
return IdlCoder.typeDefLayout(filtered[0], types, fieldName);
|
return IdlCoder.typeDefLayout(filtered[0], types, fieldName);
|
||||||
// @ts-ignore
|
} else if ("array" in field.type) {
|
||||||
} else if (field.type.array) {
|
|
||||||
// @ts-ignore
|
|
||||||
let arrayTy = field.type.array[0];
|
let arrayTy = field.type.array[0];
|
||||||
// @ts-ignore
|
|
||||||
let arrayLen = field.type.array[1];
|
let arrayLen = field.type.array[1];
|
||||||
let innerLayout = IdlCoder.fieldLayout(
|
let innerLayout = IdlCoder.fieldLayout(
|
||||||
{
|
{
|
||||||
|
@ -113,7 +109,7 @@ export class IdlCoder {
|
||||||
|
|
||||||
public static typeDefLayout(
|
public static typeDefLayout(
|
||||||
typeDef: IdlTypeDef,
|
typeDef: IdlTypeDef,
|
||||||
types: IdlTypeDef[],
|
types: IdlTypeDef[] = [],
|
||||||
name?: string
|
name?: string
|
||||||
): Layout {
|
): Layout {
|
||||||
if (typeDef.type.kind === "struct") {
|
if (typeDef.type.kind === "struct") {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
IdlTypeDef,
|
IdlTypeDef,
|
||||||
IdlAccount,
|
IdlAccount,
|
||||||
IdlAccountItem,
|
IdlAccountItem,
|
||||||
|
IdlTypeDefTyStruct,
|
||||||
} from "../idl";
|
} from "../idl";
|
||||||
import { IdlCoder } from "./idl";
|
import { IdlCoder } from "./idl";
|
||||||
import { sighash } from "./common";
|
import { sighash } from "./common";
|
||||||
|
@ -77,7 +78,11 @@ export class InstructionCoder {
|
||||||
private _encode(nameSpace: string, ixName: string, ix: any): Buffer {
|
private _encode(nameSpace: string, ixName: string, ix: any): Buffer {
|
||||||
const buffer = Buffer.alloc(1000); // TODO: use a tighter buffer.
|
const buffer = Buffer.alloc(1000); // TODO: use a tighter buffer.
|
||||||
const methodName = camelCase(ixName);
|
const methodName = camelCase(ixName);
|
||||||
const len = this.ixLayout.get(methodName).encode(ix, buffer);
|
const layout = this.ixLayout.get(methodName);
|
||||||
|
if (!layout) {
|
||||||
|
throw new Error(`Unknown method: ${methodName}`);
|
||||||
|
}
|
||||||
|
const len = layout.encode(ix, buffer);
|
||||||
const data = buffer.slice(0, len);
|
const data = buffer.slice(0, len);
|
||||||
return Buffer.concat([sighash(nameSpace, ixName), data]);
|
return Buffer.concat([sighash(nameSpace, ixName), data]);
|
||||||
}
|
}
|
||||||
|
@ -215,21 +220,20 @@ class InstructionFormatter {
|
||||||
return idlType as string;
|
return idlType as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
if ("vec" in idlType) {
|
||||||
if (idlType.vec) {
|
|
||||||
// @ts-ignore
|
|
||||||
return `Vec<${this.formatIdlType(idlType.vec)}>`;
|
return `Vec<${this.formatIdlType(idlType.vec)}>`;
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
if ("option" in idlType) {
|
||||||
if (idlType.option) {
|
|
||||||
// @ts-ignore
|
|
||||||
return `Option<${this.formatIdlType(idlType.option)}>`;
|
return `Option<${this.formatIdlType(idlType.option)}>`;
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
if ("defined" in idlType) {
|
||||||
if (idlType.defined) {
|
|
||||||
// @ts-ignore
|
|
||||||
return idlType.defined;
|
return idlType.defined;
|
||||||
}
|
}
|
||||||
|
if ("array" in idlType) {
|
||||||
|
return `Array<${idlType.array[0]}; ${idlType.array[1]}>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Unknown IDL type: ${idlType}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static formatIdlData(
|
private static formatIdlData(
|
||||||
|
@ -296,9 +300,10 @@ class InstructionFormatter {
|
||||||
types: IdlTypeDef[]
|
types: IdlTypeDef[]
|
||||||
): string {
|
): string {
|
||||||
if (typeDef.type.kind === "struct") {
|
if (typeDef.type.kind === "struct") {
|
||||||
|
const struct: IdlTypeDefTyStruct = typeDef.type;
|
||||||
const fields = Object.keys(data)
|
const fields = Object.keys(data)
|
||||||
.map((k) => {
|
.map((k) => {
|
||||||
const f = typeDef.type.fields.filter((f) => f.name === k)[0];
|
const f = struct.fields.filter((f) => f.name === k)[0];
|
||||||
if (f === undefined) {
|
if (f === undefined) {
|
||||||
throw new Error("Unable to find type");
|
throw new Error("Unable to find type");
|
||||||
}
|
}
|
||||||
|
@ -314,12 +319,13 @@ class InstructionFormatter {
|
||||||
}
|
}
|
||||||
// Struct enum.
|
// Struct enum.
|
||||||
if (typeDef.type.variants[0].name) {
|
if (typeDef.type.variants[0].name) {
|
||||||
|
const variants = typeDef.type.variants;
|
||||||
const variant = Object.keys(data)[0];
|
const variant = Object.keys(data)[0];
|
||||||
const enumType = data[variant];
|
const enumType = data[variant];
|
||||||
const namedFields = Object.keys(enumType)
|
const namedFields = Object.keys(enumType)
|
||||||
.map((f) => {
|
.map((f) => {
|
||||||
const fieldData = enumType[f];
|
const fieldData = enumType[f];
|
||||||
const idlField = typeDef.type.variants[variant]?.filter(
|
const idlField = variants[variant]?.filter(
|
||||||
(v: IdlField) => v.name === f
|
(v: IdlField) => v.name === f
|
||||||
)[0];
|
)[0];
|
||||||
if (idlField === undefined) {
|
if (idlField === undefined) {
|
||||||
|
|
|
@ -16,8 +16,9 @@ export class TypesCoder {
|
||||||
this.layouts = new Map();
|
this.layouts = new Map();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const layouts = idl.types.map((acc) => {
|
const types = idl.types;
|
||||||
return [acc.name, IdlCoder.typeDefLayout(acc, idl.types)];
|
const layouts = types.map((acc) => {
|
||||||
|
return [acc.name, IdlCoder.typeDefLayout(acc, types)];
|
||||||
});
|
});
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -27,12 +28,18 @@ export class TypesCoder {
|
||||||
public encode<T = any>(accountName: string, account: T): Buffer {
|
public encode<T = any>(accountName: string, account: T): Buffer {
|
||||||
const buffer = Buffer.alloc(1000); // TODO: use a tighter buffer.
|
const buffer = Buffer.alloc(1000); // TODO: use a tighter buffer.
|
||||||
const layout = this.layouts.get(accountName);
|
const layout = this.layouts.get(accountName);
|
||||||
|
if (!layout) {
|
||||||
|
throw new Error(`Unknown account type: ${accountName}`);
|
||||||
|
}
|
||||||
const len = layout.encode(account, buffer);
|
const len = layout.encode(account, buffer);
|
||||||
return buffer.slice(0, len);
|
return buffer.slice(0, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
public decode<T = any>(accountName: string, ix: Buffer): T {
|
public decode<T = any>(accountName: string, ix: Buffer): T {
|
||||||
const layout = this.layouts.get(accountName);
|
const layout = this.layouts.get(accountName);
|
||||||
|
if (!layout) {
|
||||||
|
throw new Error(`Unknown account type: ${accountName}`);
|
||||||
|
}
|
||||||
return layout.decode(ix);
|
return layout.decode(ix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
export class IdlError extends Error {}
|
export class IdlError extends Error {
|
||||||
|
constructor(message: string) {
|
||||||
|
super(message);
|
||||||
|
this.name = "IdlError";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// An error from a user defined program.
|
// An error from a user defined program.
|
||||||
export class ProgramError extends Error {
|
export class ProgramError extends Error {
|
||||||
|
|
|
@ -60,12 +60,18 @@ export type IdlTypeDef = {
|
||||||
type: IdlTypeDefTy;
|
type: IdlTypeDefTy;
|
||||||
};
|
};
|
||||||
|
|
||||||
type IdlTypeDefTy = {
|
export type IdlTypeDefTyStruct = {
|
||||||
kind: "struct" | "enum";
|
kind: "struct";
|
||||||
fields?: IdlTypeDefStruct;
|
fields: IdlTypeDefStruct;
|
||||||
variants?: IdlEnumVariant[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type IdlTypeDefTyEnum = {
|
||||||
|
kind: "enum";
|
||||||
|
variants: IdlEnumVariant[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type IdlTypeDefTy = IdlTypeDefTyEnum | IdlTypeDefTyStruct;
|
||||||
|
|
||||||
type IdlTypeDefStruct = Array<IdlField>;
|
type IdlTypeDefStruct = Array<IdlField>;
|
||||||
|
|
||||||
export type IdlType =
|
export type IdlType =
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import BN from "bn.js";
|
export { default as BN } from "bn.js";
|
||||||
import * as web3 from "@solana/web3.js";
|
export * as web3 from "@solana/web3.js";
|
||||||
import Provider, {
|
export {
|
||||||
|
default as Provider,
|
||||||
getProvider,
|
getProvider,
|
||||||
setProvider,
|
setProvider,
|
||||||
NodeWallet as Wallet,
|
NodeWallet as Wallet,
|
||||||
} from "./provider";
|
} from "./provider";
|
||||||
import Coder, {
|
export {
|
||||||
|
default as Coder,
|
||||||
InstructionCoder,
|
InstructionCoder,
|
||||||
EventCoder,
|
EventCoder,
|
||||||
StateCoder,
|
StateCoder,
|
||||||
|
@ -13,15 +15,15 @@ import Coder, {
|
||||||
AccountsCoder,
|
AccountsCoder,
|
||||||
} from "./coder";
|
} from "./coder";
|
||||||
|
|
||||||
import { ProgramError } from "./error";
|
export * from "./error";
|
||||||
import { Instruction } from "./coder/instruction";
|
export { Instruction } from "./coder/instruction";
|
||||||
import { Idl } from "./idl";
|
export { Idl } from "./idl";
|
||||||
import workspace from "./workspace";
|
export { default as workspace } from "./workspace";
|
||||||
import * as utils from "./utils";
|
export * as utils from "./utils";
|
||||||
import { Program } from "./program";
|
export { Program } from "./program";
|
||||||
import { Address } from "./program/common";
|
export { Address } from "./program/common";
|
||||||
import { Event } from "./program/event";
|
export { Event } from "./program/event";
|
||||||
import {
|
export {
|
||||||
ProgramAccount,
|
ProgramAccount,
|
||||||
AccountNamespace,
|
AccountNamespace,
|
||||||
AccountClient,
|
AccountClient,
|
||||||
|
@ -35,43 +37,5 @@ import {
|
||||||
InstructionNamespace,
|
InstructionNamespace,
|
||||||
InstructionFn,
|
InstructionFn,
|
||||||
} from "./program/namespace";
|
} from "./program/namespace";
|
||||||
import { Context, Accounts } from "./program/context";
|
export { Context, Accounts } from "./program/context";
|
||||||
import { EventParser } from "./program/event";
|
export { EventParser } from "./program/event";
|
||||||
|
|
||||||
export {
|
|
||||||
workspace,
|
|
||||||
Program,
|
|
||||||
AccountNamespace,
|
|
||||||
AccountClient,
|
|
||||||
StateClient,
|
|
||||||
RpcNamespace,
|
|
||||||
RpcFn,
|
|
||||||
SimulateNamespace,
|
|
||||||
SimulateFn,
|
|
||||||
TransactionNamespace,
|
|
||||||
TransactionFn,
|
|
||||||
InstructionNamespace,
|
|
||||||
InstructionFn,
|
|
||||||
ProgramAccount,
|
|
||||||
Context,
|
|
||||||
Accounts,
|
|
||||||
Coder,
|
|
||||||
InstructionCoder,
|
|
||||||
EventCoder,
|
|
||||||
StateCoder,
|
|
||||||
TypesCoder,
|
|
||||||
AccountsCoder,
|
|
||||||
Event,
|
|
||||||
Instruction,
|
|
||||||
setProvider,
|
|
||||||
getProvider,
|
|
||||||
Provider,
|
|
||||||
BN,
|
|
||||||
web3,
|
|
||||||
Idl,
|
|
||||||
utils,
|
|
||||||
Wallet,
|
|
||||||
Address,
|
|
||||||
EventParser,
|
|
||||||
ProgramError,
|
|
||||||
};
|
|
||||||
|
|
|
@ -40,13 +40,11 @@ export function toInstruction(
|
||||||
// Throws error if any account required for the `ix` is not given.
|
// Throws error if any account required for the `ix` is not given.
|
||||||
export function validateAccounts(
|
export function validateAccounts(
|
||||||
ixAccounts: IdlAccountItem[],
|
ixAccounts: IdlAccountItem[],
|
||||||
accounts: Accounts
|
accounts: Accounts = {}
|
||||||
) {
|
) {
|
||||||
ixAccounts.forEach((acc) => {
|
ixAccounts.forEach((acc) => {
|
||||||
// @ts-ignore
|
if ("accounts" in acc) {
|
||||||
if (acc.accounts !== undefined) {
|
validateAccounts(acc.accounts, accounts[acc.name] as Accounts);
|
||||||
// @ts-ignore
|
|
||||||
validateAccounts(acc.accounts, accounts[acc.name]);
|
|
||||||
} else {
|
} else {
|
||||||
if (accounts[acc.name] === undefined) {
|
if (accounts[acc.name] === undefined) {
|
||||||
throw new Error(`Invalid arguments: ${acc.name} not provided.`);
|
throw new Error(`Invalid arguments: ${acc.name} not provided.`);
|
||||||
|
|
|
@ -6,9 +6,9 @@ import Provider from "../provider";
|
||||||
const LOG_START_INDEX = "Program log: ".length;
|
const LOG_START_INDEX = "Program log: ".length;
|
||||||
|
|
||||||
// Deserialized event.
|
// Deserialized event.
|
||||||
export type Event = {
|
export type Event<T = Record<string, unknown>> = {
|
||||||
name: string;
|
name: string;
|
||||||
data: Object;
|
data: T;
|
||||||
};
|
};
|
||||||
|
|
||||||
type EventCallback = (event: any, slot: number) => void;
|
type EventCallback = (event: any, slot: number) => void;
|
||||||
|
@ -71,7 +71,7 @@ export class EventManager {
|
||||||
}
|
}
|
||||||
this._eventListeners.set(
|
this._eventListeners.set(
|
||||||
eventName,
|
eventName,
|
||||||
this._eventListeners.get(eventName).concat(listener)
|
(this._eventListeners.get(eventName) ?? []).concat(listener)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Store the callback into the listener map.
|
// Store the callback into the listener map.
|
||||||
|
@ -93,8 +93,11 @@ export class EventManager {
|
||||||
const allListeners = this._eventListeners.get(event.name);
|
const allListeners = this._eventListeners.get(event.name);
|
||||||
if (allListeners) {
|
if (allListeners) {
|
||||||
allListeners.forEach((listener) => {
|
allListeners.forEach((listener) => {
|
||||||
const [, callback] = this._eventCallbacks.get(listener);
|
const listenerCb = this._eventCallbacks.get(listener);
|
||||||
callback(event.data, ctx.slot);
|
if (listenerCb) {
|
||||||
|
const [, callback] = listenerCb;
|
||||||
|
callback(event.data, ctx.slot);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -128,10 +131,12 @@ export class EventManager {
|
||||||
// Kill the websocket connection if all listeners have been removed.
|
// Kill the websocket connection if all listeners have been removed.
|
||||||
if (this._eventCallbacks.size == 0) {
|
if (this._eventCallbacks.size == 0) {
|
||||||
assert.ok(this._eventListeners.size === 0);
|
assert.ok(this._eventListeners.size === 0);
|
||||||
await this._provider.connection.removeOnLogsListener(
|
if (this._onLogsSubscriptionId !== undefined) {
|
||||||
this._onLogsSubscriptionId
|
await this._provider.connection.removeOnLogsListener(
|
||||||
);
|
this._onLogsSubscriptionId
|
||||||
this._onLogsSubscriptionId = undefined;
|
);
|
||||||
|
this._onLogsSubscriptionId = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,7 +248,10 @@ class ExecutionContext {
|
||||||
constructor(log: string) {
|
constructor(log: string) {
|
||||||
// Assumes the first log in every transaction is an `invoke` log from the
|
// Assumes the first log in every transaction is an `invoke` log from the
|
||||||
// runtime.
|
// runtime.
|
||||||
const program = /^Program (.*) invoke.*$/g.exec(log)[1];
|
const program = /^Program (.*) invoke.*$/g.exec(log)?.[1];
|
||||||
|
if (!program) {
|
||||||
|
throw new Error(`Could not find program invocation log line`);
|
||||||
|
}
|
||||||
this.stack = [program];
|
this.stack = [program];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,7 @@ export class Program {
|
||||||
* one can use this to send transactions and read accounts for the state
|
* one can use this to send transactions and read accounts for the state
|
||||||
* abstraction.
|
* abstraction.
|
||||||
*/
|
*/
|
||||||
readonly state: StateClient;
|
readonly state?: StateClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Address of the program.
|
* Address of the program.
|
||||||
|
@ -210,14 +210,6 @@ export class Program {
|
||||||
}
|
}
|
||||||
private _programId: PublicKey;
|
private _programId: PublicKey;
|
||||||
|
|
||||||
/**
|
|
||||||
* IDL defining the program's interface.
|
|
||||||
*/
|
|
||||||
public get idl(): Idl {
|
|
||||||
return this._idl;
|
|
||||||
}
|
|
||||||
private _idl: Idl;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Coder for serializing requests.
|
* Coder for serializing requests.
|
||||||
*/
|
*/
|
||||||
|
@ -226,14 +218,6 @@ export class Program {
|
||||||
}
|
}
|
||||||
private _coder: Coder;
|
private _coder: Coder;
|
||||||
|
|
||||||
/**
|
|
||||||
* Wallet and network provider.
|
|
||||||
*/
|
|
||||||
public get provider(): Provider {
|
|
||||||
return this._provider;
|
|
||||||
}
|
|
||||||
private _provider: Provider;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles event subscriptions.
|
* Handles event subscriptions.
|
||||||
*/
|
*/
|
||||||
|
@ -245,19 +229,23 @@ export class Program {
|
||||||
* @param provider The network and wallet context to use. If not provided
|
* @param provider The network and wallet context to use. If not provided
|
||||||
* then uses [[getProvider]].
|
* then uses [[getProvider]].
|
||||||
*/
|
*/
|
||||||
public constructor(idl: Idl, programId: Address, provider?: Provider) {
|
public constructor(
|
||||||
|
/**
|
||||||
|
* IDL defining the program's interface.
|
||||||
|
*/
|
||||||
|
public readonly idl: Idl,
|
||||||
|
programId: Address,
|
||||||
|
/**
|
||||||
|
* Wallet and network provider.
|
||||||
|
*/
|
||||||
|
public readonly provider: Provider = getProvider()
|
||||||
|
) {
|
||||||
programId = translateAddress(programId);
|
programId = translateAddress(programId);
|
||||||
|
|
||||||
// Fields.
|
// Fields.
|
||||||
this._idl = idl;
|
|
||||||
this._programId = programId;
|
this._programId = programId;
|
||||||
this._provider = provider ?? getProvider();
|
|
||||||
this._coder = new Coder(idl);
|
this._coder = new Coder(idl);
|
||||||
this._events = new EventManager(
|
this._events = new EventManager(this._programId, provider, this._coder);
|
||||||
this._programId,
|
|
||||||
this._provider,
|
|
||||||
this._coder
|
|
||||||
);
|
|
||||||
|
|
||||||
// Dynamic namespaces.
|
// Dynamic namespaces.
|
||||||
const [
|
const [
|
||||||
|
@ -267,7 +255,7 @@ export class Program {
|
||||||
account,
|
account,
|
||||||
simulate,
|
simulate,
|
||||||
state,
|
state,
|
||||||
] = NamespaceFactory.build(idl, this._coder, programId, this._provider);
|
] = NamespaceFactory.build(idl, this._coder, programId, provider);
|
||||||
this.rpc = rpc;
|
this.rpc = rpc;
|
||||||
this.instruction = instruction;
|
this.instruction = instruction;
|
||||||
this.transaction = transaction;
|
this.transaction = transaction;
|
||||||
|
@ -285,10 +273,16 @@ export class Program {
|
||||||
* @param programId The on-chain address of the program.
|
* @param programId The on-chain address of the program.
|
||||||
* @param provider The network and wallet context.
|
* @param provider The network and wallet context.
|
||||||
*/
|
*/
|
||||||
public static async at(address: Address, provider?: Provider) {
|
public static async at(
|
||||||
|
address: Address,
|
||||||
|
provider?: Provider
|
||||||
|
): Promise<Program> {
|
||||||
const programId = translateAddress(address);
|
const programId = translateAddress(address);
|
||||||
|
|
||||||
const idl = await Program.fetchIdl(programId, provider);
|
const idl = await Program.fetchIdl(programId, provider);
|
||||||
|
if (!idl) {
|
||||||
|
throw new Error(`IDL not found for program: ${address.toString()}`);
|
||||||
|
}
|
||||||
return new Program(idl, programId, provider);
|
return new Program(idl, programId, provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,12 +295,18 @@ export class Program {
|
||||||
* @param programId The on-chain address of the program.
|
* @param programId The on-chain address of the program.
|
||||||
* @param provider The network and wallet context.
|
* @param provider The network and wallet context.
|
||||||
*/
|
*/
|
||||||
public static async fetchIdl(address: Address, provider?: Provider) {
|
public static async fetchIdl(
|
||||||
|
address: Address,
|
||||||
|
provider?: Provider
|
||||||
|
): Promise<Idl | null> {
|
||||||
provider = provider ?? getProvider();
|
provider = provider ?? getProvider();
|
||||||
const programId = translateAddress(address);
|
const programId = translateAddress(address);
|
||||||
|
|
||||||
const idlAddr = await idlAddress(programId);
|
const idlAddr = await idlAddress(programId);
|
||||||
const accountInfo = await provider.connection.getAccountInfo(idlAddr);
|
const accountInfo = await provider.connection.getAccountInfo(idlAddr);
|
||||||
|
if (!accountInfo) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
// Chop off account discriminator.
|
// Chop off account discriminator.
|
||||||
let idlAccount = decodeIdlAccount(accountInfo.data.slice(8));
|
let idlAccount = decodeIdlAccount(accountInfo.data.slice(8));
|
||||||
const inflatedIdl = inflate(idlAccount.data);
|
const inflatedIdl = inflate(idlAccount.data);
|
||||||
|
|
|
@ -28,7 +28,7 @@ export default class AccountFactory {
|
||||||
): AccountNamespace {
|
): AccountNamespace {
|
||||||
const accountFns: AccountNamespace = {};
|
const accountFns: AccountNamespace = {};
|
||||||
|
|
||||||
idl.accounts.forEach((idlAccount) => {
|
idl.accounts?.forEach((idlAccount) => {
|
||||||
const name = camelCase(idlAccount.name);
|
const name = camelCase(idlAccount.name);
|
||||||
accountFns[name] = new AccountClient(
|
accountFns[name] = new AccountClient(
|
||||||
idl,
|
idl,
|
||||||
|
@ -113,7 +113,8 @@ export class AccountClient {
|
||||||
this._programId = programId;
|
this._programId = programId;
|
||||||
this._provider = provider ?? getProvider();
|
this._provider = provider ?? getProvider();
|
||||||
this._coder = coder ?? new Coder(idl);
|
this._coder = coder ?? new Coder(idl);
|
||||||
this._size = ACCOUNT_DISCRIMINATOR_SIZE + accountSize(idl, idlAccount);
|
this._size =
|
||||||
|
ACCOUNT_DISCRIMINATOR_SIZE + (accountSize(idl, idlAccount) ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,8 +178,9 @@ export class AccountClient {
|
||||||
* changes.
|
* changes.
|
||||||
*/
|
*/
|
||||||
subscribe(address: Address, commitment?: Commitment): EventEmitter {
|
subscribe(address: Address, commitment?: Commitment): EventEmitter {
|
||||||
if (subscriptions.get(address.toString())) {
|
const sub = subscriptions.get(address.toString());
|
||||||
return subscriptions.get(address.toString()).ee;
|
if (sub) {
|
||||||
|
return sub.ee;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ee = new EventEmitter();
|
const ee = new EventEmitter();
|
||||||
|
|
|
@ -34,7 +34,7 @@ export default class NamespaceFactory {
|
||||||
TransactionNamespace,
|
TransactionNamespace,
|
||||||
AccountNamespace,
|
AccountNamespace,
|
||||||
SimulateNamespace,
|
SimulateNamespace,
|
||||||
StateClient
|
StateClient | undefined
|
||||||
] {
|
] {
|
||||||
const rpc: RpcNamespace = {};
|
const rpc: RpcNamespace = {};
|
||||||
const instruction: InstructionNamespace = {};
|
const instruction: InstructionNamespace = {};
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
|
import {
|
||||||
|
AccountMeta,
|
||||||
|
PublicKey,
|
||||||
|
TransactionInstruction,
|
||||||
|
} from "@solana/web3.js";
|
||||||
import { IdlAccount, IdlInstruction, IdlAccountItem } from "../../idl";
|
import { IdlAccount, IdlInstruction, IdlAccountItem } from "../../idl";
|
||||||
import { IdlError } from "../../error";
|
import { IdlError } from "../../error";
|
||||||
import {
|
import {
|
||||||
|
@ -41,19 +45,22 @@ export default class InstructionNamespaceFactory {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Utility fn for ordering the accounts for this instruction.
|
// Utility fn for ordering the accounts for this instruction.
|
||||||
ix["accounts"] = (accs: Accounts) => {
|
ix["accounts"] = (accs: Accounts = {}) => {
|
||||||
return InstructionNamespaceFactory.accountsArray(accs, idlIx.accounts);
|
return InstructionNamespaceFactory.accountsArray(accs, idlIx.accounts);
|
||||||
};
|
};
|
||||||
|
|
||||||
return ix;
|
return ix;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static accountsArray(ctx: Accounts, accounts: IdlAccountItem[]): any {
|
public static accountsArray(
|
||||||
|
ctx: Accounts,
|
||||||
|
accounts: IdlAccountItem[]
|
||||||
|
): AccountMeta[] {
|
||||||
return accounts
|
return accounts
|
||||||
.map((acc: IdlAccountItem) => {
|
.map((acc: IdlAccountItem) => {
|
||||||
// Nested accounts.
|
// Nested accounts.
|
||||||
// @ts-ignore
|
const nestedAccounts: IdlAccountItem[] | undefined =
|
||||||
const nestedAccounts: IdlAccountItem[] | undefined = acc.accounts;
|
"accounts" in acc ? acc.accounts : undefined;
|
||||||
if (nestedAccounts !== undefined) {
|
if (nestedAccounts !== undefined) {
|
||||||
const rpcAccs = ctx[acc.name] as Accounts;
|
const rpcAccs = ctx[acc.name] as Accounts;
|
||||||
return InstructionNamespaceFactory.accountsArray(
|
return InstructionNamespaceFactory.accountsArray(
|
||||||
|
@ -113,7 +120,7 @@ export interface InstructionNamespace {
|
||||||
*/
|
*/
|
||||||
export type InstructionFn = IxProps & ((...args: any[]) => any);
|
export type InstructionFn = IxProps & ((...args: any[]) => any);
|
||||||
type IxProps = {
|
type IxProps = {
|
||||||
accounts: (ctx: Accounts) => any;
|
accounts: (ctx: Accounts) => AccountMeta[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type InstructionEncodeFn = (ixName: string, ix: any) => Buffer;
|
export type InstructionEncodeFn = (ixName: string, ix: any) => Buffer;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { TransactionSignature } from "@solana/web3.js";
|
import { TransactionSignature } from "@solana/web3.js";
|
||||||
import Provider from "../../provider";
|
import Provider from "../../provider";
|
||||||
import { IdlInstruction } from "../../idl";
|
import { IdlInstruction } from "../../idl";
|
||||||
import { splitArgsAndCtx } from "../context";
|
import { Context, splitArgsAndCtx } from "../context";
|
||||||
import { TransactionFn } from "./transaction";
|
import { TransactionFn } from "./transaction";
|
||||||
import { ProgramError } from "../../error";
|
import { ProgramError } from "../../error";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
import { PublicKey } from "@solana/web3.js";
|
import {
|
||||||
|
PublicKey,
|
||||||
|
RpcResponseAndContext,
|
||||||
|
SimulatedTransactionResponse,
|
||||||
|
} from "@solana/web3.js";
|
||||||
import Provider from "../../provider";
|
import Provider from "../../provider";
|
||||||
import { IdlInstruction } from "../../idl";
|
import { IdlInstruction } from "../../idl";
|
||||||
import { splitArgsAndCtx } from "../context";
|
import { splitArgsAndCtx } from "../context";
|
||||||
|
@ -21,7 +25,9 @@ export default class SimulateFactory {
|
||||||
const simulate = async (...args: any[]): Promise<SimulateResponse> => {
|
const simulate = async (...args: any[]): Promise<SimulateResponse> => {
|
||||||
const tx = txFn(...args);
|
const tx = txFn(...args);
|
||||||
const [, ctx] = splitArgsAndCtx(idlIx, [...args]);
|
const [, ctx] = splitArgsAndCtx(idlIx, [...args]);
|
||||||
let resp = undefined;
|
let resp:
|
||||||
|
| RpcResponseAndContext<SimulatedTransactionResponse>
|
||||||
|
| undefined = undefined;
|
||||||
try {
|
try {
|
||||||
resp = await provider.simulate(tx, ctx.signers, ctx.options);
|
resp = await provider.simulate(tx, ctx.signers, ctx.options);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -43,7 +49,7 @@ export default class SimulateFactory {
|
||||||
throw new Error("Simulated logs not found");
|
throw new Error("Simulated logs not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
const events = [];
|
const events: Event[] = [];
|
||||||
if (idl.events) {
|
if (idl.events) {
|
||||||
let parser = new EventParser(programId, coder);
|
let parser = new EventParser(programId, coder);
|
||||||
parser.parseLogs(logs, (event) => {
|
parser.parseLogs(logs, (event) => {
|
||||||
|
|
|
@ -56,37 +56,25 @@ export class StateClient {
|
||||||
}
|
}
|
||||||
private _programId: PublicKey;
|
private _programId: PublicKey;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the client's wallet and network provider.
|
|
||||||
*/
|
|
||||||
get provider(): Provider {
|
|
||||||
return this._provider;
|
|
||||||
}
|
|
||||||
private _provider: Provider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the coder.
|
|
||||||
*/
|
|
||||||
get coder(): Coder {
|
|
||||||
return this._coder;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _address: PublicKey;
|
private _address: PublicKey;
|
||||||
private _coder: Coder;
|
|
||||||
private _idl: Idl;
|
private _idl: Idl;
|
||||||
private _sub: Subscription | null;
|
private _sub: Subscription | null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
idl: Idl,
|
idl: Idl,
|
||||||
programId: PublicKey,
|
programId: PublicKey,
|
||||||
provider?: Provider,
|
/**
|
||||||
coder?: Coder
|
* Returns the client's wallet and network provider.
|
||||||
|
*/
|
||||||
|
public readonly provider: Provider = getProvider(),
|
||||||
|
/**
|
||||||
|
* Returns the coder.
|
||||||
|
*/
|
||||||
|
public readonly coder: Coder = new Coder(idl)
|
||||||
) {
|
) {
|
||||||
this._idl = idl;
|
this._idl = idl;
|
||||||
this._programId = programId;
|
this._programId = programId;
|
||||||
this._address = programStateAddress(programId);
|
this._address = programStateAddress(programId);
|
||||||
this._provider = provider ?? getProvider();
|
|
||||||
this._coder = coder ?? new Coder(idl);
|
|
||||||
this._sub = null;
|
this._sub = null;
|
||||||
|
|
||||||
// Build namespaces.
|
// Build namespaces.
|
||||||
|
@ -99,7 +87,7 @@ export class StateClient {
|
||||||
let transaction: TransactionNamespace = {};
|
let transaction: TransactionNamespace = {};
|
||||||
let rpc: RpcNamespace = {};
|
let rpc: RpcNamespace = {};
|
||||||
|
|
||||||
idl.state.methods.forEach((m: IdlStateMethod) => {
|
idl.state?.methods.forEach((m: IdlStateMethod) => {
|
||||||
// Build instruction method.
|
// Build instruction method.
|
||||||
const ixItem = InstructionNamespaceFactory.build(
|
const ixItem = InstructionNamespaceFactory.build(
|
||||||
m,
|
m,
|
||||||
|
@ -147,9 +135,11 @@ export class StateClient {
|
||||||
throw new Error(`Account does not exist ${addr.toString()}`);
|
throw new Error(`Account does not exist ${addr.toString()}`);
|
||||||
}
|
}
|
||||||
// Assert the account discriminator is correct.
|
// Assert the account discriminator is correct.
|
||||||
const expectedDiscriminator = await stateDiscriminator(
|
const state = this._idl.state;
|
||||||
this._idl.state.struct.name
|
if (!state) {
|
||||||
);
|
throw new Error("State is not specified in IDL.");
|
||||||
|
}
|
||||||
|
const expectedDiscriminator = await stateDiscriminator(state.struct.name);
|
||||||
if (expectedDiscriminator.compare(accountInfo.data.slice(0, 8))) {
|
if (expectedDiscriminator.compare(accountInfo.data.slice(0, 8))) {
|
||||||
throw new Error("Invalid account discriminator");
|
throw new Error("Invalid account discriminator");
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,9 @@ export default class Provider {
|
||||||
* (This api is for Node only.)
|
* (This api is for Node only.)
|
||||||
*/
|
*/
|
||||||
static env(): Provider {
|
static env(): Provider {
|
||||||
if (isBrowser) return;
|
if (isBrowser) {
|
||||||
|
throw new Error(`Provider env is not available on browser.`);
|
||||||
|
}
|
||||||
|
|
||||||
const process = require("process");
|
const process = require("process");
|
||||||
const url = process.env.ANCHOR_PROVIDER_URL;
|
const url = process.env.ANCHOR_PROVIDER_URL;
|
||||||
|
@ -102,7 +104,7 @@ export default class Provider {
|
||||||
|
|
||||||
await this.wallet.signTransaction(tx);
|
await this.wallet.signTransaction(tx);
|
||||||
signers
|
signers
|
||||||
.filter((s) => s !== undefined)
|
.filter((s): s is Signer => s !== undefined)
|
||||||
.forEach((kp) => {
|
.forEach((kp) => {
|
||||||
tx.partialSign(kp);
|
tx.partialSign(kp);
|
||||||
});
|
});
|
||||||
|
@ -144,7 +146,7 @@ export default class Provider {
|
||||||
tx.recentBlockhash = blockhash.blockhash;
|
tx.recentBlockhash = blockhash.blockhash;
|
||||||
|
|
||||||
signers
|
signers
|
||||||
.filter((s) => s !== undefined)
|
.filter((s): s is Signer => s !== undefined)
|
||||||
.forEach((kp) => {
|
.forEach((kp) => {
|
||||||
tx.partialSign(kp);
|
tx.partialSign(kp);
|
||||||
});
|
});
|
||||||
|
@ -154,7 +156,7 @@ export default class Provider {
|
||||||
|
|
||||||
const signedTxs = await this.wallet.signAllTransactions(txs);
|
const signedTxs = await this.wallet.signAllTransactions(txs);
|
||||||
|
|
||||||
const sigs = [];
|
const sigs: TransactionSignature[] = [];
|
||||||
|
|
||||||
for (let k = 0; k < txs.length; k += 1) {
|
for (let k = 0; k < txs.length; k += 1) {
|
||||||
const tx = signedTxs[k];
|
const tx = signedTxs[k];
|
||||||
|
@ -178,14 +180,11 @@ export default class Provider {
|
||||||
async simulate(
|
async simulate(
|
||||||
tx: Transaction,
|
tx: Transaction,
|
||||||
signers?: Array<Signer | undefined>,
|
signers?: Array<Signer | undefined>,
|
||||||
opts?: ConfirmOptions
|
opts: ConfirmOptions = this.opts
|
||||||
): Promise<RpcResponseAndContext<SimulatedTransactionResponse>> {
|
): Promise<RpcResponseAndContext<SimulatedTransactionResponse>> {
|
||||||
if (signers === undefined) {
|
if (signers === undefined) {
|
||||||
signers = [];
|
signers = [];
|
||||||
}
|
}
|
||||||
if (opts === undefined) {
|
|
||||||
opts = this.opts;
|
|
||||||
}
|
|
||||||
|
|
||||||
tx.feePayer = this.wallet.publicKey;
|
tx.feePayer = this.wallet.publicKey;
|
||||||
tx.recentBlockhash = (
|
tx.recentBlockhash = (
|
||||||
|
@ -196,7 +195,7 @@ export default class Provider {
|
||||||
|
|
||||||
await this.wallet.signTransaction(tx);
|
await this.wallet.signTransaction(tx);
|
||||||
signers
|
signers
|
||||||
.filter((s) => s !== undefined)
|
.filter((s): s is Signer => s !== undefined)
|
||||||
.forEach((kp) => {
|
.forEach((kp) => {
|
||||||
tx.partialSign(kp);
|
tx.partialSign(kp);
|
||||||
});
|
});
|
||||||
|
@ -204,7 +203,7 @@ export default class Provider {
|
||||||
return await simulateTransaction(
|
return await simulateTransaction(
|
||||||
this.connection,
|
this.connection,
|
||||||
tx,
|
tx,
|
||||||
opts.commitment ?? this.opts.commitment
|
opts.commitment ?? this.opts.commitment ?? "recent"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,9 @@ function attachWorkspaceOverride(
|
||||||
if (typeof entry !== "string" && entry.idl) {
|
if (typeof entry !== "string" && entry.idl) {
|
||||||
idl = JSON.parse(require("fs").readFileSync(entry.idl, "utf-8"));
|
idl = JSON.parse(require("fs").readFileSync(entry.idl, "utf-8"));
|
||||||
}
|
}
|
||||||
|
if (!idl) {
|
||||||
|
throw new Error(`Error loading workspace IDL for ${programName}`);
|
||||||
|
}
|
||||||
workspaceCache[wsProgramName] = new Program(idl, overrideAddress);
|
workspaceCache[wsProgramName] = new Program(idl, overrideAddress);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
"outDir": "dist/esm/",
|
"outDir": "dist/esm/",
|
||||||
"rootDir": "./src",
|
"rootDir": "./src",
|
||||||
"declarationDir": "dist",
|
|
||||||
|
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
|
@ -16,6 +15,7 @@
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"typeRoots": ["types/", "node_modules/@types"],
|
"typeRoots": ["types/", "node_modules/@types"],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@solana/web3.js": ["./node_modules/@solana/web3.js/lib"]
|
"@solana/web3.js": ["./node_modules/@solana/web3.js/lib"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5303,10 +5303,10 @@ typedoc@^0.20.36:
|
||||||
shiki "^0.9.3"
|
shiki "^0.9.3"
|
||||||
typedoc-default-themes "^0.12.10"
|
typedoc-default-themes "^0.12.10"
|
||||||
|
|
||||||
typescript@^4.0.5:
|
typescript@^4.4.3:
|
||||||
version "4.1.3"
|
version "4.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324"
|
||||||
integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==
|
integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==
|
||||||
|
|
||||||
uglify-js@^3.1.4:
|
uglify-js@^3.1.4:
|
||||||
version "3.13.5"
|
version "3.13.5"
|
||||||
|
|
Loading…
Reference in New Issue