ts: make `Provider` an interface, add `AnchorProvider` class, and update provider functions (#1707)
This commit is contained in:
parent
4d9bd6adc6
commit
537d470954
|
@ -7,12 +7,15 @@
|
|||
[submodule "examples/cfo/deps/swap"]
|
||||
path = tests/cfo/deps/swap
|
||||
url = https://github.com/project-serum/swap.git
|
||||
branch = armani/cfo
|
||||
[submodule "examples/cfo/deps/stake"]
|
||||
path = tests/cfo/deps/stake
|
||||
url = https://github.com/project-serum/stake.git
|
||||
branch = armani/cfo
|
||||
[submodule "examples/permissioned-markets/deps/serum-dex"]
|
||||
path = tests/permissioned-markets/deps/serum-dex
|
||||
url = https://github.com/project-serum/serum-dex
|
||||
[submodule "tests/auction-house"]
|
||||
path = tests/auction-house
|
||||
url = https://github.com/armaniferrante/auction-house
|
||||
branch = armani/pda
|
||||
|
|
|
@ -35,6 +35,7 @@ The minor version will be incremented upon a breaking change and the patch versi
|
|||
* spl: Re-export the `spl_token` crate ([#1665](https://github.com/project-serum/anchor/pull/1665)).
|
||||
* lang, cli, spl: Update solana toolchain to v1.9.13 ([#1653](https://github.com/project-serum/anchor/pull/1653) and [#1751](https://github.com/project-serum/anchor/pull/1751)).
|
||||
* lang: `Program` type now deserializes `programdata_address` only on demand ([#1723](https://github.com/project-serum/anchor/pull/1723)).
|
||||
* ts: Make `Provider` an interface and adjust its signatures and add `AnchorProvider` implementor class ([#1707](https://github.com/project-serum/anchor/pull/1707)).
|
||||
* spl: Change "to" to "from" in `token::burn` ([#1080](https://github.com/project-serum/anchor/pull/1080)).
|
||||
|
||||
## [0.23.0] - 2022-03-20
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
const anchor = require("@project-serum/anchor");
|
||||
|
||||
// Configure the local cluster.
|
||||
anchor.setProvider(anchor.Provider.local());
|
||||
anchor.setProvider(anchor.AnchorProvider.local());
|
||||
|
||||
async function main() {
|
||||
// #region main
|
||||
|
|
|
@ -2,7 +2,7 @@ const anchor = require("@project-serum/anchor");
|
|||
|
||||
describe("basic-0", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.local());
|
||||
anchor.setProvider(anchor.AnchorProvider.local());
|
||||
|
||||
it("Uses the workspace to invoke the initialize instruction", async () => {
|
||||
// #region code
|
||||
|
|
|
@ -4,7 +4,7 @@ const { SystemProgram } = anchor.web3;
|
|||
|
||||
describe("basic-1", () => {
|
||||
// Use a local provider.
|
||||
const provider = anchor.Provider.local();
|
||||
const provider = anchor.AnchorProvider.local();
|
||||
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(provider);
|
||||
|
|
|
@ -3,7 +3,7 @@ const anchor = require("@project-serum/anchor");
|
|||
const { SystemProgram } = anchor.web3;
|
||||
|
||||
describe("basic-2", () => {
|
||||
const provider = anchor.Provider.local();
|
||||
const provider = anchor.AnchorProvider.local();
|
||||
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(provider);
|
||||
|
|
|
@ -3,7 +3,7 @@ const anchor = require("@project-serum/anchor");
|
|||
const { SystemProgram } = anchor.web3;
|
||||
|
||||
describe("basic-3", () => {
|
||||
const provider = anchor.Provider.local();
|
||||
const provider = anchor.AnchorProvider.local();
|
||||
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(provider);
|
||||
|
|
|
@ -2,7 +2,7 @@ const assert = require("assert");
|
|||
const anchor = require("@project-serum/anchor");
|
||||
|
||||
describe("basic-4", () => {
|
||||
const provider = anchor.Provider.local();
|
||||
const provider = anchor.AnchorProvider.local();
|
||||
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(provider);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 967650c531ba0f23c88374875ccfcecb9b1a7800
|
||||
Subproject commit 2d4d9583467d697267b87b250af8c8bd360f3745
|
|
@ -6,7 +6,7 @@ import { assert } from "chai";
|
|||
import { BpfUpgradeableState } from "../target/types/bpf_upgradeable_state";
|
||||
|
||||
describe("bpf_upgradeable_state", () => {
|
||||
const provider = anchor.Provider.env();
|
||||
const provider = anchor.AnchorProvider.env();
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(provider);
|
||||
|
||||
|
|
|
@ -5,7 +5,11 @@ const { TOKEN_PROGRAM_ID } = require("@solana/spl-token");
|
|||
|
||||
describe("cashiers-check", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
const provider = anchor.AnchorProvider.env();
|
||||
// hack so we don't have to update serum-common library
|
||||
// to the new AnchorProvider class and Provider interface
|
||||
provider.send = provider.sendAndConfirm;
|
||||
anchor.setProvider(provider);
|
||||
|
||||
const program = anchor.workspace.CashiersCheck;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 9c41642dffbb334e1e39c616cd6a645d91768d3e
|
||||
Subproject commit b68b9a6fdea2c8befe95aa0f1fcca394579fc3bd
|
|
@ -1 +1 @@
|
|||
Subproject commit 3da36aaae7af6ce901d68c0280aac34817fe7fd8
|
||||
Subproject commit 2ac6045cf37436c4702fbe12678f3a6243feecb1
|
|
@ -6,7 +6,7 @@ const anchor = require("@project-serum/anchor");
|
|||
const { Market, OpenOrders } = require("@project-serum/serum");
|
||||
const Account = anchor.web3.Account;
|
||||
const Program = anchor.Program;
|
||||
const provider = anchor.Provider.local();
|
||||
const provider = anchor.AnchorProvider.local();
|
||||
const secret = JSON.parse(fs.readFileSync("./scripts/market-maker.json"));
|
||||
const MARKET_MAKER = new Account(secret);
|
||||
const PublicKey = anchor.web3.PublicKey;
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
const utils = require("../tests/utils");
|
||||
const fs = require("fs");
|
||||
const anchor = require("@project-serum/anchor");
|
||||
const provider = anchor.Provider.local();
|
||||
const provider = anchor.AnchorProvider.local();
|
||||
// hack so we don't have to update serum-common library
|
||||
// to the new AnchorProvider class and Provider interface
|
||||
provider.send = provider.sendAndConfirm;
|
||||
|
||||
async function main() {
|
||||
ORDERBOOK_ENV = await utils.initMarket({
|
||||
|
|
|
@ -9,7 +9,7 @@ const { runTradeBot } = require("../tests/utils");
|
|||
|
||||
async function main() {
|
||||
const market = new PublicKey(process.argv[2]);
|
||||
const provider = anchor.Provider.local();
|
||||
const provider = anchor.AnchorProvider.local();
|
||||
runTradeBot(market, provider);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,13 @@ const SYSVAR_INSTRUCTIONS_PUBKEY = new PublicKey(
|
|||
const FEES = "6160355581";
|
||||
|
||||
describe("cfo", () => {
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
const provider = anchor.AnchorProvider.env();
|
||||
anchor.setProvider(provider);
|
||||
|
||||
const program = anchor.workspace.Cfo;
|
||||
// hack so we don't have to update serum-common library
|
||||
// to the new AnchorProvider class and Provider interface
|
||||
program.provider.send = provider.sendAndConfirm;
|
||||
const sweepAuthority = program.provider.wallet.publicKey;
|
||||
let officer, srmVault, usdcVault, bVault, stake, treasury;
|
||||
let officerBump, srmBump, usdcBump, bBump, stakeBump, treasuryBump;
|
||||
|
|
|
@ -125,7 +125,7 @@ async function fundAccount({ provider, mints }) {
|
|||
};
|
||||
|
||||
// Transfer lamports to market maker.
|
||||
await provider.send(
|
||||
await provider.sendAndConfirm(
|
||||
(() => {
|
||||
const tx = new Transaction();
|
||||
tx.add(
|
||||
|
@ -155,7 +155,7 @@ async function fundAccount({ provider, mints }) {
|
|||
MARKET_MAKER.publicKey
|
||||
);
|
||||
|
||||
await provider.send(
|
||||
await provider.sendAndConfirm(
|
||||
(() => {
|
||||
const tx = new Transaction();
|
||||
tx.add(
|
||||
|
@ -220,7 +220,10 @@ async function setupMarket({
|
|||
feeDiscountPubkey: null,
|
||||
selfTradeBehavior: "abortTransaction",
|
||||
});
|
||||
await provider.send(transaction, signers.concat(marketMaker.account));
|
||||
await provider.sendAndConfirm(
|
||||
transaction,
|
||||
signers.concat(marketMaker.account)
|
||||
);
|
||||
}
|
||||
|
||||
for (let k = 0; k < bids.length; k += 1) {
|
||||
|
@ -239,7 +242,10 @@ async function setupMarket({
|
|||
feeDiscountPubkey: null,
|
||||
selfTradeBehavior: "abortTransaction",
|
||||
});
|
||||
await provider.send(transaction, signers.concat(marketMaker.account));
|
||||
await provider.sendAndConfirm(
|
||||
transaction,
|
||||
signers.concat(marketMaker.account)
|
||||
);
|
||||
}
|
||||
|
||||
return [MARKET_A_USDC, vaultOwner];
|
||||
|
@ -527,7 +533,7 @@ async function runTradeBot(market, provider, iterations = undefined) {
|
|||
feeDiscountPubkey: null,
|
||||
selfTradeBehavior: "abortTransaction",
|
||||
});
|
||||
let txSig = await provider.send(tx_ask, sigs_ask.concat(maker));
|
||||
let txSig = await provider.sendAndConfirm(tx_ask, sigs_ask.concat(maker));
|
||||
console.log("Ask", txSig);
|
||||
|
||||
// Take.
|
||||
|
@ -545,7 +551,7 @@ async function runTradeBot(market, provider, iterations = undefined) {
|
|||
feeDiscountPubkey: null,
|
||||
selfTradeBehavior: "abortTransaction",
|
||||
});
|
||||
txSig = await provider.send(tx_bid, sigs_bid.concat(taker));
|
||||
txSig = await provider.sendAndConfirm(tx_bid, sigs_bid.concat(taker));
|
||||
console.log("Bid", txSig);
|
||||
|
||||
await sleep(1000);
|
||||
|
|
|
@ -5,7 +5,10 @@ const utils = require("../../deps/stake/tests/utils");
|
|||
|
||||
const lockup = anchor.workspace.Lockup;
|
||||
const registry = anchor.workspace.Registry;
|
||||
const provider = anchor.Provider.env();
|
||||
const provider = anchor.AnchorProvider.env();
|
||||
// hack so we don't have to update serum-common library
|
||||
// to the new AnchorProvider class and Provider interface
|
||||
provider.send = provider.sendAndConfirm;
|
||||
|
||||
let lockupAddress = null;
|
||||
let mint = null;
|
||||
|
|
|
@ -4,7 +4,7 @@ const { PublicKey } = anchor.web3;
|
|||
|
||||
describe("chat", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
// Program client handle.
|
||||
const program = anchor.workspace.Chat;
|
||||
|
|
|
@ -2,7 +2,7 @@ const { assert } = require("chai");
|
|||
const anchor = require("@project-serum/anchor");
|
||||
|
||||
describe("composite", () => {
|
||||
const provider = anchor.Provider.local();
|
||||
const provider = anchor.AnchorProvider.local();
|
||||
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(provider);
|
||||
|
|
|
@ -8,7 +8,7 @@ import { Caller } from "../target/types/caller";
|
|||
const { SystemProgram } = anchor.web3;
|
||||
|
||||
describe("CPI return", () => {
|
||||
const provider = anchor.Provider.env();
|
||||
const provider = anchor.AnchorProvider.env();
|
||||
anchor.setProvider(provider);
|
||||
|
||||
const callerProgram = anchor.workspace.Caller as Program<Caller>;
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Keypair, SYSVAR_RENT_PUBKEY } from "@solana/web3.js";
|
|||
|
||||
describe("custom-coder", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
// Client.
|
||||
const program = Spl.token();
|
||||
|
|
|
@ -5,7 +5,7 @@ import { DeclareId } from "../target/types/declare_id";
|
|||
import { assert } from "chai";
|
||||
|
||||
describe("declare_id", () => {
|
||||
anchor.setProvider(anchor.Provider.local());
|
||||
anchor.setProvider(anchor.AnchorProvider.local());
|
||||
const program = anchor.workspace.DeclareId as Program<DeclareId>;
|
||||
|
||||
it("throws error!", async () => {
|
||||
|
|
|
@ -64,7 +64,7 @@ const withLogTest = async (callback, expectedLogs) => {
|
|||
|
||||
describe("errors", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
const localProvider = anchor.Provider.local();
|
||||
const localProvider = anchor.AnchorProvider.local();
|
||||
localProvider.opts.skipPreflight = true;
|
||||
// processed failed tx do not result in AnchorErrors in the client
|
||||
// because we cannot get logs for them (only through overkill `onLogs`)
|
||||
|
@ -279,7 +279,7 @@ describe("errors", () => {
|
|||
data: program.coder.instruction.encode("signer_error", {}),
|
||||
})
|
||||
);
|
||||
await program.provider.send(tx);
|
||||
await program.provider.sendAndConfirm(tx);
|
||||
assert.ok(false);
|
||||
} catch (err) {
|
||||
anchor.getProvider().connection.removeOnLogsListener(listener);
|
||||
|
|
|
@ -8,7 +8,7 @@ import { Escrow } from "../target/types/escrow";
|
|||
type EscrowAccount = IdlAccounts<Escrow>["escrowAccount"];
|
||||
|
||||
describe("escrow", () => {
|
||||
const provider = anchor.Provider.env();
|
||||
const provider = anchor.AnchorProvider.env();
|
||||
anchor.setProvider(provider);
|
||||
|
||||
const program = anchor.workspace.Escrow as Program<Escrow>;
|
||||
|
|
|
@ -3,7 +3,7 @@ const { assert } = require("chai");
|
|||
|
||||
describe("events", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
const program = anchor.workspace.Events;
|
||||
|
||||
it("Is initialized!", async () => {
|
||||
|
|
|
@ -6,7 +6,7 @@ import { assert } from "chai";
|
|||
|
||||
describe("floats", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.Floats as Program<Floats>;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ const {
|
|||
const { token } = require("@project-serum/anchor/dist/cjs/utils");
|
||||
|
||||
describe("ido-pool", () => {
|
||||
const provider = anchor.Provider.local();
|
||||
const provider = anchor.AnchorProvider.local();
|
||||
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(provider);
|
||||
|
@ -182,7 +182,7 @@ describe("ido-pool", () => {
|
|||
let createUserUsdcTrns = new anchor.web3.Transaction().add(
|
||||
createUserUsdcInstr
|
||||
);
|
||||
await provider.send(createUserUsdcTrns);
|
||||
await provider.sendAndConfirm(createUserUsdcTrns);
|
||||
await usdcMintAccount.mintTo(
|
||||
userUsdc,
|
||||
provider.wallet.publicKey,
|
||||
|
@ -283,7 +283,7 @@ describe("ido-pool", () => {
|
|||
let createSecondUserUsdcTrns = new anchor.web3.Transaction();
|
||||
createSecondUserUsdcTrns.add(transferSolInstr);
|
||||
createSecondUserUsdcTrns.add(createSecondUserUsdcInstr);
|
||||
await provider.send(createSecondUserUsdcTrns);
|
||||
await provider.sendAndConfirm(createSecondUserUsdcTrns);
|
||||
await usdcMintAccount.mintTo(
|
||||
secondUserUsdc,
|
||||
provider.wallet.publicKey,
|
||||
|
|
|
@ -4,7 +4,7 @@ const nativeAssert = require("assert");
|
|||
|
||||
describe("interface", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const counter = anchor.workspace.Counter;
|
||||
const counterAuth = anchor.workspace.CounterAuth;
|
||||
|
|
|
@ -9,7 +9,10 @@ anchor.utils.features.set("anchor-deprecated-state");
|
|||
|
||||
describe("Lockup and Registry", () => {
|
||||
// Read the provider from the configured environmnet.
|
||||
const provider = anchor.Provider.env();
|
||||
const provider = anchor.AnchorProvider.env();
|
||||
// hack so we don't have to update serum-common library
|
||||
// to the new AnchorProvider class and Provider interface
|
||||
provider.send = provider.sendAndConfirm;
|
||||
|
||||
// Configure the client to use the provider.
|
||||
anchor.setProvider(provider);
|
||||
|
|
|
@ -11,7 +11,7 @@ const { assert } = require("chai");
|
|||
|
||||
describe("miscNonRentExempt", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
const program = anchor.workspace.Misc as Program<Misc>;
|
||||
|
||||
it("init_if_needed checks rent_exemption if init is not needed", async () => {
|
||||
|
|
|
@ -20,7 +20,7 @@ const miscIdl = require("../target/idl/misc.json");
|
|||
|
||||
describe("misc", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
const program = anchor.workspace.Misc as Program<Misc>;
|
||||
const misc2Program = anchor.workspace.Misc2 as Program<Misc2>;
|
||||
|
||||
|
@ -760,7 +760,7 @@ describe("misc", () => {
|
|||
const anotherProgram = new anchor.Program(
|
||||
miscIdl,
|
||||
program.programId,
|
||||
new anchor.Provider(
|
||||
new anchor.AnchorProvider(
|
||||
program.provider.connection,
|
||||
new anchor.Wallet(anchor.web3.Keypair.generate()),
|
||||
{ commitment: program.provider.connection.commitment }
|
||||
|
|
|
@ -6,7 +6,7 @@ import { MultipleSuites } from "../../target/types/multiple_suites";
|
|||
|
||||
describe("multiple-suites", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.MultipleSuites as Program<MultipleSuites>;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { MultipleSuites } from "../../../target/types/multiple_suites";
|
|||
|
||||
describe("multiple-suites", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.MultipleSuites as Program<MultipleSuites>;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { MultipleSuites } from "../../../target/types/multiple_suites";
|
|||
|
||||
describe("multiple-suites", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.MultipleSuites as Program<MultipleSuites>;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { MultipleSuites } from "../../target/types/multiple_suites";
|
|||
|
||||
describe("multiple-suites", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.MultipleSuites as Program<MultipleSuites>;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { assert } from "chai";
|
|||
|
||||
describe("multiple-suites", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.MultipleSuites as Program<MultipleSuites>;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { MultipleSuites } from "../../../target/types/multiple_suites";
|
|||
|
||||
describe("multiple-suites", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.MultipleSuites as Program<MultipleSuites>;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ const { assert } = require("chai");
|
|||
|
||||
describe("multisig", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.Multisig;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ const encode = anchor.utils.bytes.utf8.encode;
|
|||
|
||||
describe("typescript", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.PdaDerivation as Program<PdaDerivation>;
|
||||
const base = Keypair.generate();
|
||||
|
|
|
@ -4,7 +4,7 @@ import { assert } from "chai";
|
|||
import { createPriceFeed, setFeedPrice, getFeedData } from "./oracleUtils";
|
||||
|
||||
describe("pyth-oracle", () => {
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
const program = anchor.workspace.Pyth as Program;
|
||||
|
||||
it("initialize", async () => {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { SafetyChecks } from "../target/types/safety_checks";
|
|||
|
||||
describe("safety-checks", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.SafetyChecks as Program<SafetyChecks>;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ const anchor = require("@project-serum/anchor");
|
|||
const { assert } = require("chai");
|
||||
|
||||
describe("token", () => {
|
||||
const provider = anchor.Provider.local();
|
||||
const provider = anchor.AnchorProvider.local();
|
||||
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(provider);
|
||||
|
@ -118,7 +118,7 @@ async function createMint(provider, authority) {
|
|||
const tx = new anchor.web3.Transaction();
|
||||
tx.add(...instructions);
|
||||
|
||||
await provider.send(tx, [mint]);
|
||||
await provider.sendAndConfirm(tx, [mint]);
|
||||
|
||||
return mint.publicKey;
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ async function createTokenAccount(provider, mint, owner) {
|
|||
tx.add(
|
||||
...(await createTokenAccountInstrs(provider, vault.publicKey, mint, owner))
|
||||
);
|
||||
await provider.send(tx, [vault]);
|
||||
await provider.sendAndConfirm(tx, [vault]);
|
||||
return vault.publicKey;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,11 @@ const TAKER_FEE = 0.0022;
|
|||
|
||||
describe("swap", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
const provider = anchor.AnchorProvider.env();
|
||||
// hack so we don't have to update serum-common library
|
||||
// to the new AnchorProvider class and Provider interface
|
||||
provider.send = provider.sendAndConfirm;
|
||||
anchor.setProvider(provider);
|
||||
|
||||
// Swap program client.
|
||||
const program = anchor.workspace.Swap;
|
||||
|
|
|
@ -196,7 +196,7 @@ async function fundAccount({ provider, mints }) {
|
|||
};
|
||||
|
||||
// Transfer lamports to market maker.
|
||||
await provider.send(
|
||||
await provider.sendAndConfirm(
|
||||
(() => {
|
||||
const tx = new Transaction();
|
||||
tx.add(
|
||||
|
@ -226,7 +226,7 @@ async function fundAccount({ provider, mints }) {
|
|||
MARKET_MAKER.publicKey
|
||||
);
|
||||
|
||||
await provider.send(
|
||||
await provider.sendAndConfirm(
|
||||
(() => {
|
||||
const tx = new Transaction();
|
||||
tx.add(
|
||||
|
@ -291,7 +291,10 @@ async function setupMarket({
|
|||
feeDiscountPubkey: null,
|
||||
selfTradeBehavior: "abortTransaction",
|
||||
});
|
||||
await provider.send(transaction, signers.concat(marketMaker.account));
|
||||
await provider.sendAndConfirm(
|
||||
transaction,
|
||||
signers.concat(marketMaker.account)
|
||||
);
|
||||
}
|
||||
|
||||
for (let k = 0; k < bids.length; k += 1) {
|
||||
|
@ -310,7 +313,10 @@ async function setupMarket({
|
|||
feeDiscountPubkey: null,
|
||||
selfTradeBehavior: "abortTransaction",
|
||||
});
|
||||
await provider.send(transaction, signers.concat(marketMaker.account));
|
||||
await provider.sendAndConfirm(
|
||||
transaction,
|
||||
signers.concat(marketMaker.account)
|
||||
);
|
||||
}
|
||||
|
||||
return MARKET_A_USDC;
|
||||
|
|
|
@ -3,7 +3,7 @@ const splToken = require("@solana/spl-token");
|
|||
const { assert } = require("chai");
|
||||
|
||||
describe("system_accounts", () => {
|
||||
anchor.setProvider(anchor.Provider.local());
|
||||
anchor.setProvider(anchor.AnchorProvider.local());
|
||||
const program = anchor.workspace.SystemAccounts;
|
||||
const authority = program.provider.wallet.payer;
|
||||
const wallet = anchor.web3.Keypair.generate();
|
||||
|
|
|
@ -3,7 +3,7 @@ const { assert } = require("chai");
|
|||
|
||||
describe("sysvars", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.local());
|
||||
anchor.setProvider(anchor.AnchorProvider.local());
|
||||
const program = anchor.workspace.Sysvars;
|
||||
|
||||
it("Is initialized!", async () => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const anchor = require("@project-serum/anchor");
|
||||
|
||||
describe("tictactoe", () => {
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
const program = anchor.workspace.Tictactoe;
|
||||
let dashboard = anchor.web3.Keypair.generate();
|
||||
let game = anchor.web3.Keypair.generate();
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as anchor from "@project-serum/anchor";
|
|||
|
||||
describe("typescript", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
it("Is initialized!", async () => {
|
||||
// Add your test here.
|
||||
|
|
|
@ -5,7 +5,7 @@ import { ValidatorClone } from "../target/types/validator_clone";
|
|||
|
||||
describe("validator-clone", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.ValidatorClone as Program<ValidatorClone>;
|
||||
const connection = program.provider.connection;
|
||||
|
|
|
@ -6,7 +6,7 @@ const BN = anchor.BN;
|
|||
|
||||
describe("zero-copy", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
anchor.setProvider(anchor.Provider.env());
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
const program = anchor.workspace.ZeroCopy;
|
||||
const programCpi = anchor.workspace.ZeroCpi;
|
||||
|
|
|
@ -3,7 +3,12 @@ import { isBrowser } from "./utils/common.js";
|
|||
|
||||
export { default as BN } from "bn.js";
|
||||
export * as web3 from "@solana/web3.js";
|
||||
export { default as Provider, getProvider, setProvider } from "./provider.js";
|
||||
export {
|
||||
default as Provider,
|
||||
getProvider,
|
||||
setProvider,
|
||||
AnchorProvider,
|
||||
} from "./provider.js";
|
||||
export * from "./error.js";
|
||||
export { Instruction } from "./coder/borsh/instruction.js";
|
||||
export { Idl } from "./idl.js";
|
||||
|
|
|
@ -58,6 +58,13 @@ export class AccountsResolver<IDL extends Idl, I extends AllInstructions<IDL>> {
|
|||
|
||||
// Signers default to the provider.
|
||||
if (accountDesc.isSigner && !this._accounts[accountDescName]) {
|
||||
// @ts-expect-error
|
||||
if (this._provider.wallet === undefined) {
|
||||
throw new Error(
|
||||
"This function requires the Provider interface implementor to have a 'wallet' field."
|
||||
);
|
||||
}
|
||||
// @ts-expect-error
|
||||
this._accounts[accountDescName] = this._provider.wallet.publicKey;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -287,7 +287,15 @@ export class AccountClient<
|
|||
): Promise<TransactionInstruction> {
|
||||
const size = this.size;
|
||||
|
||||
// @ts-expect-error
|
||||
if (this._provider.wallet === undefined) {
|
||||
throw new Error(
|
||||
"This function requires the Provider interface implementor to have a 'wallet' field."
|
||||
);
|
||||
}
|
||||
|
||||
return SystemProgram.createAccount({
|
||||
// @ts-expect-error
|
||||
fromPubkey: this._provider.wallet.publicKey,
|
||||
newAccountPubkey: signer.publicKey,
|
||||
space: sizeOverride ?? size,
|
||||
|
|
|
@ -20,8 +20,17 @@ export default class RpcFactory {
|
|||
const rpc: RpcFn<IDL, I> = async (...args) => {
|
||||
const tx = txFn(...args);
|
||||
const [, ctx] = splitArgsAndCtx(idlIx, [...args]);
|
||||
if (provider.sendAndConfirm === undefined) {
|
||||
throw new Error(
|
||||
"This function requires 'Provider.sendAndConfirm' to be implemented."
|
||||
);
|
||||
}
|
||||
try {
|
||||
return await provider.send(tx, ctx.signers, ctx.options);
|
||||
return await provider.sendAndConfirm(
|
||||
tx,
|
||||
ctx.signers ?? [],
|
||||
ctx.options
|
||||
);
|
||||
} catch (err) {
|
||||
throw translateError(err, idlErrors);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import {
|
||||
PublicKey,
|
||||
RpcResponseAndContext,
|
||||
SimulatedTransactionResponse,
|
||||
} from "@solana/web3.js";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import Provider from "../../provider.js";
|
||||
import { SuccessfulTxSimulationResponse } from "src/utils/rpc.js";
|
||||
import { splitArgsAndCtx } from "../context.js";
|
||||
import { TransactionFn } from "./transaction.js";
|
||||
import { EventParser, Event } from "../event.js";
|
||||
|
@ -30,21 +27,25 @@ export default class SimulateFactory {
|
|||
const simulate: SimulateFn<IDL> = async (...args) => {
|
||||
const tx = txFn(...args);
|
||||
const [, ctx] = splitArgsAndCtx(idlIx, [...args]);
|
||||
let resp:
|
||||
| RpcResponseAndContext<SimulatedTransactionResponse>
|
||||
| undefined = undefined;
|
||||
let resp: SuccessfulTxSimulationResponse | undefined = undefined;
|
||||
if (provider.simulate === undefined) {
|
||||
throw new Error(
|
||||
"This function requires 'Provider.simulate' to be implemented."
|
||||
);
|
||||
}
|
||||
try {
|
||||
resp = await provider!.simulate(tx, ctx.signers, ctx.options);
|
||||
resp = await provider!.simulate(
|
||||
tx,
|
||||
ctx.signers,
|
||||
ctx.options?.commitment
|
||||
);
|
||||
} catch (err) {
|
||||
throw translateError(err, idlErrors);
|
||||
}
|
||||
if (resp === undefined) {
|
||||
throw new Error("Unable to simulate transaction");
|
||||
}
|
||||
if (resp.value.err) {
|
||||
throw new Error(`Simulate error: ${resp.value.err.toString()}`);
|
||||
}
|
||||
const logs = resp.value.logs;
|
||||
const logs = resp.logs;
|
||||
if (!logs) {
|
||||
throw new Error("Simulated logs not found");
|
||||
}
|
||||
|
|
|
@ -245,8 +245,15 @@ function stateInstructionKeys<M extends IdlStateMethod>(
|
|||
if (m.name === "new") {
|
||||
// Ctor `new` method.
|
||||
const [programSigner] = findProgramAddressSync([], programId);
|
||||
// @ts-expect-error
|
||||
if (provider.wallet === undefined) {
|
||||
throw new Error(
|
||||
"This function requires the Provider interface implementor to have a 'wallet' field."
|
||||
);
|
||||
}
|
||||
return [
|
||||
{
|
||||
// @ts-expect-error
|
||||
pubkey: provider.wallet.publicKey,
|
||||
isWritable: false,
|
||||
isSigner: true,
|
||||
|
|
|
@ -5,19 +5,49 @@ import {
|
|||
Transaction,
|
||||
TransactionSignature,
|
||||
ConfirmOptions,
|
||||
RpcResponseAndContext,
|
||||
SimulatedTransactionResponse,
|
||||
Commitment,
|
||||
SendTransactionError,
|
||||
SendOptions,
|
||||
RpcResponseAndContext,
|
||||
} from "@solana/web3.js";
|
||||
import { bs58 } from "./utils/bytes/index.js";
|
||||
import { isBrowser } from "./utils/common.js";
|
||||
import {
|
||||
simulateTransaction,
|
||||
SuccessfulTxSimulationResponse,
|
||||
} from "./utils/rpc.js";
|
||||
|
||||
export default interface Provider {
|
||||
readonly connection: Connection;
|
||||
|
||||
send?(
|
||||
tx: Transaction,
|
||||
signers?: Signer[],
|
||||
opts?: SendOptions
|
||||
): Promise<TransactionSignature>;
|
||||
sendAndConfirm?(
|
||||
tx: Transaction,
|
||||
signers?: Signer[],
|
||||
opts?: ConfirmOptions
|
||||
): Promise<TransactionSignature>;
|
||||
sendAll?(
|
||||
txWithSigners: { tx: Transaction; signers?: Signer[] }[],
|
||||
opts?: ConfirmOptions
|
||||
): Promise<Array<TransactionSignature>>;
|
||||
simulate?(
|
||||
tx: Transaction,
|
||||
signers?: Signer[],
|
||||
commitment?: Commitment,
|
||||
includeAccounts?: boolean | PublicKey[]
|
||||
): Promise<SuccessfulTxSimulationResponse>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The network and wallet context used to send transactions paid for and signed
|
||||
* by the provider.
|
||||
*/
|
||||
export default class Provider {
|
||||
export class AnchorProvider implements Provider {
|
||||
/**
|
||||
* @param connection The cluster connection where the program is deployed.
|
||||
* @param wallet The wallet used to pay for and sign all transactions.
|
||||
|
@ -44,18 +74,18 @@ export default class Provider {
|
|||
*
|
||||
* (This api is for Node only.)
|
||||
*/
|
||||
static local(url?: string, opts?: ConfirmOptions): Provider {
|
||||
static local(url?: string, opts?: ConfirmOptions): AnchorProvider {
|
||||
if (isBrowser) {
|
||||
throw new Error(`Provider local is not available on browser.`);
|
||||
}
|
||||
opts = opts ?? Provider.defaultOptions();
|
||||
opts = opts ?? AnchorProvider.defaultOptions();
|
||||
const connection = new Connection(
|
||||
url ?? "http://localhost:8899",
|
||||
opts.preflightCommitment
|
||||
);
|
||||
const NodeWallet = require("./nodewallet.js").default;
|
||||
const wallet = NodeWallet.local();
|
||||
return new Provider(connection, wallet, opts);
|
||||
return new AnchorProvider(connection, wallet, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,7 +94,7 @@ export default class Provider {
|
|||
*
|
||||
* (This api is for Node only.)
|
||||
*/
|
||||
static env(): Provider {
|
||||
static env(): AnchorProvider {
|
||||
if (isBrowser) {
|
||||
throw new Error(`Provider env is not available on browser.`);
|
||||
}
|
||||
|
@ -74,30 +104,26 @@ export default class Provider {
|
|||
if (url === undefined) {
|
||||
throw new Error("ANCHOR_PROVIDER_URL is not defined");
|
||||
}
|
||||
const options = Provider.defaultOptions();
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
const connection = new Connection(url, options.commitment);
|
||||
const NodeWallet = require("./nodewallet.js").default;
|
||||
const wallet = NodeWallet.local();
|
||||
|
||||
return new Provider(connection, wallet, options);
|
||||
return new AnchorProvider(connection, wallet, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the given transaction, paid for and signed by the provider's wallet.
|
||||
*
|
||||
* @param tx The transaction to send.
|
||||
* @param signers The set of signers in addition to the provider wallet that
|
||||
* will sign the transaction.
|
||||
* @param signers The signers of the transaction.
|
||||
* @param opts Transaction confirmation options.
|
||||
*/
|
||||
async send(
|
||||
async sendAndConfirm(
|
||||
tx: Transaction,
|
||||
signers?: Array<Signer | undefined>,
|
||||
signers?: Signer[],
|
||||
opts?: ConfirmOptions
|
||||
): Promise<TransactionSignature> {
|
||||
if (signers === undefined) {
|
||||
signers = [];
|
||||
}
|
||||
if (opts === undefined) {
|
||||
opts = this.opts;
|
||||
}
|
||||
|
@ -108,11 +134,9 @@ export default class Provider {
|
|||
).blockhash;
|
||||
|
||||
tx = await this.wallet.signTransaction(tx);
|
||||
signers
|
||||
.filter((s): s is Signer => s !== undefined)
|
||||
.forEach((kp) => {
|
||||
tx.partialSign(kp);
|
||||
});
|
||||
(signers ?? []).forEach((kp) => {
|
||||
tx.partialSign(kp);
|
||||
});
|
||||
|
||||
const rawTx = tx.serialize();
|
||||
|
||||
|
@ -146,7 +170,7 @@ export default class Provider {
|
|||
* Similar to `send`, but for an array of transactions and signers.
|
||||
*/
|
||||
async sendAll(
|
||||
reqs: Array<SendTxRequest>,
|
||||
txWithSigners: { tx: Transaction; signers?: Signer[] }[],
|
||||
opts?: ConfirmOptions
|
||||
): Promise<Array<TransactionSignature>> {
|
||||
if (opts === undefined) {
|
||||
|
@ -156,22 +180,16 @@ export default class Provider {
|
|||
opts.preflightCommitment
|
||||
);
|
||||
|
||||
let txs = reqs.map((r) => {
|
||||
let txs = txWithSigners.map((r) => {
|
||||
let tx = r.tx;
|
||||
let signers = r.signers;
|
||||
|
||||
if (signers === undefined) {
|
||||
signers = [];
|
||||
}
|
||||
let signers = r.signers ?? [];
|
||||
|
||||
tx.feePayer = this.wallet.publicKey;
|
||||
tx.recentBlockhash = blockhash.blockhash;
|
||||
|
||||
signers
|
||||
.filter((s): s is Signer => s !== undefined)
|
||||
.forEach((kp) => {
|
||||
tx.partialSign(kp);
|
||||
});
|
||||
signers.forEach((kp) => {
|
||||
tx.partialSign(kp);
|
||||
});
|
||||
|
||||
return tx;
|
||||
});
|
||||
|
@ -195,38 +213,45 @@ export default class Provider {
|
|||
* Simulates the given transaction, returning emitted logs from execution.
|
||||
*
|
||||
* @param tx The transaction to send.
|
||||
* @param signers The set of signers in addition to the provdier wallet that
|
||||
* will sign the transaction.
|
||||
* @param signers The signers of the transaction.
|
||||
* @param opts Transaction confirmation options.
|
||||
*/
|
||||
async simulate(
|
||||
tx: Transaction,
|
||||
signers?: Array<Signer | undefined>,
|
||||
opts: ConfirmOptions = this.opts
|
||||
): Promise<RpcResponseAndContext<SimulatedTransactionResponse>> {
|
||||
if (signers === undefined) {
|
||||
signers = [];
|
||||
}
|
||||
|
||||
signers?: Signer[],
|
||||
commitment?: Commitment,
|
||||
includeAccounts?: boolean | PublicKey[]
|
||||
): Promise<SuccessfulTxSimulationResponse> {
|
||||
tx.feePayer = this.wallet.publicKey;
|
||||
tx.recentBlockhash = (
|
||||
await this.connection.getRecentBlockhash(
|
||||
opts.preflightCommitment ?? this.opts.preflightCommitment
|
||||
await this.connection.getLatestBlockhash(
|
||||
commitment ?? this.connection.commitment
|
||||
)
|
||||
).blockhash;
|
||||
|
||||
tx = await this.wallet.signTransaction(tx);
|
||||
signers
|
||||
.filter((s): s is Signer => s !== undefined)
|
||||
.forEach((kp) => {
|
||||
tx.partialSign(kp);
|
||||
});
|
||||
|
||||
return await simulateTransaction(
|
||||
const result = await simulateTransaction(
|
||||
this.connection,
|
||||
tx,
|
||||
opts.commitment ?? this.opts.commitment ?? "processed"
|
||||
signers,
|
||||
commitment,
|
||||
includeAccounts
|
||||
);
|
||||
|
||||
if (result.value.err) {
|
||||
throw new SimulateError(result.value);
|
||||
}
|
||||
|
||||
return result.value;
|
||||
}
|
||||
}
|
||||
|
||||
class SimulateError extends Error {
|
||||
constructor(
|
||||
readonly simulationResponse: SimulatedTransactionResponse,
|
||||
message?: string
|
||||
) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,33 +269,6 @@ export interface Wallet {
|
|||
publicKey: PublicKey;
|
||||
}
|
||||
|
||||
// Copy of Connection.simulateTransaction that takes a commitment parameter.
|
||||
async function simulateTransaction(
|
||||
connection: Connection,
|
||||
transaction: Transaction,
|
||||
commitment: Commitment
|
||||
): Promise<RpcResponseAndContext<SimulatedTransactionResponse>> {
|
||||
// @ts-ignore
|
||||
transaction.recentBlockhash = await connection._recentBlockhash(
|
||||
// @ts-ignore
|
||||
connection._disableBlockhashCaching
|
||||
);
|
||||
|
||||
const signData = transaction.serializeMessage();
|
||||
// @ts-ignore
|
||||
const wireTransaction = transaction._serialize(signData);
|
||||
const encodedTransaction = wireTransaction.toString("base64");
|
||||
const config: any = { encoding: "base64", commitment };
|
||||
const args = [encodedTransaction, config];
|
||||
|
||||
// @ts-ignore
|
||||
const res = await connection._rpcRequest("simulateTransaction", args);
|
||||
if (res.error) {
|
||||
throw new Error("failed to simulate transaction: " + res.error.message);
|
||||
}
|
||||
return res.result;
|
||||
}
|
||||
|
||||
// Copy of Connection.sendAndConfirmRawTransaction that throws
|
||||
// a better error if 'confirmTransaction` returns an error status
|
||||
async function sendAndConfirmRawTransaction(
|
||||
|
@ -322,7 +320,7 @@ export function setProvider(provider: Provider) {
|
|||
*/
|
||||
export function getProvider(): Provider {
|
||||
if (_provider === null) {
|
||||
return Provider.local();
|
||||
return AnchorProvider.local();
|
||||
}
|
||||
return _provider;
|
||||
}
|
||||
|
|
|
@ -9,10 +9,33 @@ import {
|
|||
Transaction,
|
||||
TransactionInstruction,
|
||||
Commitment,
|
||||
Signer,
|
||||
RpcResponseAndContext,
|
||||
SimulatedTransactionResponse,
|
||||
SendTransactionError,
|
||||
} from "@solana/web3.js";
|
||||
import { chunks } from "../utils/common.js";
|
||||
import { Address, translateAddress } from "../program/common.js";
|
||||
import Provider, { getProvider } from "../provider.js";
|
||||
import Provider, { getProvider, Wallet } from "../provider.js";
|
||||
import {
|
||||
type as pick,
|
||||
number,
|
||||
string,
|
||||
array,
|
||||
boolean,
|
||||
literal,
|
||||
record,
|
||||
union,
|
||||
optional,
|
||||
nullable,
|
||||
coerce,
|
||||
instance,
|
||||
create,
|
||||
tuple,
|
||||
unknown,
|
||||
any,
|
||||
Struct,
|
||||
} from "superstruct";
|
||||
|
||||
/**
|
||||
* Sends a transaction to a program with the given accounts and instruction
|
||||
|
@ -38,7 +61,13 @@ export async function invoke(
|
|||
})
|
||||
);
|
||||
|
||||
return await provider.send(tx);
|
||||
if (provider.sendAndConfirm === undefined) {
|
||||
throw new Error(
|
||||
"This function requires 'Provider.sendAndConfirm' to be implemented."
|
||||
);
|
||||
}
|
||||
|
||||
return await provider.sendAndConfirm(tx, []);
|
||||
}
|
||||
|
||||
const GET_MULTIPLE_ACCOUNTS_LIMIT: number = 99;
|
||||
|
@ -87,3 +116,141 @@ async function getMultipleAccountsCore(
|
|||
};
|
||||
});
|
||||
}
|
||||
|
||||
// copy from @solana/web3.js that has a commitment param
|
||||
export async function simulateTransaction(
|
||||
connection: Connection,
|
||||
transaction: Transaction,
|
||||
signers?: Array<Signer>,
|
||||
commitment?: Commitment,
|
||||
includeAccounts?: boolean | Array<PublicKey>
|
||||
): Promise<RpcResponseAndContext<SimulatedTransactionResponse>> {
|
||||
if (signers && signers.length > 0) {
|
||||
transaction.sign(...signers);
|
||||
}
|
||||
|
||||
// @ts-expect-error
|
||||
const message = transaction._compile();
|
||||
const signData = message.serialize();
|
||||
// @ts-expect-error
|
||||
const wireTransaction = transaction._serialize(signData);
|
||||
const encodedTransaction = wireTransaction.toString("base64");
|
||||
const config: any = {
|
||||
encoding: "base64",
|
||||
commitment: commitment ?? connection.commitment,
|
||||
};
|
||||
|
||||
if (includeAccounts) {
|
||||
const addresses = (
|
||||
Array.isArray(includeAccounts) ? includeAccounts : message.nonProgramIds()
|
||||
).map((key) => key.toBase58());
|
||||
|
||||
config["accounts"] = {
|
||||
encoding: "base64",
|
||||
addresses,
|
||||
};
|
||||
}
|
||||
|
||||
if (signers) {
|
||||
config.sigVerify = true;
|
||||
}
|
||||
|
||||
const args = [encodedTransaction, config];
|
||||
// @ts-expect-error
|
||||
const unsafeRes = await connection._rpcRequest("simulateTransaction", args);
|
||||
const res = create(unsafeRes, SimulatedTransactionResponseStruct);
|
||||
if ("error" in res) {
|
||||
let logs;
|
||||
if ("data" in res.error) {
|
||||
logs = res.error.data.logs;
|
||||
if (logs && Array.isArray(logs)) {
|
||||
const traceIndent = "\n ";
|
||||
const logTrace = traceIndent + logs.join(traceIndent);
|
||||
console.error(res.error.message, logTrace);
|
||||
}
|
||||
}
|
||||
throw new SendTransactionError(
|
||||
"failed to simulate transaction: " + res.error.message,
|
||||
logs
|
||||
);
|
||||
}
|
||||
return res.result;
|
||||
}
|
||||
|
||||
// copy from @solana/web3.js
|
||||
function jsonRpcResult<T, U>(schema: Struct<T, U>) {
|
||||
return coerce(createRpcResult(schema), UnknownRpcResult, (value) => {
|
||||
if ("error" in value) {
|
||||
return value;
|
||||
} else {
|
||||
return {
|
||||
...value,
|
||||
result: create(value.result, schema),
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// copy from @solana/web3.js
|
||||
const UnknownRpcResult = createRpcResult(unknown());
|
||||
|
||||
// copy from @solana/web3.js
|
||||
function createRpcResult<T, U>(result: Struct<T, U>) {
|
||||
return union([
|
||||
pick({
|
||||
jsonrpc: literal("2.0"),
|
||||
id: string(),
|
||||
result,
|
||||
}),
|
||||
pick({
|
||||
jsonrpc: literal("2.0"),
|
||||
id: string(),
|
||||
error: pick({
|
||||
code: unknown(),
|
||||
message: string(),
|
||||
data: optional(any()),
|
||||
}),
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
// copy from @solana/web3.js
|
||||
function jsonRpcResultAndContext<T, U>(value: Struct<T, U>) {
|
||||
return jsonRpcResult(
|
||||
pick({
|
||||
context: pick({
|
||||
slot: number(),
|
||||
}),
|
||||
value,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// copy from @solana/web3.js
|
||||
const SimulatedTransactionResponseStruct = jsonRpcResultAndContext(
|
||||
pick({
|
||||
err: nullable(union([pick({}), string()])),
|
||||
logs: nullable(array(string())),
|
||||
accounts: optional(
|
||||
nullable(
|
||||
array(
|
||||
nullable(
|
||||
pick({
|
||||
executable: boolean(),
|
||||
owner: string(),
|
||||
lamports: number(),
|
||||
data: array(string()),
|
||||
rentEpoch: optional(number()),
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
unitsConsumed: optional(number()),
|
||||
})
|
||||
);
|
||||
|
||||
export type SuccessfulTxSimulationResponse = Omit<
|
||||
SimulatedTransactionResponse,
|
||||
"err"
|
||||
>;
|
||||
|
|
Loading…
Reference in New Issue