Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the documentation for the transaction simulation enhancement #702

Merged
merged 9 commits into from
Nov 15, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ const transaction = await aptos.transaction.build.multiAgent({
});
```

### Simulate the transaction by passing in all additional public keys to `secondarySignersPublicKeys`. (Optional)
### (Optional) Simulate the transaction.

You can simulate the multi-agent transaction to preview the result before submitting it as follows:
```ts filename="multi-agent.ts"
const [userTransactionResponse] = await aptos.transaction.simulate.multiAgent(
{
Expand All @@ -50,6 +51,7 @@ const [userTransactionResponse] = await aptos.transaction.simulate.multiAgent(
},
);
```
Note that `signerPublicKey` is optional and can be omitted to skip the authentication key check for the sender. Similarly, `secondarySignersPublicKeys` is optional and can be omitted to skip the authentication key check for all secondary signers. If you want to skip the authentication key check for only some of the secondary signers, you can provide `secondarySignersPublicKeys` with the public keys of the specific signers you want to check, using `undefined` as a placeholder for the others. For example, if `bob` and `carol` are secondary signers and you only want to check `carol`’s authentication key, you can set `secondarySignersPublicKeys: [undefined, carol.publicKey]`, leaving `undefined` as a placeholder for `bob`.
junkil-park marked this conversation as resolved.
Show resolved Hide resolved

### Sign once for each agent.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ async function example() {
await aptos.fundAccount({
accountAddress: sender.accountAddress,
amount: 100_000_000,
});
});

// 1. Build the transaction to preview the impact of it
const transaction = await aptos.transaction.build.simple({
Expand Down Expand Up @@ -56,6 +56,14 @@ example();

This will produce the same output as if the transaction was submitted.

The `signerPublicKey` parameter in `aptos.transaction.simulate.simple` is used to verify the signer’s authentication key during transaction simulation. This parameter is optional, allowing the simulation to bypass the authentication key check if omitted. To skip this check, the code can be modified as follows:
junkil-park marked this conversation as resolved.
Show resolved Hide resolved
```ts
// 2. Simulate to see what would happen if we execute this transaction, skipping the authentication key check
const [userTransactionResponse] = await aptos.transaction.simulate.simple({
transaction,
});
```

<details>
<summary>Example Output</summary>
```bash filename="Terminal"
Expand Down Expand Up @@ -156,6 +164,58 @@ This will produce the same output as if the transaction was submitted.

Look [here](../building-transactions.mdx) to see the full example of how to build, simulate, and submit a transaction.

# Simulating more advanced Transactions

You can also learn how to simulate more advanced transactions by looking at the following guides:
- [Sponsored Transactions](sponsoring-transactions.mdx)
- [Multi-Agent Transactions](multi-agent-transactions.mdx)
- Multisig V2 Transactions: See the next section for details.

## Simulating Multisig V2 Transactions
junkil-park marked this conversation as resolved.
Show resolved Hide resolved
For multisig transactions, there are two types of simulations:
junkil-park marked this conversation as resolved.
Show resolved Hide resolved
1. Simulating the target payload before it’s submitted on-chain, ignoring the voting status.
2. Simulating the on-chain approved multisig transaction for a final review and gas estimation before execution.
junkil-park marked this conversation as resolved.
Show resolved Hide resolved

To perform the first type, you can simulate the target payload as a sponsoring transaction with the multisig account as the sender, and set the fee payer to `0x0` to bypass gas fee payment during simulation. For example:
junkil-park marked this conversation as resolved.
Show resolved Hide resolved
```ts
// Generate a raw transaction with the multisig address as the sender,
// the provided entry function payload, and 0x0 as the fee payer address.
const transactionToSimulate = await aptos.transaction.build.simple({
sender: multisigAddress,
data: {
function: "0x1::aptos_account::transfer",
functionArguments: [recipient.accountAddress, 1_000_000],
},
withFeePayer: true,
});

// Simulate the transaction, skipping the public/auth key check for both the sender and the fee payer.
const [simulateMultisigTx] = await aptos.transaction.simulate.simple({
transaction: transactionToSimulate,
});
```
This setup allows you to preview the target payload's result before submitting it on-chain. Here, `signerPublicKey` is omitted to skip the authentication key check for the sender, as the multisig account does not have a public key. Additionally, `feePayerAddress` defaults to `0x0`, and `feePayerPublicKey` is omitted to bypass the gas fee payment during simulation. When this payload is later executed after submission and approval, the owner executing the transaction will cover the gas fee.

For the second type of simulation, where the on-chain multisig payload transaction is simulated for final validation and gas estimation, use the following approach:
```ts
const transactionPayload: TransactionPayloadMultiSig = await generateTransactionPayload({
multisigAddress,
function: "0x1::aptos_account::transfer",
functionArguments: [recipient.accountAddress, 1_000_000],
aptosConfig: config,
});

const rawTransaction = await generateRawTransaction({
aptosConfig: config,
sender: owner.accountAddress,
payload: transactionPayload,
});

const [simulateMultisigTx] = await aptos.transaction.simulate.simple({
signerPublicKey: owner.publicKey,
transaction: new SimpleTransaction(rawTransaction),
});
```
Note that `signerPublicKey` is optional and can be omitted if you wish to skip the authentication key check for the sender during simulation.

For the complete source code, see the [Multisig V2 Example](https://github.com/aptos-labs/aptos-ts-sdk/blob/main/examples/typescript-esm/multisig_v2.ts).
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,27 @@ const feePayerAuthenticator = aptos.transaction.signAsFeePayer({
})
```

### (Optional) When simulating the transaction, include the parameter `feePayerPublicKey: account.publicKey`
### (Optional) Simulate the sponsoring transaction

<Callout type="warning">
Currently, simulating a sponsor transaction must happen AFTER signing with the sponsor or it will fail to recognize this transaction has a sponsor.
</Callout>
You can simulate the sponsoring transaction to preview the result before submitting it as follows:
```ts filename="sponsor.ts"
const [userTransactionResponse] = await aptos.transaction.simulate.simple({
signerPublicKey: sender.publicKey,
transaction,
});
```
By default, the `transaction`’s `feePayerAddress` is set to `0x0`, which directs the transaction simulation to skip the gas fee payment. This allows you to simulate the transaction without specifying a fee payer. Note that `signerPublicKey` is optional and can be omitted if you want to skip the authentication key check for the sender.

You can also simulate the transaction with a specific fee payer by setting the `feePayerAddress` in the `transaction` object as follows:
```ts filename="sponsor.ts"
transaction.feePayerAddress = feePayer.accountAddress;
const [userTransactionResponse] = await aptos.transaction.simulate.simple({
signerPublicKey: sender.publicKey,
feePayerPublicKey: feePayer.publicKey,
transaction,
});
```
This setup will verify that `feePayer` has sufficient balance to cover the gas fee for the transaction. Similarly, `feePayerPublicKey` is optional and can be omitted if you wish to bypass the authentication key check for the fee payer.

### Submit the transaction by combining both signatures.

Expand Down
Loading