Rust SDK - 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 regular transaction flow, but with several notable differences.
-
Build the raw transaction, then wrap it in
MultiAgentRawTransactionwith each additional signer.let payload = TransactionPayload::EntryFunction(EntryFunction {module: MoveModuleId::from_str_strict("0x1::aptos_account")?,function: "transfer".to_string(),type_args: vec![],args: vec![aptos_bcs::to_bytes(&secondary_signer.address())?,aptos_bcs::to_bytes(&1000u64)?,],});let sequence_number = aptos.get_sequence_number(primary_signer.address()).await?;let raw_txn = TransactionBuilder::new().sender(primary_signer.address()).sequence_number(sequence_number).payload(payload).chain_id(aptos.chain_id()).expiration_from_now(600).build()?;let multi_agent_txn =MultiAgentRawTransaction::new(raw_txn, vec![secondary_signer.address()]); -
Sign with the primary signer and each additional signer.
let signed_txn = sign_multi_agent_transaction(&multi_agent_txn,&primary_signer,&[&secondary_signer as &dyn Account],)?; -
Submit and wait for the transaction.
let result = aptos.submit_and_wait(&signed_txn, None).await?;
Rust Multi-Agent Code Sample
Section titled “Rust Multi-Agent Code Sample”use aptos_sdk::{ Aptos, AptosConfig, account::{Account, Ed25519Account}, transaction::{ EntryFunction, TransactionBuilder, TransactionPayload, builder::sign_multi_agent_transaction, types::MultiAgentRawTransaction, }, types::MoveModuleId,};
#[tokio::main]async fn main() -> anyhow::Result<()> { let aptos = Aptos::new(AptosConfig::devnet())?; let primary_signer = Ed25519Account::generate(); let secondary_signer = Ed25519Account::generate();
aptos .fund_account(primary_signer.address(), 1_000_000_000) .await?; aptos .fund_account(secondary_signer.address(), 100_000_000) .await?;
let payload = TransactionPayload::EntryFunction(EntryFunction { module: MoveModuleId::from_str_strict("0x1::aptos_account")?, function: "transfer".to_string(), type_args: vec![], args: vec![ aptos_bcs::to_bytes(&secondary_signer.address())?, aptos_bcs::to_bytes(&1000u64)?, ], }); let sequence_number = aptos.get_sequence_number(primary_signer.address()).await?; let raw_txn = TransactionBuilder::new() .sender(primary_signer.address()) .sequence_number(sequence_number) .payload(payload) .chain_id(aptos.chain_id()) .expiration_from_now(600) .build()?; let multi_agent_txn = MultiAgentRawTransaction::new(raw_txn, vec![secondary_signer.address()]); let signed_txn = sign_multi_agent_transaction( &multi_agent_txn, &primary_signer, &[&secondary_signer as &dyn Account], )?; match aptos.submit_and_wait(&signed_txn, None).await { Ok(result) => println!("Submitted: {:?}", result.data.get("hash")), Err(err) => { println!("Expected without a multi-signer entry function: {err}"); } }
Ok(())}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.