ts: Improve TypeScript types (#739)

This commit is contained in:
Ian Macalinao 2021-09-16 13:42:11 -07:00 committed by GitHub
parent 8eec4d3e3d
commit 90df0b1976
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 209 additions and 220 deletions

View File

@ -5,7 +5,7 @@
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"license": "(MIT OR Apache-2.0)",
"types": "dist/index.d.ts",
"types": "dist/cjs/index.d.ts",
"publishConfig": {
"access": "public"
},
@ -58,6 +58,6 @@
"ts-jest": "^26.4.3",
"ts-node": "^9.0.0",
"typedoc": "^0.20.36",
"typescript": "^4.0.5"
"typescript": "^4.4.3"
}
}

View File

@ -35,6 +35,9 @@ export class AccountsCoder {
): Promise<Buffer> {
const buffer = Buffer.alloc(1000); // TODO: use a tighter buffer.
const layout = this.accountLayouts.get(accountName);
if (!layout) {
throw new Error(`Unknown account: ${accountName}`);
}
const len = layout.encode(account, buffer);
let accountData = buffer.slice(0, len);
let discriminator = await accountDiscriminator(accountName);
@ -45,6 +48,9 @@ export class AccountsCoder {
// Chop off the discriminator before decoding.
const data = ix.slice(8);
const layout = this.accountLayouts.get(accountName);
if (!layout) {
throw new Error(`Unknown account: ${accountName}`);
}
return layout.decode(data);
}
}

View File

@ -3,29 +3,21 @@ import { sha256 } from "js-sha256";
import { Idl, IdlField, IdlTypeDef, IdlEnumVariant, IdlType } from "../idl";
import { IdlError } from "../error";
export function accountSize(
idl: Idl,
idlAccount: IdlTypeDef
): number | undefined {
export function accountSize(idl: Idl, idlAccount: IdlTypeDef): number {
if (idlAccount.type.kind === "enum") {
let variantSizes = idlAccount.type.variants.map(
(variant: IdlEnumVariant) => {
if (variant.fields === undefined) {
return 0;
}
return (
variant.fields
// @ts-ignore
.map((f: IdlField | IdlType) => {
// @ts-ignore
if (f.name === undefined) {
throw new Error("Tuple enum variants not yet implemented.");
}
// @ts-ignore
return typeSize(idl, f.type);
})
.reduce((a: number, b: number) => a + b)
);
return variant.fields
.map((f: IdlField | IdlType) => {
if (!(typeof f === "object" && "name" in f)) {
throw new Error("Tuple enum variants not yet implemented.");
}
return typeSize(idl, f.type);
})
.reduce((a: number, b: number) => a + b);
}
);
return Math.max(...variantSizes) + 1;
@ -71,19 +63,14 @@ function typeSize(idl: Idl, ty: IdlType): number {
case "publicKey":
return 32;
default:
// @ts-ignore
if (ty.vec !== undefined) {
if ("vec" in ty) {
return 1;
}
// @ts-ignore
if (ty.option !== undefined) {
// @ts-ignore
if ("option" in ty) {
return 1 + typeSize(idl, ty.option);
}
// @ts-ignore
if (ty.defined !== undefined) {
// @ts-ignore
const filtered = idl.types.filter((t) => t.name === ty.defined);
if ("defined" in ty) {
const filtered = idl.types?.filter((t) => t.name === ty.defined) ?? [];
if (filtered.length !== 1) {
throw new IdlError(`Type not found: ${JSON.stringify(ty)}`);
}
@ -91,13 +78,9 @@ function typeSize(idl: Idl, ty: IdlType): number {
return accountSize(idl, typeDef);
}
// @ts-ignore
if (ty.array !== undefined) {
// @ts-ignore
if ("array" in ty) {
let arrayTy = ty.array[0];
// @ts-ignore
let arraySize = ty.array[1];
// @ts-ignore
return typeSize(idl, arrayTy) * arraySize;
}
throw new Error(`Invalid type ${JSON.stringify(ty)}`);

View File

@ -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;
// This will throw if log length is not a multiple of 4.
try {
@ -63,7 +63,10 @@ export class EventCoder {
}
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 };
}
}

View File

@ -5,7 +5,10 @@ import { IdlField, IdlTypeDef, IdlEnumVariant, IdlType } from "../idl";
import { IdlError } from "../error";
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 =
field.name !== undefined ? camelCase(field.name) : undefined;
switch (field.type) {
@ -52,8 +55,7 @@ export class IdlCoder {
return borsh.publicKey(fieldName);
}
default: {
// @ts-ignore
if (field.type.vec) {
if ("vec" in field.type) {
return borsh.vec(
IdlCoder.fieldLayout(
{
@ -65,36 +67,30 @@ export class IdlCoder {
),
fieldName
);
// @ts-ignore
} else if (field.type.option) {
} else if ("option" in field.type) {
return borsh.option(
IdlCoder.fieldLayout(
{
name: undefined,
// @ts-ignore
type: field.type.option,
},
types
),
fieldName
);
// @ts-ignore
} else if (field.type.defined) {
} else if ("defined" in field.type) {
const defined = field.type.defined;
// User defined type.
if (types === undefined) {
throw new IdlError("User defined types not provided");
}
// @ts-ignore
const filtered = types.filter((t) => t.name === field.type.defined);
const filtered = types.filter((t) => t.name === defined);
if (filtered.length !== 1) {
throw new IdlError(`Type not found: ${JSON.stringify(field)}`);
}
return IdlCoder.typeDefLayout(filtered[0], types, fieldName);
// @ts-ignore
} else if (field.type.array) {
// @ts-ignore
} else if ("array" in field.type) {
let arrayTy = field.type.array[0];
// @ts-ignore
let arrayLen = field.type.array[1];
let innerLayout = IdlCoder.fieldLayout(
{
@ -113,7 +109,7 @@ export class IdlCoder {
public static typeDefLayout(
typeDef: IdlTypeDef,
types: IdlTypeDef[],
types: IdlTypeDef[] = [],
name?: string
): Layout {
if (typeDef.type.kind === "struct") {

View File

@ -10,6 +10,7 @@ import {
IdlTypeDef,
IdlAccount,
IdlAccountItem,
IdlTypeDefTyStruct,
} from "../idl";
import { IdlCoder } from "./idl";
import { sighash } from "./common";
@ -77,7 +78,11 @@ export class InstructionCoder {
private _encode(nameSpace: string, ixName: string, ix: any): Buffer {
const buffer = Buffer.alloc(1000); // TODO: use a tighter buffer.
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);
return Buffer.concat([sighash(nameSpace, ixName), data]);
}
@ -215,21 +220,20 @@ class InstructionFormatter {
return idlType as string;
}
// @ts-ignore
if (idlType.vec) {
// @ts-ignore
if ("vec" in idlType) {
return `Vec<${this.formatIdlType(idlType.vec)}>`;
}
// @ts-ignore
if (idlType.option) {
// @ts-ignore
if ("option" in idlType) {
return `Option<${this.formatIdlType(idlType.option)}>`;
}
// @ts-ignore
if (idlType.defined) {
// @ts-ignore
if ("defined" in idlType) {
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(
@ -296,9 +300,10 @@ class InstructionFormatter {
types: IdlTypeDef[]
): string {
if (typeDef.type.kind === "struct") {
const struct: IdlTypeDefTyStruct = typeDef.type;
const fields = Object.keys(data)
.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) {
throw new Error("Unable to find type");
}
@ -314,12 +319,13 @@ class InstructionFormatter {
}
// Struct enum.
if (typeDef.type.variants[0].name) {
const variants = typeDef.type.variants;
const variant = Object.keys(data)[0];
const enumType = data[variant];
const namedFields = Object.keys(enumType)
.map((f) => {
const fieldData = enumType[f];
const idlField = typeDef.type.variants[variant]?.filter(
const idlField = variants[variant]?.filter(
(v: IdlField) => v.name === f
)[0];
if (idlField === undefined) {

View File

@ -16,8 +16,9 @@ export class TypesCoder {
this.layouts = new Map();
return;
}
const layouts = idl.types.map((acc) => {
return [acc.name, IdlCoder.typeDefLayout(acc, idl.types)];
const types = idl.types;
const layouts = types.map((acc) => {
return [acc.name, IdlCoder.typeDefLayout(acc, types)];
});
// @ts-ignore
@ -27,12 +28,18 @@ export class TypesCoder {
public encode<T = any>(accountName: string, account: T): Buffer {
const buffer = Buffer.alloc(1000); // TODO: use a tighter buffer.
const layout = this.layouts.get(accountName);
if (!layout) {
throw new Error(`Unknown account type: ${accountName}`);
}
const len = layout.encode(account, buffer);
return buffer.slice(0, len);
}
public decode<T = any>(accountName: string, ix: Buffer): T {
const layout = this.layouts.get(accountName);
if (!layout) {
throw new Error(`Unknown account type: ${accountName}`);
}
return layout.decode(ix);
}
}

View File

@ -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.
export class ProgramError extends Error {

View File

@ -60,12 +60,18 @@ export type IdlTypeDef = {
type: IdlTypeDefTy;
};
type IdlTypeDefTy = {
kind: "struct" | "enum";
fields?: IdlTypeDefStruct;
variants?: IdlEnumVariant[];
export type IdlTypeDefTyStruct = {
kind: "struct";
fields: IdlTypeDefStruct;
};
export type IdlTypeDefTyEnum = {
kind: "enum";
variants: IdlEnumVariant[];
};
type IdlTypeDefTy = IdlTypeDefTyEnum | IdlTypeDefTyStruct;
type IdlTypeDefStruct = Array<IdlField>;
export type IdlType =

View File

@ -1,11 +1,13 @@
import BN from "bn.js";
import * as web3 from "@solana/web3.js";
import Provider, {
export { default as BN } from "bn.js";
export * as web3 from "@solana/web3.js";
export {
default as Provider,
getProvider,
setProvider,
NodeWallet as Wallet,
} from "./provider";
import Coder, {
export {
default as Coder,
InstructionCoder,
EventCoder,
StateCoder,
@ -13,15 +15,15 @@ import Coder, {
AccountsCoder,
} from "./coder";
import { ProgramError } from "./error";
import { Instruction } from "./coder/instruction";
import { Idl } from "./idl";
import workspace from "./workspace";
import * as utils from "./utils";
import { Program } from "./program";
import { Address } from "./program/common";
import { Event } from "./program/event";
import {
export * from "./error";
export { Instruction } from "./coder/instruction";
export { Idl } from "./idl";
export { default as workspace } from "./workspace";
export * as utils from "./utils";
export { Program } from "./program";
export { Address } from "./program/common";
export { Event } from "./program/event";
export {
ProgramAccount,
AccountNamespace,
AccountClient,
@ -35,43 +37,5 @@ import {
InstructionNamespace,
InstructionFn,
} from "./program/namespace";
import { Context, Accounts } from "./program/context";
import { 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,
};
export { Context, Accounts } from "./program/context";
export { EventParser } from "./program/event";

View File

@ -40,13 +40,11 @@ export function toInstruction(
// Throws error if any account required for the `ix` is not given.
export function validateAccounts(
ixAccounts: IdlAccountItem[],
accounts: Accounts
accounts: Accounts = {}
) {
ixAccounts.forEach((acc) => {
// @ts-ignore
if (acc.accounts !== undefined) {
// @ts-ignore
validateAccounts(acc.accounts, accounts[acc.name]);
if ("accounts" in acc) {
validateAccounts(acc.accounts, accounts[acc.name] as Accounts);
} else {
if (accounts[acc.name] === undefined) {
throw new Error(`Invalid arguments: ${acc.name} not provided.`);

View File

@ -6,9 +6,9 @@ import Provider from "../provider";
const LOG_START_INDEX = "Program log: ".length;
// Deserialized event.
export type Event = {
export type Event<T = Record<string, unknown>> = {
name: string;
data: Object;
data: T;
};
type EventCallback = (event: any, slot: number) => void;
@ -71,7 +71,7 @@ export class EventManager {
}
this._eventListeners.set(
eventName,
this._eventListeners.get(eventName).concat(listener)
(this._eventListeners.get(eventName) ?? []).concat(listener)
);
// Store the callback into the listener map.
@ -93,8 +93,11 @@ export class EventManager {
const allListeners = this._eventListeners.get(event.name);
if (allListeners) {
allListeners.forEach((listener) => {
const [, callback] = this._eventCallbacks.get(listener);
callback(event.data, ctx.slot);
const listenerCb = this._eventCallbacks.get(listener);
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.
if (this._eventCallbacks.size == 0) {
assert.ok(this._eventListeners.size === 0);
await this._provider.connection.removeOnLogsListener(
this._onLogsSubscriptionId
);
this._onLogsSubscriptionId = undefined;
if (this._onLogsSubscriptionId !== undefined) {
await this._provider.connection.removeOnLogsListener(
this._onLogsSubscriptionId
);
this._onLogsSubscriptionId = undefined;
}
}
}
}
@ -243,7 +248,10 @@ class ExecutionContext {
constructor(log: string) {
// Assumes the first log in every transaction is an `invoke` log from the
// 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];
}

View File

@ -200,7 +200,7 @@ export class Program {
* one can use this to send transactions and read accounts for the state
* abstraction.
*/
readonly state: StateClient;
readonly state?: StateClient;
/**
* Address of the program.
@ -210,14 +210,6 @@ export class Program {
}
private _programId: PublicKey;
/**
* IDL defining the program's interface.
*/
public get idl(): Idl {
return this._idl;
}
private _idl: Idl;
/**
* Coder for serializing requests.
*/
@ -226,14 +218,6 @@ export class Program {
}
private _coder: Coder;
/**
* Wallet and network provider.
*/
public get provider(): Provider {
return this._provider;
}
private _provider: Provider;
/**
* Handles event subscriptions.
*/
@ -245,19 +229,23 @@ export class Program {
* @param provider The network and wallet context to use. If not provided
* 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);
// Fields.
this._idl = idl;
this._programId = programId;
this._provider = provider ?? getProvider();
this._coder = new Coder(idl);
this._events = new EventManager(
this._programId,
this._provider,
this._coder
);
this._events = new EventManager(this._programId, provider, this._coder);
// Dynamic namespaces.
const [
@ -267,7 +255,7 @@ export class Program {
account,
simulate,
state,
] = NamespaceFactory.build(idl, this._coder, programId, this._provider);
] = NamespaceFactory.build(idl, this._coder, programId, provider);
this.rpc = rpc;
this.instruction = instruction;
this.transaction = transaction;
@ -285,10 +273,16 @@ export class Program {
* @param programId The on-chain address of the program.
* @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 idl = await Program.fetchIdl(programId, provider);
if (!idl) {
throw new Error(`IDL not found for program: ${address.toString()}`);
}
return new Program(idl, programId, provider);
}
@ -301,12 +295,18 @@ export class Program {
* @param programId The on-chain address of the program.
* @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();
const programId = translateAddress(address);
const idlAddr = await idlAddress(programId);
const accountInfo = await provider.connection.getAccountInfo(idlAddr);
if (!accountInfo) {
return null;
}
// Chop off account discriminator.
let idlAccount = decodeIdlAccount(accountInfo.data.slice(8));
const inflatedIdl = inflate(idlAccount.data);

View File

@ -28,7 +28,7 @@ export default class AccountFactory {
): AccountNamespace {
const accountFns: AccountNamespace = {};
idl.accounts.forEach((idlAccount) => {
idl.accounts?.forEach((idlAccount) => {
const name = camelCase(idlAccount.name);
accountFns[name] = new AccountClient(
idl,
@ -113,7 +113,8 @@ export class AccountClient {
this._programId = programId;
this._provider = provider ?? getProvider();
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.
*/
subscribe(address: Address, commitment?: Commitment): EventEmitter {
if (subscriptions.get(address.toString())) {
return subscriptions.get(address.toString()).ee;
const sub = subscriptions.get(address.toString());
if (sub) {
return sub.ee;
}
const ee = new EventEmitter();

View File

@ -34,7 +34,7 @@ export default class NamespaceFactory {
TransactionNamespace,
AccountNamespace,
SimulateNamespace,
StateClient
StateClient | undefined
] {
const rpc: RpcNamespace = {};
const instruction: InstructionNamespace = {};

View File

@ -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 { IdlError } from "../../error";
import {
@ -41,19 +45,22 @@ export default class InstructionNamespaceFactory {
};
// Utility fn for ordering the accounts for this instruction.
ix["accounts"] = (accs: Accounts) => {
ix["accounts"] = (accs: Accounts = {}) => {
return InstructionNamespaceFactory.accountsArray(accs, idlIx.accounts);
};
return ix;
}
public static accountsArray(ctx: Accounts, accounts: IdlAccountItem[]): any {
public static accountsArray(
ctx: Accounts,
accounts: IdlAccountItem[]
): AccountMeta[] {
return accounts
.map((acc: IdlAccountItem) => {
// Nested accounts.
// @ts-ignore
const nestedAccounts: IdlAccountItem[] | undefined = acc.accounts;
const nestedAccounts: IdlAccountItem[] | undefined =
"accounts" in acc ? acc.accounts : undefined;
if (nestedAccounts !== undefined) {
const rpcAccs = ctx[acc.name] as Accounts;
return InstructionNamespaceFactory.accountsArray(
@ -113,7 +120,7 @@ export interface InstructionNamespace {
*/
export type InstructionFn = IxProps & ((...args: any[]) => any);
type IxProps = {
accounts: (ctx: Accounts) => any;
accounts: (ctx: Accounts) => AccountMeta[];
};
export type InstructionEncodeFn = (ixName: string, ix: any) => Buffer;

View File

@ -1,7 +1,7 @@
import { TransactionSignature } from "@solana/web3.js";
import Provider from "../../provider";
import { IdlInstruction } from "../../idl";
import { splitArgsAndCtx } from "../context";
import { Context, splitArgsAndCtx } from "../context";
import { TransactionFn } from "./transaction";
import { ProgramError } from "../../error";

View File

@ -1,4 +1,8 @@
import { PublicKey } from "@solana/web3.js";
import {
PublicKey,
RpcResponseAndContext,
SimulatedTransactionResponse,
} from "@solana/web3.js";
import Provider from "../../provider";
import { IdlInstruction } from "../../idl";
import { splitArgsAndCtx } from "../context";
@ -21,7 +25,9 @@ export default class SimulateFactory {
const simulate = async (...args: any[]): Promise<SimulateResponse> => {
const tx = txFn(...args);
const [, ctx] = splitArgsAndCtx(idlIx, [...args]);
let resp = undefined;
let resp:
| RpcResponseAndContext<SimulatedTransactionResponse>
| undefined = undefined;
try {
resp = await provider.simulate(tx, ctx.signers, ctx.options);
} catch (err) {
@ -43,7 +49,7 @@ export default class SimulateFactory {
throw new Error("Simulated logs not found");
}
const events = [];
const events: Event[] = [];
if (idl.events) {
let parser = new EventParser(programId, coder);
parser.parseLogs(logs, (event) => {

View File

@ -56,37 +56,25 @@ export class StateClient {
}
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 _coder: Coder;
private _idl: Idl;
private _sub: Subscription | null;
constructor(
idl: Idl,
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._programId = programId;
this._address = programStateAddress(programId);
this._provider = provider ?? getProvider();
this._coder = coder ?? new Coder(idl);
this._sub = null;
// Build namespaces.
@ -99,7 +87,7 @@ export class StateClient {
let transaction: TransactionNamespace = {};
let rpc: RpcNamespace = {};
idl.state.methods.forEach((m: IdlStateMethod) => {
idl.state?.methods.forEach((m: IdlStateMethod) => {
// Build instruction method.
const ixItem = InstructionNamespaceFactory.build(
m,
@ -147,9 +135,11 @@ export class StateClient {
throw new Error(`Account does not exist ${addr.toString()}`);
}
// Assert the account discriminator is correct.
const expectedDiscriminator = await stateDiscriminator(
this._idl.state.struct.name
);
const state = this._idl.state;
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))) {
throw new Error("Invalid account discriminator");
}

View File

@ -61,7 +61,9 @@ export default class Provider {
* (This api is for Node only.)
*/
static env(): Provider {
if (isBrowser) return;
if (isBrowser) {
throw new Error(`Provider env is not available on browser.`);
}
const process = require("process");
const url = process.env.ANCHOR_PROVIDER_URL;
@ -102,7 +104,7 @@ export default class Provider {
await this.wallet.signTransaction(tx);
signers
.filter((s) => s !== undefined)
.filter((s): s is Signer => s !== undefined)
.forEach((kp) => {
tx.partialSign(kp);
});
@ -144,7 +146,7 @@ export default class Provider {
tx.recentBlockhash = blockhash.blockhash;
signers
.filter((s) => s !== undefined)
.filter((s): s is Signer => s !== undefined)
.forEach((kp) => {
tx.partialSign(kp);
});
@ -154,7 +156,7 @@ export default class Provider {
const signedTxs = await this.wallet.signAllTransactions(txs);
const sigs = [];
const sigs: TransactionSignature[] = [];
for (let k = 0; k < txs.length; k += 1) {
const tx = signedTxs[k];
@ -178,14 +180,11 @@ export default class Provider {
async simulate(
tx: Transaction,
signers?: Array<Signer | undefined>,
opts?: ConfirmOptions
opts: ConfirmOptions = this.opts
): Promise<RpcResponseAndContext<SimulatedTransactionResponse>> {
if (signers === undefined) {
signers = [];
}
if (opts === undefined) {
opts = this.opts;
}
tx.feePayer = this.wallet.publicKey;
tx.recentBlockhash = (
@ -196,7 +195,7 @@ export default class Provider {
await this.wallet.signTransaction(tx);
signers
.filter((s) => s !== undefined)
.filter((s): s is Signer => s !== undefined)
.forEach((kp) => {
tx.partialSign(kp);
});
@ -204,7 +203,7 @@ export default class Provider {
return await simulateTransaction(
this.connection,
tx,
opts.commitment ?? this.opts.commitment
opts.commitment ?? this.opts.commitment ?? "recent"
);
}
}

View File

@ -97,6 +97,9 @@ function attachWorkspaceOverride(
if (typeof entry !== "string" && entry.idl) {
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);
});
}

View File

@ -7,7 +7,6 @@
"outDir": "dist/esm/",
"rootDir": "./src",
"declarationDir": "dist",
"sourceMap": true,
"declaration": true,
@ -16,6 +15,7 @@
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"noImplicitAny": false,
"strictNullChecks": true,
"esModuleInterop": true,
"resolveJsonModule": true,
@ -23,7 +23,7 @@
"baseUrl": ".",
"typeRoots": ["types/", "node_modules/@types"],
"paths": {
"@solana/web3.js": ["./node_modules/@solana/web3.js/lib"]
"@solana/web3.js": ["./node_modules/@solana/web3.js/lib"]
}
}
}

View File

@ -5303,10 +5303,10 @@ typedoc@^0.20.36:
shiki "^0.9.3"
typedoc-default-themes "^0.12.10"
typescript@^4.0.5:
version "4.1.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7"
integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==
typescript@^4.4.3:
version "4.4.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324"
integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==
uglify-js@^3.1.4:
version "3.13.5"