| title | Batch Transactions with EIP-5792 - MetaMask Connect EVM | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| sidebar_label | Batch transactions | ||||||||
| description | Send multiple transactions atomically using wallet_sendCalls (EIP-5792), check capabilities, and track batch status in MetaMask. | ||||||||
| keywords |
|
import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
MetaMask Connect EVM supports atomic batch transactions through EIP-5792, allowing your dapp to submit multiple calls as a single atomic operation. Use wallet_getCapabilities to check support, wallet_sendCalls to submit the batch, and wallet_getCallsStatus to track execution.
Send and manage batch transactions in MetaMask, using the methods specified by EIP-5792:
wallet_getCapabilities- Query whether support for atomic batch transactions is available.wallet_sendCalls- Submit multiple transactions to be processed atomically by MetaMask.wallet_getCallsStatus- Track the status of your transaction batch.
An atomic batch transaction is a group of transactions that are executed together as a single unit. When a dapp requests to submit a batch of transactions atomically, MetaMask may prompt users to upgrade their externally owned account (EOA) to a MetaMask smart account. If the user accepts, MetaMask proceeds to upgrade the account and process the request as a single atomic transaction as specified by EIP-7702.
:::note MetaMask Smart Accounts MetaMask Smart Accounts are ERC-4337 smart contract accounts that support programmable account behavior and advanced features such as multi-signature approvals, transaction batching, and custom security policies.
See the Smart Accounts Kit documentation for more information about smart accounts and their capabilities. :::
The key benefits of atomic batch transactions include:
- Fewer steps and less friction - Users only need to review and approve a single wallet confirmation, instead of multiple confirmations. For example, users can confirm a spending cap and swap in one step instead of two.
- Faster completion times - Only a single atomic transaction is confirmed onchain, instead of multiple individual transactions.
- Reduced gas fees - When multiple transactions are executed atomically, users only need to pay a single gas fee.
This page describes how to send batch transactions directly in your dapp. You can also send batch transactions using third-party libraries.
Follow the JavaScript quickstart or Wagmi quickstart to install, initialize, and connect the EVM client.
Use wallet_getCapabilities to query
whether MetaMask supports atomic batch transactions for a specific address and specific chain IDs.
For example:
import { createEVMClient } from '@metamask/connect-evm'
const evmClient = await createEVMClient({
dapp: {
name: 'MetaMask Connect EVM Example',
url: window.location.href,
iconUrl: 'https://mydapp.com/icon.png', // Optional
},
api: {
supportedNetworks: {
'0x1': 'https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY',
'0xaa36a7': 'https://sepolia.infura.io/v3/YOUR_INFURA_API_KEY',
},
},
})
const provider = evmClient.getProvider()
const capabilities = await provider.request({
method: 'wallet_getCapabilities',
params: [
'0xd46e8dd67c5d32be8058bb8eb970870f07244567', // The user's wallet address.
['0x1', '0xaa36a7'], // (Optional) A list of chain IDs to query for.
],
})import { createEVMClient } from '@metamask/connect-evm'
import { createWalletClient, custom } from 'viem'
import { mainnet } from 'viem/chains'
const evmClient = await createEVMClient({
dapp: {
name: 'MetaMask Connect EVM Example',
url: window.location.href,
iconUrl: 'https://mydapp.com/icon.png', // Optional
},
api: {
supportedNetworks: {
'0x1': 'https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY',
'0xaa36a7': 'https://sepolia.infura.io/v3/YOUR_INFURA_API_KEY',
},
},
})
const provider = evmClient.getProvider()
const walletClient = createWalletClient({ chain: mainnet, transport: custom(provider) })
const address = await walletClient.getAddresses()
const capabilities = await walletClient.getCapabilities({
account: address[0],
})import { createEVMClient } from '@metamask/connect-evm'
import { useCapabilities } from 'wagmi'
const evmClient = await createEVMClient({
dapp: {
name: 'MetaMask Connect EVM Example',
url: window.location.href,
iconUrl: 'https://mydapp.com/icon.png', // Optional
},
api: {
supportedNetworks: {
'0x1': 'https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY',
'0xaa36a7': 'https://sepolia.infura.io/v3/YOUR_INFURA_API_KEY',
},
},
})
const provider = evmClient.getProvider()
const status = await useCapabilities({
account: '0xd46e8dd67c5d32be8058bb8eb970870f07244567',
})This method returns the status of the atomic capability for each chain ID.
For example:
{
"0x1": {
"atomic": {
"status": "ready"
}
},
"0xaa36a7": {
"atomic": {
"status": "supported"
}
}
}The atomic capability can have a status of supported or ready:
supportedmeans MetaMask supports atomic batch transactions for the account and chain ID.readymeans MetaMask will prompt the user to upgrade their account to a MetaMask smart account. If the user approves, thestatuswill upgrade tosupported.
If the atomic capability is not supported or ready for a specified chain ID, MetaMask will not return anything for that chain ID.
If you don't specify any chain IDs in wallet_getCapabilities, MetaMask will return all chains in the wallet where the atomic capability is supported or ready.
Supported networks
- Ethereum Mainnet and Sepolia
- Gnosis Mainnet and Chiado
- BNB Smart Chain Mainnet and Testnet
- OP Mainnet and Sepolia
- Base Mainnet and Sepolia
- Polygon Mainnet and Amoy
- Arbitrum Mainnet, Sepolia, and Nova
- Unichain Mainnet and Sepolia
- Berachain Mainnet and Bepolia
MetaMask supports this feature on more networks as they adopt EIP-7702.
:::note Atomic batch unsupported
- If the user has already upgraded their account to a third-party smart contract account, MetaMask does not currently support atomic batch transactions for that account.
- If atomic batch is not supported, fall back to
eth_sendTransactioninstead ofwallet_sendCalls, andeth_getTransactionReceiptinstead ofwallet_getCallsStatus. :::
Use wallet_sendCalls to submit a batch of transactions.
For example:
const result = await provider.request({
method: 'wallet_sendCalls',
params: [
{
version: '2.0.0', // The version of the API format. This must be 2.0.0.
from: '0xd46e8dd67c5d32be8058bb8eb970870f07244567', // The sender's address.
chainId: '0xaa36a7', // The chain ID, which must match the currently selected network.
atomicRequired: true, // Whether or not atomicity is required.
calls: [
// The list of calls to send as a batch.
{
to: '0xd46e8dd67c5d32be8058bb8eb970870f07244567',
value: '0x0',
},
{
to: '0xd46e8dd67c5d32be8058bb8eb970870f07244567',
value: '0x0',
},
],
},
],
})const { id } = await walletClient.sendCalls({
account: address[0],
calls: [
{
to: '0xd46e8dd67c5d32be8058bb8eb970870f07244567',
value: '0x0',
},
{
to: '0xd46e8dd67c5d32be8058bb8eb970870f07244567',
value: '0x0',
},
],
})import { useSendCalls } from 'wagmi'
const { sendCalls, data } = useSendCalls()
sendCalls({
calls: [
{
to: '0xd46e8dd67c5d32be8058bb8eb970870f07244567',
value: '0x0',
},
{
to: '0xd46e8dd67c5d32be8058bb8eb970870f07244567',
value: '0x0',
},
],
}):::note Atomic required parameter
MetaMask only supports using wallet_sendCalls to send atomic batch transactions (not sequential batch transactions),
so atomicRequired can be set to either true or false.
If the atomic capability is not supported, wallet_sendCalls will return an error.
:::
This method returns a batch ID that you can use to track the status of the batch. For example:
{
"id": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"
}Use wallet_getCallsStatus to track
the status of the submitted batch of transactions, using the batch ID returned by wallet_sendCalls.
For example:
const status = await provider.request({
method: 'wallet_getCallsStatus',
params: [
'0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331', // Batch ID.
],
})const { result } = await walletClient.getCallsStatus({
id: '0x1234567890abcdef',
})import { getCallsStatus } from 'wagmi'
const status = await getCallsStatus(config, { id: data.id })This method returns status information about the batch of transactions, including:
- The status code of the batch.
- Whether the batch was executed atomically.
Currently, this will always be
trueif the execution was successful. - A list of transaction receipts.
For example:
{
"version": "2.0.0",
"chainId": "0xaa36a7",
"id": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331",
"status": 200, // Status code. 200 means confirmed.
"atomic": true, // Whether the calls were executed atomically.
"receipts": [
// List of transaction receipts.
{
"logs": [
{
"address": "0xa922b54716264130634d6ff183747a8ead91a40b",
"topics": ["0x5a2a90727cc9d000dd060b1132a5c977c9702bb3a52afe360c9c22f0e9451a68"],
"data": "0xabcd"
}
],
"status": "0x1",
"blockHash": "0xf19bbafd9fd0124ec110b848e8de4ab4f62bf60c189524e54213285e7f540d4a",
"blockNumber": "0xabcd",
"gasUsed": "0xdef",
"transactionHash": "0x9b7bb827c2e5e3c1a0a44dc53e573aa0b3af3bd1f9f5ed03071b100bb039eaff"
}
]
}:::note If the calls were executed atomically in a single transaction, a single receipt is returned.
In some cases, calls can be executed atomically but in multiple transactions (for example, using
eth_bundle on an L2 network resistant to reorgs).
In these cases, atomic is true but multiple receipts are returned.
:::
Send batch transactions using the following third-party libraries that support EIP-5792:
- See the MetaMask 7702/5792 Readiness dapp to quickly test sending batch transactions.
- Follow the tutorial to send atomic batch transactions using Wagmi, upgrading an externally owned account to a smart account.
- See the MetaMask Smart Accounts Kit documentation for more information about MetaMask Smart Accounts and their capabilities.
- See the following topics in the MetaMask end user documentation: