# Batch & Sponsor Transactions (via ERC-5792)

If you are building a Dapp, you communicate the actions to the wallet that the user performs. Instead of sending a single transaction one after the other, you can send an `array` of transactions, and the wallet will execute the bundle.

## EIP Definitions[​](#eip-definitions "Direct link to EIP Definitions")

* [ERC-5792](https://eips.ethereum.org/EIPS/eip-5792) standardizes the general communication between the dApp and the wallet, with batching as the default capability.
* [ERC-7677](https://eips.ethereum.org/EIPS/eip-7677) standardizes the communication of gas sponsorship capability.

![](/img/batch-transactions.png)

## Who is live?[​](#who-is-live "Direct link to Who is live?")

The following apps and wallets support smart capabilities.

### Wallets[​](#wallets "Direct link to Wallets")

| Wallet                                                              | Batching | Sponsor Gas     |
| ------------------------------------------------------------------- | -------- | --------------- |
| [Ambire](https://www.ambire.com/)                                   | ✅       | ERC-7677        |
| [Coinbase Smart Wallet](https://www.base.org/builders/smart-wallet) | ✅       | ERC-7677        |
| [Reown AppKit](https://reown.com/appkit)                            | ✅       | ERC-7677        |
| [thirdweb InApp](https://thirdweb.com)                              | ✅       | ERC-7677        |
| [Openfort](https://openfort.xyz)                                    | ✅       | ERC-7677        |
| [Safe{Wallet}](https://github.com/safe-global/safe-wallet-web)      | ✅       | via its Relayer |
| [Abstract Global](https://abs.xyz)                                  | ✅       | via its Relayer |
| [MetaMask Extension](https://metamask.io)                           | ✅       | ✖️              |

### Apps[​](#apps "Direct link to Apps")

| App                                             | Batching | Sponsor Gas |
| ----------------------------------------------- | -------- | ----------- |
| [PoolTogether Cabana](https://app.cabana.fi/)   | ✅       | ERC-767     |
| [revoke.cash](https://revoke.cash/)             | ✅       | ERC-7677    |
| [Lido](https://lido.fi)                         | ✅       | ✖️          |
| [Lifi](https://li.fi/)                          | ✅       | ✖️          |
| [Jumper.Exchange](https://jumper.exchange/)     | ✅       | ✖️          |
| [PoolTogether PoolTime](https://app.cabana.fi/) | ✅       | ✖️          |
| [Ekubo Exchange](https://ekubo.org/)            | ✅       | ✖️          |
| [Uniswap Exchange](https://app.uniswap.org)     | ✅       | ✖️          |
| [Vaults.fyi](https://app.vaults.fyi/)           | ✅       | ✖️          |
| [Spark](https://spark.fi/)                      | ✅       | ✖️          |
| [Reserve](https://app.reserve.org/)             | ✅       | ✖️          |
| [Matcha](https://matcha.xyz/)                   | ✅       | ✖️          |
| [Ethena](https://app.ethena.fi/)                | ✅       | ✖️          |
| [Fibrous](https://app.fibrous.finance/)         | ✅       | ✖️          |
| [PWN](https://app.pwn.xyz/)                     | ✅       | ✖️          |
| [Relay](https://relay.link/bridge)              | ✅       | ✖️          |
| [Relay](https://relay.link/bridge)              | ✅       | ✖️          |

## Reference Example[​](#reference-example "Direct link to Reference Example")

This example demonstrates communicating a batch of transactions and the gas sponsorship information directly to the wallet.

* Live Demo [batch-and-sponsor.on-fleek.app](https://batch-and-sponsor.on-fleek.app/)
* Source code [candidelabs/batch-sponsor-calls-instagas](https://github.com/candidelabs/batch-sponsor-calls-instagas)

## Quickstart with Viem/WAGMI[​](#quickstart-with-viemwagmi "Direct link to Quickstart with Viem/WAGMI")

### Installation[​](#installation "Direct link to Installation")

```
npm install viem wagmi
```

note

EIP-5792 is supported beginning with viem\@2.30 and wagmi\@2.15.4 and later

### Step 1: Get Wallet Capabilities[​](#step-1-get-wallet-capabilities "Direct link to Step 1: Get Wallet Capabilities")

Example using wagmi [useCapabilities](https://wagmi.sh/react/api/hooks/useCapabilities) hook

* Usage
* Response

```
import { useCapabilities } from 'wagmi';

const { data: capabilities } = useCapabilities({
    account: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", // account address
});

console.log(capabilities);
```

```
{
  "1": {
    "paymasterService": {
      "supported": true
    },
    "atomic": {
      "supported": true
    }
  },
  "10": {
    "paymasterService": {
      "supported": true
    },
    "atomic": {
      "supported": true
    }
  },
}
```

### Step 2: Batch & Sponsor Transactions[​](#step-2-batch--sponsor-transactions "Direct link to Step 2: Batch & Sponsor Transactions")

The example below uses WAGMI [useSendCalls](https://wagmi.sh/react/api/hooks/useSendCalls) hook that shows how to send two actions in a single one. Your app should fallback to sending normal transactions if the wallet doesn't support smart batching capabilities.

**Gas Sponsorship**

InstaGas is a no-code solution for dApps, provided that the wallet natively uses Candide's [Paymaster API](https://docs.candide.dev/wallet/paymaster/rpc-methods.md). However, this integration is not a barrier for apps wishing to sponsor gas fees for wallets that do not natively support Candide. In this step, we demonstrate how to use [ERC-7677](https://eips.ethereum.org/EIPS/eip-5792), which is an extension to ERC-5792 that standardizes the communication of gas sponsorship between the app and the wallet.

1. Create an App on [dashboard.candide.dev/api-keys](https://dashboard.candide.dev/api-keys)
2. Copy the paymaster URL link with the API key and fill in the `candidePaymasterUrl`
3. [Setup a Gas Policy](https://docs.candide.dev/instagas/overview/.md#how-it-works) and customise it with [your rules](https://docs.candide.dev/instagas/gas-policies.md)

```
import { useSendCalls } from 'wagmi'
import { useChainId, useSendTransaction } from 'wagmi';
import { toHex, zeroAddress } from 'viem';

const { sendCalls, data: id } = useSendCalls(); // to send batch & sponsored tx
const { sendTransaction } = useSendTransaction(); // to send standard tx
const chainId = useChainId();

const paymasterUrl = "https://api.candide.dev/paymaster/v3/network/APY_KEY";
const sponsorshipPolicyId = process.env.SPONSORSHIP_POLICY_ID;

const tx = {
  to: zeroAddress as Address,
  value: parseGwei('0'),
  data: zeroAddress as Hex,
};

const handleSendTx = () => {
  // if smart capabilities are supported, send a batched and optionally sponsored transaction
  try {
    if (!capabilities) {
      // Fallback to standard sendTransactions if capabilities are not available
      sendTransaction(tx);
      return;
    }

    const atomicStatus = capabilities[chainId].atomic?.status;
    const isAtomicSupported = atomicStatus === "supported" || atomicStatus === "ready";

    if (isAtomicSupported) {
      sendCalls({
        calls: [TEST_TX, TEST_TX],
        // and sponsor the tx, optionally with a sponsorshipPolicyId
        capabilities: {
          paymasterService: {
            url: paymasterUrl,
            optional: true,
            context: {
              sponsorshipPolicyId,
            }
          }
        },
      });
    } else {
      // if not, fallback to standard sendTransactions
      sendTransaction(tx);
    }
  } catch (err) {
    sendError(`Error sending transaction:'${err}`)
    console.log('Error sending transaction:', err);
  }
};
```

### Step 3: Track Transaction Status[​](#step-3-track-transaction-status "Direct link to Step 3: Track Transaction Status")

Example using wagmi [useCallsStatus](https://wagmi.sh/react/api/hooks/useCallsStatus) hook

```
import { useCallsStatus } from 'wagmi'

const { data: callStatusData, refetch: refetchCallStatus } = useCallsStatus({
  id: id?.id || '',
  query: {
    enabled: !!id,
    refetchInterval: (data) =>
      data.state.data?.status === "success" ? false : 1000,
  },
});
```

Optional: if you've lost track of the transaction, you can also delegate showing the status to the wallet directly using [useShowCallsStatus](https://wagmi.sh/react/api/hooks/useShowCallsStatus).

## ERC-5792 Spec[​](#erc-5792-spec "Direct link to ERC-5792 Spec")

[ERC-5792](https://eips.ethereum.org/EIPS/eip-5792) allows us to standardize JSON-RPC methods for apps to communicate bundle calls to wallets. The flow is usually in this order:

1. `wallet_getCapabilities`: App checks which capabilities the wallet supports (e.g., batching, sponsorship, etc.)
2. `wallet_sendCalls`: App sends the batch transactions.
3. `wallet_getCallsStatus`: App requests to get the status (e.g., pending, confirmed, failed).
4. `wallet_showCallsStatus`: Optional method for the app to request showing the status of the transaction on the wallet interface.

### wallet\_getCapabilities[​](#wallet_getcapabilities "Direct link to wallet_getCapabilities")

This RPC allows an application to request capabilities from a wallet (e.g. batch transactions, paymaster communication), without distinct discovery and permission requests.

#### Invocation[​](#invocation "Direct link to Invocation")

```
{ "method": "wallet_getCapabilities", "params": [address, [chainId]] }
```

#### Return[​](#return "Direct link to Return")

```
{ "result": { capabilities } }
```

* Example Request
* Example Response

```
["0xd46e8dd67c5d32be8058bb8eb970870f07244567", ["0x2105", "0x14A34"]]
```

```
{
  "0x0": {
    "flow-control": {
      "supported": true
    }
  },
  "0x2105": {
    "paymasterService": {
      "supported": true
    },
    "sessionKeys": {
      "supported": true
    }
  },
  "0x14A34": {
    "auxiliaryFunds": {
      "supported": true
    }
  }
}
```

### wallet\_sendCalls[​](#wallet_sendcalls "Direct link to wallet_sendCalls")

Requests that the wallet deliver a group of function calls on-chain from the user’s wallet.

#### Invocation[​](#invocation-1 "Direct link to Invocation")

```
{ "method": "wallet_sendCalls", "params": [{ chainId, from, calls }] }
```

#### Return[​](#return-1 "Direct link to Return")

```
{ "result": { transactionHash } }
```

* Example Request
* Example Response

```
[
  {
    "version": "1.0",
    "from": "0x0000000000000000000000000000000000000000",
    "chainId": "0x01",
    "atomicRequired": true,
    "calls": [
      {
        "to": "0x0000000000000000000000000000000000000000",
        "value": "0x",
        "data": "0x"
      },
      {
        "to": "0x0000000000000000000000000000000000000000",
        "value": "0x",
        "data": "0x"
      }
    ],
    "capabilities": {
      "paymasterService": {
          "url": "https://...",
          "optional": true,
          "context" {
            "sponsorshipPolicyId": "123",
          }
        }
      }
    }
  }
]
```

```
{
  "jsonrpc": "2.0",
  "id": 0,
  "result": "0xe67asds.."
}
```

### wallet\_getCallsStatus[​](#wallet_getcallsstatus "Direct link to wallet_getCallsStatus")

Returns the status of a bundle that was sent via `wallet_sendCalls`. The identifier of the bundle is the value returned from the `wallet_sendCalls` RPC.

#### Invocation[​](#invocation-2 "Direct link to Invocation")

```
{ "method": "wallet_getCallsStatus", "params": [transactionHash] }
```

#### Return[​](#return-2 "Direct link to Return")

```
{ "result": { calls } }
```

* Example Request
* Example Response

```
{
  "jsonrpc": "2.0",
  "id": 0,
  "result": "0xe67asds.."
}
```

```
{
  "version": "1.0",
  "chainId": "0x01",
  "id": "0x00000000000000000000000000000000000000000000000000000000000000000e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331",
  "status": 200,
  "atomic": true,
  "receipts": [
    {
      "logs": [
        {
          "address": "0xa922b54716264130634d6ff183747a8ead91a40b",
          "topics": [
            "0x5a2a90727cc9d000dd060b1132a5c977c9702bb3a52afe360c9c22f0e9451a68"
          ],
          "data": "0xabcd"
        }
      ],
      "status": "0x1",
      "blockHash": "0xf19bbafd9fd0124ec110b848e8de4ab4f62bf60c189524e54213285e7f540d4a",
      "blockNumber": "0xabcd",
      "gasUsed": "0xdef",
      "transactionHash": "0x9b7bb827c2e5e3c1a0a44dc53e573aa0b3af3bd1f9f5ed03071b100bb039eaff"
    }
  ]
}
```

### wallet\_showCallsStatus[​](#wallet_showcallsstatus "Direct link to wallet_showCallsStatus")

Requests that the wallet present UI showing the status of the given bundle. This allows apps to delegate the display of the function call status to the wallet, which can most accurately render the current status of the bundle. This RPC is intended to replace the typical user experience of a dapp linking to a block explorer for a given transaction hash.

#### Invocation[​](#invocation-3 "Direct link to Invocation")

```
{ "method": "wallet_showCallsStatus", "params": [transactionHash] }
```

#### Return[​](#return-3 "Direct link to Return")

```
{ "result": call }
```

* Example Request
* Example Response

```
{
  "jsonrpc": "2.0",
  "id": 0,
  "result": "0xe67asds.."
}
```

```
{
  status: "CONFIRMED"
  receipt: {
    logs: [..]
    success: true
    blockHash: "0x84b9f48e922c6b500fa07a1e94144cb1452f2466199fc726e807d31bae6b4e52"
    blockNumber: "0x7dbc3c"
    gasUsed: "0x25c8e"
    transactionHash: "0xcb8c43372800586bffc7521e0ca09f8828a87d4f0003f36ea68f9cbcf3e229f9"
  }
}
```
