web3.js: add accounts support to simulateTransaction (#19590)

* feat: add accounts support to simulateTransaction

* feat: introduce test for simulateTransaction on Message objects

* feat: populate transaction from message defaults to no signatures

* fix: remove unused constant

* fix: small formatting error

* fix: eslint and prettier were fighting over ternary indentation

* fix: make simulated transaction result accounts nullable
This commit is contained in:
Josh
2021-09-16 14:10:28 -07:00
committed by GitHub
parent 1a91621c29
commit 49d3d79459
4 changed files with 150 additions and 6 deletions

View File

@@ -439,15 +439,44 @@ const VersionResult = pick({
'feature-set': optional(number()),
});
export type SimulatedTransactionAccountInfo = {
/** `true` if this account's data contains a loaded program */
executable: boolean;
/** Identifier of the program that owns the account */
owner: string;
/** Number of lamports assigned to the account */
lamports: number;
/** Optional data assigned to the account */
data: string[];
/** Optional rent epoch info for account */
rentEpoch?: number;
};
export type SimulatedTransactionResponse = {
err: TransactionError | string | null;
logs: Array<string> | null;
accounts?: SimulatedTransactionAccountInfo[] | null;
unitsConsumed?: number;
};
const SimulatedTransactionResponseStruct = jsonRpcResultAndContext(
pick({
err: nullable(union([pick({}), string()])),
logs: nullable(array(string())),
accounts: optional(
nullable(
array(
pick({
executable: boolean(),
owner: string(),
lamports: number(),
data: array(string()),
rentEpoch: optional(number()),
}),
),
),
),
unitsConsumed: optional(number()),
}),
);
@@ -1679,6 +1708,8 @@ export type AccountInfo<T> = {
lamports: number;
/** Optional data assigned to the account */
data: T;
/** Optional rent epoch infor for account */
rentEpoch?: number;
};
/**
@@ -3430,9 +3461,17 @@ export class Connection {
* Simulate a transaction
*/
async simulateTransaction(
transaction: Transaction,
transactionOrMessage: Transaction | Message,
signers?: Array<Signer>,
includeAccounts?: boolean | Array<PublicKey>,
): Promise<RpcResponseAndContext<SimulatedTransactionResponse>> {
let transaction;
if (transactionOrMessage instanceof Transaction) {
transaction = transactionOrMessage;
} else {
transaction = Transaction.populate(transactionOrMessage);
}
if (transaction.nonceInfo && signers) {
transaction.sign(...signers);
} else {
@@ -3466,7 +3505,8 @@ export class Connection {
}
}
const signData = transaction.serializeMessage();
const message = transaction._compile();
const signData = message.serialize();
const wireTransaction = transaction._serialize(signData);
const encodedTransaction = wireTransaction.toString('base64');
const config: any = {
@@ -3474,6 +3514,19 @@ export class Connection {
commitment: this.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;
}