Multi-Agent Transactions
Multi-agent transactions allow multiple accounts to participate in the logic of a Move contract.
This can be used to require multiple parties agree to a transaction before executing or to use resources from multiple accounts.
Writing Multi-Agent Transactions
Section titled “Writing Multi-Agent Transactions”Creating and executing a multi-agent transaction follows a similar flow to the simple transaction flow, but with several notable differences.
-
Build the transaction by including secondarySignerAddresses with a list of each additional agent.
const transaction = await aptos.transaction.build.multiAgent({sender: alice.accountAddress,secondarySignerAddresses: [bob.accountAddress],data: {// REPLACE WITH YOUR MULTI-AGENT FUNCTION HEREfunction:"<REPLACE WITH YOUR MULTI AGENT MOVE ENTRY FUNCTION> (Syntax {address}::{module}::{function})",// Pass in arguments for the function you specify abovefunctionArguments: [],},}); -
(Optional) Simulate the transaction.
You can simulate the multi-agent transaction to preview the result before submitting it as follows:
const [userTransactionResponse] = await aptos.transaction.simulate.multiAgent({signerPublicKey: alice.publicKey,secondarySignersPublicKeys: [bob.publicKey],transaction,},);The
signerPublicKey
andsecondarySignersPublicKeys
inputs are optional and can be omitted to skip authentication key checks for the signers during simulation. If you want to skip the authentication key check for only some of the secondary signers, you can providesecondarySignersPublicKeys
with the public keys of the specific signers you want to check, usingundefined
as a placeholder for the others.For example, if
bob
andcarol
are secondary signers and you only want to checkcarol
’s authentication key, you can setsecondarySignersPublicKeys: [undefined, carol.publicKey]
, leavingundefined
as a placeholder forbob
. -
Sign once for each agent.
You will combine these signatures in the next step.
const aliceSenderAuthenticator = aptos.transaction.sign({signer: alice,transaction,});// Bob is a secondary signer for this transactionconst bobSenderAuthenticator = aptos.transaction.sign({signer: bob,transaction,}); -
Submit the transaction by combining all agent signatures via the additionalSignerAuthenticators parameter.
const committedTransaction = await aptos.transaction.submit.multiAgent({transaction,senderAuthenticator: aliceSenderAuthenticator,additionalSignersAuthenticators: [bobSenderAuthenticator],}); -
Lastly, wait for the transaction to resolve.
const executedTransaction = await aptos.waitForTransaction({transactionHash: committedTransaction.hash,});
Full TypeScript Multi-Agent Code Snippet
Section titled “Full TypeScript Multi-Agent Code Snippet”- Install
@aptos-labs/ts-sdk
by runningpnpm i @aptos-labs/ts-sdk
or using whichever package manager is most comfortable for you. - Update the below snippet to build a transaction that requires multi-agent signing.
- Replace the function and parameters below this comment:
// REPLACE WITH YOUR MULTI-AGENT FUNCTION HERE
- This customization is needed as there are no pre-made Aptos contracts which need multi-agent signatures. If you want to deploy your own example multi-agent contract, you can deploy the “transfer two by two” example Move contract.
- Replace the function and parameters below this comment:
/** * This example shows how to use the Aptos SDK to send a transaction. */
import { Account, Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
async function example() { console.log( "This example will create two accounts (Alice and Bob) and send a transaction transfering APT to Bob's account.", );
// 0. Setup the client and test accounts const config = new AptosConfig({ network: Network.DEVNET }); const aptos = new Aptos(config);
let alice = Account.generate(); let bob = Account.generate(); let carol = Account.generate();
console.log("=== Addresses ===\n"); console.log(`Alice's address is: ${alice.accountAddress}`); console.log(`Bob's address is: ${bob.accountAddress}`); console.log(`Carol's address is: ${carol.accountAddress}`);
console.log("\n=== Funding accounts ===\n"); await aptos.fundAccount({ accountAddress: alice.accountAddress, amount: 100_000_000, }); await aptos.fundAccount({ accountAddress: bob.accountAddress, amount: 100_000_000, }); await aptos.fundAccount({ accountAddress: carol.accountAddress, amount: 100_000_000, }); console.log("Done funding Alice, Bob, and Carol's accounts.");
// 1. Build console.log("\n=== 1. Building the transaction ===\n"); const transaction = await aptos.transaction.build.multiAgent({ sender: alice.accountAddress, secondarySignerAddresses: [bob.accountAddress], data: { // REPLACE WITH YOUR MULTI-AGENT FUNCTION HERE function: "<REPLACE WITH YOUR MULTI AGENT MOVE ENTRY FUNCTION> (Syntax {address}::{module}::{function})", functionArguments: [], }, }); console.log("Transaction:", transaction);
// 2. Simulate (Optional) console.log("\n === 2. Simulating Response (Optional) === \n"); const [userTransactionResponse] = await aptos.transaction.simulate.multiAgent( { signerPublicKey: alice.publicKey, secondarySignersPublicKeys: [bob.publicKey], transaction, }, ); console.log(userTransactionResponse);
// 3. Sign console.log("\n=== 3. Signing transaction ===\n"); const aliceSenderAuthenticator = aptos.transaction.sign({ signer: alice, transaction, }); const bobSenderAuthenticator = aptos.transaction.sign({ signer: bob, transaction, }); console.log(aliceSenderAuthenticator); console.log(bobSenderAuthenticator);
// 4. Submit console.log("\n=== 4. Submitting transaction ===\n"); const committedTransaction = await aptos.transaction.submit.multiAgent({ transaction, senderAuthenticator: aliceSenderAuthenticator, additionalSignersAuthenticators: [bobSenderAuthenticator], }); console.log("Submitted transaction hash:", committedTransaction.hash);
// 5. Wait for results console.log("\n=== 5. Waiting for result of transaction ===\n"); const executedTransaction = await aptos.waitForTransaction({ transactionHash: committedTransaction.hash, }); console.log(executedTransaction);}
example();
Common Errors
Section titled “Common Errors”NUMBER_OF_SIGNER_ARGUMENTS_MISMATCH
- This happens when you are attempting to do multi-agent signing for a function which does not require that number of accounts. For example, if you try using multiple signatures for a 0x1::aptos_account::transfer
function - it only expects one address, and so produces an error when more than one is provided.