This reverts commit 064dde4b1a
.
This commit is contained in:
parent
064dde4b1a
commit
1dc16d6642
|
@ -23,7 +23,6 @@ The minor version will be incremented upon a breaking change and the patch versi
|
|||
- client: Add support for multithreading to the rust client: use flag `--multithreaded` ([#2321](https://github.com/coral-xyz/anchor/pull/2321)).
|
||||
- client: Add `async_rpc` a method which returns a nonblocking solana rpc client ([2322](https://github.com/coral-xyz/anchor/pull/2322)).
|
||||
- avm, cli: Use the `rustls-tls` feature of `reqwest` so that users don't need OpenSSL installed ([#2385](https://github.com/coral-xyz/anchor/pull/2385)).
|
||||
- ts: Add `VersionedTransaction` support. Methods in the `Provider` class and `Wallet` interface now use the argument `tx: Transaction | VersionedTransaction` ([2407](https://github.com/coral-xyz/anchor/pull/2407)).
|
||||
- cli: Add `--arch sbf` option to compile programs using `cargo build-sbf` ([#2398](https://github.com/coral-xyz/anchor/pull/2398)).
|
||||
|
||||
### Fixes
|
||||
|
|
|
@ -6,8 +6,6 @@ import {
|
|||
SystemProgram,
|
||||
Message,
|
||||
VersionedTransaction,
|
||||
AddressLookupTableProgram,
|
||||
TransactionMessage,
|
||||
} from "@solana/web3.js";
|
||||
import {
|
||||
TOKEN_PROGRAM_ID,
|
||||
|
@ -63,104 +61,6 @@ const miscTest = (
|
|||
assert.strictEqual(dataAccount.data, 99);
|
||||
});
|
||||
|
||||
it("Can send VersionedTransaction", async () => {
|
||||
// Create the lookup table
|
||||
const recentSlot = await provider.connection.getSlot();
|
||||
const [loookupTableInstruction, lookupTableAddress] =
|
||||
AddressLookupTableProgram.createLookupTable({
|
||||
authority: provider.publicKey,
|
||||
payer: provider.publicKey,
|
||||
recentSlot,
|
||||
});
|
||||
const extendInstruction = AddressLookupTableProgram.extendLookupTable({
|
||||
payer: provider.publicKey,
|
||||
authority: provider.publicKey,
|
||||
lookupTable: lookupTableAddress,
|
||||
addresses: [provider.publicKey, SystemProgram.programId],
|
||||
});
|
||||
let createLookupTableTx = new VersionedTransaction(
|
||||
new TransactionMessage({
|
||||
instructions: [loookupTableInstruction, extendInstruction],
|
||||
payerKey: program.provider.publicKey,
|
||||
recentBlockhash: (await provider.connection.getLatestBlockhash())
|
||||
.blockhash,
|
||||
}).compileToV0Message()
|
||||
);
|
||||
await provider.sendAndConfirm(createLookupTableTx, [], {
|
||||
skipPreflight: true,
|
||||
});
|
||||
|
||||
// Use the lookup table in a transaction
|
||||
const transferAmount = 1_000_000;
|
||||
const lookupTableAccount = await provider.connection
|
||||
.getAddressLookupTable(lookupTableAddress)
|
||||
.then((res) => res.value);
|
||||
const target = anchor.web3.Keypair.generate();
|
||||
let transferInstruction = SystemProgram.transfer({
|
||||
fromPubkey: provider.publicKey,
|
||||
lamports: transferAmount,
|
||||
toPubkey: target.publicKey,
|
||||
});
|
||||
let transferUsingLookupTx = new VersionedTransaction(
|
||||
new TransactionMessage({
|
||||
instructions: [transferInstruction],
|
||||
payerKey: program.provider.publicKey,
|
||||
recentBlockhash: (await provider.connection.getLatestBlockhash())
|
||||
.blockhash,
|
||||
}).compileToV0Message([lookupTableAccount])
|
||||
);
|
||||
await provider.simulate(transferUsingLookupTx, [], "processed");
|
||||
await provider.sendAndConfirm(transferUsingLookupTx, [], {
|
||||
skipPreflight: true,
|
||||
commitment: "confirmed",
|
||||
});
|
||||
let newBalance = await provider.connection.getBalance(
|
||||
target.publicKey,
|
||||
"confirmed"
|
||||
);
|
||||
assert.strictEqual(newBalance, transferAmount);
|
||||
|
||||
// Test sendAll with versioned transaction
|
||||
let oneTransferUsingLookupTx = new VersionedTransaction(
|
||||
new TransactionMessage({
|
||||
instructions: [
|
||||
SystemProgram.transfer({
|
||||
fromPubkey: provider.publicKey,
|
||||
// Needed to make the transactions distinct
|
||||
lamports: transferAmount + 1,
|
||||
toPubkey: target.publicKey,
|
||||
}),
|
||||
],
|
||||
payerKey: program.provider.publicKey,
|
||||
recentBlockhash: (await provider.connection.getLatestBlockhash())
|
||||
.blockhash,
|
||||
}).compileToV0Message([lookupTableAccount])
|
||||
);
|
||||
let twoTransferUsingLookupTx = new VersionedTransaction(
|
||||
new TransactionMessage({
|
||||
instructions: [
|
||||
SystemProgram.transfer({
|
||||
fromPubkey: provider.publicKey,
|
||||
lamports: transferAmount,
|
||||
toPubkey: target.publicKey,
|
||||
}),
|
||||
],
|
||||
payerKey: program.provider.publicKey,
|
||||
recentBlockhash: (await provider.connection.getLatestBlockhash())
|
||||
.blockhash,
|
||||
}).compileToV0Message([lookupTableAccount])
|
||||
);
|
||||
await provider.sendAll(
|
||||
[{ tx: oneTransferUsingLookupTx }, { tx: twoTransferUsingLookupTx }],
|
||||
{ skipPreflight: true, commitment: "confirmed" }
|
||||
);
|
||||
newBalance = await provider.connection.getBalance(
|
||||
target.publicKey,
|
||||
"confirmed"
|
||||
);
|
||||
assert.strictEqual(newBalance, transferAmount * 3 + 1);
|
||||
});
|
||||
|
||||
it("Can embed programs into genesis from the Anchor.toml", async () => {
|
||||
const pid = new anchor.web3.PublicKey(
|
||||
"FtMNMKp9DZHKWUyVAsj3Q5QV8ow4P3fUPP7ZrWEQJzKr"
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
import { Buffer } from "buffer";
|
||||
import {
|
||||
Keypair,
|
||||
PublicKey,
|
||||
Transaction,
|
||||
VersionedTransaction,
|
||||
} from "@solana/web3.js";
|
||||
import { Keypair, PublicKey, Transaction } from "@solana/web3.js";
|
||||
import { Wallet } from "./provider";
|
||||
|
||||
/**
|
||||
|
@ -35,26 +30,14 @@ export default class NodeWallet implements Wallet {
|
|||
return new NodeWallet(payer);
|
||||
}
|
||||
|
||||
async signTransaction<T extends Transaction | VersionedTransaction>(
|
||||
tx: T
|
||||
): Promise<T> {
|
||||
if (tx instanceof VersionedTransaction) {
|
||||
tx.sign([this.payer]);
|
||||
} else {
|
||||
async signTransaction(tx: Transaction): Promise<Transaction> {
|
||||
tx.partialSign(this.payer);
|
||||
}
|
||||
return tx;
|
||||
}
|
||||
|
||||
async signAllTransactions<T extends Transaction | VersionedTransaction>(
|
||||
txs: T[]
|
||||
): Promise<T[]> {
|
||||
async signAllTransactions(txs: Transaction[]): Promise<Transaction[]> {
|
||||
return txs.map((t) => {
|
||||
if (t instanceof VersionedTransaction) {
|
||||
t.sign([this.payer]);
|
||||
} else {
|
||||
t.partialSign(this.payer);
|
||||
}
|
||||
return t;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -9,8 +9,6 @@ import {
|
|||
Commitment,
|
||||
SendTransactionError,
|
||||
SendOptions,
|
||||
VersionedTransaction,
|
||||
RpcResponseAndContext,
|
||||
} from "@solana/web3.js";
|
||||
import { bs58 } from "./utils/bytes/index.js";
|
||||
import { isBrowser } from "./utils/common.js";
|
||||
|
@ -24,24 +22,21 @@ export default interface Provider {
|
|||
readonly publicKey?: PublicKey;
|
||||
|
||||
send?(
|
||||
tx: Transaction | VersionedTransaction,
|
||||
tx: Transaction,
|
||||
signers?: Signer[],
|
||||
opts?: SendOptions
|
||||
): Promise<TransactionSignature>;
|
||||
sendAndConfirm?(
|
||||
tx: Transaction | VersionedTransaction,
|
||||
tx: Transaction,
|
||||
signers?: Signer[],
|
||||
opts?: ConfirmOptions
|
||||
): Promise<TransactionSignature>;
|
||||
sendAll?<T extends Transaction | VersionedTransaction>(
|
||||
txWithSigners: {
|
||||
tx: T;
|
||||
signers?: Signer[];
|
||||
}[],
|
||||
sendAll?(
|
||||
txWithSigners: { tx: Transaction; signers?: Signer[] }[],
|
||||
opts?: ConfirmOptions
|
||||
): Promise<Array<TransactionSignature>>;
|
||||
simulate?(
|
||||
tx: Transaction | VersionedTransaction,
|
||||
tx: Transaction,
|
||||
signers?: Signer[],
|
||||
commitment?: Commitment,
|
||||
includeAccounts?: boolean | PublicKey[]
|
||||
|
@ -129,7 +124,7 @@ export class AnchorProvider implements Provider {
|
|||
* @param opts Transaction confirmation options.
|
||||
*/
|
||||
async sendAndConfirm(
|
||||
tx: Transaction | VersionedTransaction,
|
||||
tx: Transaction,
|
||||
signers?: Signer[],
|
||||
opts?: ConfirmOptions
|
||||
): Promise<TransactionSignature> {
|
||||
|
@ -137,23 +132,17 @@ export class AnchorProvider implements Provider {
|
|||
opts = this.opts;
|
||||
}
|
||||
|
||||
if (tx instanceof VersionedTransaction) {
|
||||
if (signers) {
|
||||
tx.sign(signers);
|
||||
}
|
||||
} else {
|
||||
tx.feePayer = tx.feePayer ?? this.wallet.publicKey;
|
||||
tx.feePayer = tx.feePayer || this.wallet.publicKey;
|
||||
|
||||
tx.recentBlockhash = (
|
||||
await this.connection.getLatestBlockhash(opts.preflightCommitment)
|
||||
).blockhash;
|
||||
|
||||
if (signers) {
|
||||
for (const signer of signers) {
|
||||
tx.partialSign(signer);
|
||||
}
|
||||
}
|
||||
}
|
||||
tx = await this.wallet.signTransaction(tx);
|
||||
(signers ?? []).forEach((kp) => {
|
||||
tx.partialSign(kp);
|
||||
});
|
||||
|
||||
const rawTx = tx.serialize();
|
||||
|
||||
try {
|
||||
|
@ -166,14 +155,10 @@ export class AnchorProvider implements Provider {
|
|||
// (the json RPC does not support any shorter than "confirmed" for 'getTransaction')
|
||||
// because that will see the tx sent with `sendAndConfirmRawTransaction` no matter which
|
||||
// commitment `sendAndConfirmRawTransaction` used
|
||||
const txSig = bs58.encode(
|
||||
tx instanceof VersionedTransaction
|
||||
? tx.signatures?.[0] || new Uint8Array()
|
||||
: tx.signature ?? new Uint8Array()
|
||||
const failedTx = await this.connection.getTransaction(
|
||||
bs58.encode(tx.signature!),
|
||||
{ commitment: "confirmed" }
|
||||
);
|
||||
const failedTx = await this.connection.getTransaction(txSig, {
|
||||
commitment: "confirmed",
|
||||
});
|
||||
if (!failedTx) {
|
||||
throw err;
|
||||
} else {
|
||||
|
@ -188,44 +173,34 @@ export class AnchorProvider implements Provider {
|
|||
|
||||
/**
|
||||
* Similar to `send`, but for an array of transactions and signers.
|
||||
* All transactions need to be of the same type, it doesn't support a mix of `VersionedTransaction`s and `Transaction`s.
|
||||
*
|
||||
* @param txWithSigners Array of transactions and signers.
|
||||
* @param opts Transaction confirmation options.
|
||||
*/
|
||||
async sendAll<T extends Transaction | VersionedTransaction>(
|
||||
txWithSigners: {
|
||||
tx: T;
|
||||
signers?: Signer[];
|
||||
}[],
|
||||
async sendAll(
|
||||
txWithSigners: { tx: Transaction; signers?: Signer[] }[],
|
||||
opts?: ConfirmOptions
|
||||
): Promise<Array<TransactionSignature>> {
|
||||
if (opts === undefined) {
|
||||
opts = this.opts;
|
||||
}
|
||||
const recentBlockhash = (
|
||||
await this.connection.getLatestBlockhash(opts.preflightCommitment)
|
||||
).blockhash;
|
||||
const blockhash = await this.connection.getLatestBlockhash(
|
||||
opts.preflightCommitment
|
||||
);
|
||||
|
||||
let txs = txWithSigners.map((r) => {
|
||||
if (r.tx instanceof VersionedTransaction) {
|
||||
let tx: VersionedTransaction = r.tx;
|
||||
if (r.signers) {
|
||||
tx.sign(r.signers);
|
||||
}
|
||||
return tx;
|
||||
} else {
|
||||
let tx: Transaction = r.tx;
|
||||
let tx = r.tx;
|
||||
let signers = r.signers ?? [];
|
||||
|
||||
tx.feePayer = tx.feePayer ?? this.wallet.publicKey;
|
||||
tx.recentBlockhash = recentBlockhash;
|
||||
tx.feePayer = tx.feePayer || this.wallet.publicKey;
|
||||
|
||||
tx.recentBlockhash = blockhash.blockhash;
|
||||
|
||||
signers.forEach((kp) => {
|
||||
tx.partialSign(kp);
|
||||
});
|
||||
|
||||
return tx;
|
||||
}
|
||||
});
|
||||
|
||||
const signedTxs = await this.wallet.signAllTransactions(txs);
|
||||
|
@ -248,14 +223,10 @@ export class AnchorProvider implements Provider {
|
|||
// (the json RPC does not support any shorter than "confirmed" for 'getTransaction')
|
||||
// because that will see the tx sent with `sendAndConfirmRawTransaction` no matter which
|
||||
// commitment `sendAndConfirmRawTransaction` used
|
||||
const txSig = bs58.encode(
|
||||
tx instanceof VersionedTransaction
|
||||
? tx.signatures?.[0] || new Uint8Array()
|
||||
: tx.signature ?? new Uint8Array()
|
||||
const failedTx = await this.connection.getTransaction(
|
||||
bs58.encode(tx.signature!),
|
||||
{ commitment: "confirmed" }
|
||||
);
|
||||
const failedTx = await this.connection.getTransaction(txSig, {
|
||||
commitment: "confirmed",
|
||||
});
|
||||
if (!failedTx) {
|
||||
throw err;
|
||||
} else {
|
||||
|
@ -282,42 +253,29 @@ export class AnchorProvider implements Provider {
|
|||
* @param opts Transaction confirmation options.
|
||||
*/
|
||||
async simulate(
|
||||
tx: Transaction | VersionedTransaction,
|
||||
tx: Transaction,
|
||||
signers?: Signer[],
|
||||
commitment?: Commitment,
|
||||
includeAccounts?: boolean | PublicKey[]
|
||||
): Promise<SuccessfulTxSimulationResponse> {
|
||||
let recentBlockhash = (
|
||||
tx.feePayer = tx.feePayer || this.wallet.publicKey;
|
||||
|
||||
tx.recentBlockhash = (
|
||||
await this.connection.getLatestBlockhash(
|
||||
commitment ?? this.connection.commitment
|
||||
)
|
||||
).blockhash;
|
||||
|
||||
let result: RpcResponseAndContext<SimulatedTransactionResponse>;
|
||||
if (tx instanceof VersionedTransaction) {
|
||||
if (signers) {
|
||||
tx.sign(signers);
|
||||
tx = await this.wallet.signTransaction(tx);
|
||||
}
|
||||
|
||||
// Doesn't support includeAccounts which has been changed to something
|
||||
// else in later versions of this function.
|
||||
result = await this.connection.simulateTransaction(tx, { commitment });
|
||||
} else {
|
||||
tx.feePayer = tx.feePayer || this.wallet.publicKey;
|
||||
tx.recentBlockhash = recentBlockhash;
|
||||
|
||||
if (signers) {
|
||||
tx = await this.wallet.signTransaction(tx);
|
||||
}
|
||||
result = await simulateTransaction(
|
||||
const result = await simulateTransaction(
|
||||
this.connection,
|
||||
tx,
|
||||
signers,
|
||||
commitment,
|
||||
includeAccounts
|
||||
);
|
||||
}
|
||||
|
||||
if (result.value.err) {
|
||||
throw new SimulateError(result.value);
|
||||
|
@ -345,12 +303,8 @@ export type SendTxRequest = {
|
|||
* Wallet interface for objects that can be used to sign provider transactions.
|
||||
*/
|
||||
export interface Wallet {
|
||||
signTransaction<T extends Transaction | VersionedTransaction>(
|
||||
tx: T
|
||||
): Promise<T>;
|
||||
signAllTransactions<T extends Transaction | VersionedTransaction>(
|
||||
txs: T[]
|
||||
): Promise<T[]>;
|
||||
signTransaction(tx: Transaction): Promise<Transaction>;
|
||||
signAllTransactions(txs: Transaction[]): Promise<Transaction[]>;
|
||||
publicKey: PublicKey;
|
||||
}
|
||||
|
||||
|
@ -358,7 +312,7 @@ export interface Wallet {
|
|||
// a better error if 'confirmTransaction` returns an error status
|
||||
async function sendAndConfirmRawTransaction(
|
||||
connection: Connection,
|
||||
rawTransaction: Buffer | Uint8Array,
|
||||
rawTransaction: Buffer,
|
||||
options?: ConfirmOptions
|
||||
): Promise<TransactionSignature> {
|
||||
const sendOptions = options && {
|
||||
|
|
Loading…
Reference in New Issue