Skip to content
🎉 Welcome to the new Aptos Docs! Click here to submit feedback!
BuildSDKsTypeScript SDKTransactionsMulti-Agent Transactions

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

Creating and executing a multi-agent transaction follows a similar flow to the simple transaction flow, but with several notable differences.

Instead of .simple, multi-agent transaction functions use .multiAgent.

Build the transaction by including secondarySignerAddresses with a list of each additional agent.

Make sure to replace the function field below with your entry function that requires multiple agents to sign.

multi-agent.ts
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})",
    // Pass in arguments for the function you specify above
    functionArguments: [],
  },
});

(Optional) Simulate the transaction.

You can simulate the multi-agent transaction to preview the result before submitting it as follows:

multi-agent.ts
const [userTransactionResponse] = await aptos.transaction.simulate.multiAgent(
  {
    signerPublicKey: alice.publicKey,
    secondarySignersPublicKeys: [bob.publicKey],
    transaction,
  },
);

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.

Sign once for each agent.

You will combine these signatures in the next step.

multi-agent.ts
const aliceSenderAuthenticator = aptos.transaction.sign({
  signer: alice,
  transaction,
});
// Bob is a secondary signer for this transaction
const bobSenderAuthenticator = aptos.transaction.sign({
  signer: bob,
  transaction,
});

Submit the transaction by combining all agent signatures via the additionalSignerAuthenticators parameter.

multi-agent.ts
const committedTransaction = await aptos.transaction.submit.multiAgent({
  transaction,
  senderAuthenticator: aliceSenderAuthenticator,
  additionalSignersAuthenticators: [bobSenderAuthenticator],
});

Lastly, wait for the transaction to resolve.

multi-agent.ts
const executedTransaction = await aptos.waitForTransaction({
  transactionHash: committedTransaction.hash,
});

Full TypeScript Multi-Agent Code Snippet

⚠️

The below snippet needs light editing to work properly! (See below steps)

  1. Install @aptos-labs/ts-sdk by running pnpm i @aptos-labs/ts-sdk or using whichever package manager is most comfortable for you.
  2. Update the below snippet to build a transaction that requires multi-agent signing.
    1. Replace the function and parameters below this comment: // REPLACE WITH YOUR MULTI-AGENT FUNCTION HERE
    2. 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.
multi-agent.ts
/**
 * 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

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.