---
eip: 5792
title: Wallet Call API
description: Adds JSON-RPC methods for sending multiple calls from the user's wallet, and checking their status
author: Moody Salem (@moodysalem), Lukas Rosario (@lukasrosario), Wilson Cusack (@wilsoncusack), Dror Tirosh (@drortirosh), Jake Moxey (@jxom), Derek Rein (@arein), Alex Forshtat (@forshtat), Sam Wilson (@SamWilsn) <sam@binarycake.ca>, Borislav Itskov (@Oxbobby), Joao Tavares (@cryptotavares), Adam Fuller (@azf20), Philip Liao (@phil-ociraptor), bumblefudge (@bumblefudge)
discussions-to: https://ethereum-magicians.org/t/eip-5792-wallet-abstract-transaction-send-api/11374
status: Final
type: Standards Track
category: Interface
created: 2022-10-17
requires: 1193
---

## Abstract

Defines new JSON-RPC methods which enable apps to ask a wallet to process a batch of onchain write calls and to check on the status of those calls.
Applications can specify that these onchain calls be executed taking advantage of specific capabilities previously expressed by the wallet; an additional, novel wallet RPC is defined to enable apps to query the wallet for those capabilities.

## Motivation

The current methods used to send transactions from the user wallet and check their status are `eth_sendTransaction` and `eth_getTransactionReceipt`.

The current methods used to send transactions from the user wallet and check their status do not meet modern developer demands and cannot accommodate new transaction formats. Even the name–- `eth_sendTransaction`-– is an artifact of a time when nodes served as wallets.

Today, developers want to send multiple calls batched together in a single RPC call, which many smart accounts can, in turn, execute atomically in a single transaction. Developers also want to make use of features afforded by new transaction formats, like paymasters in [ERC-4337](./eip-4337.md) transactions. `eth_sendTransaction` offers no way to do these things.

In updating to a new set of `wallet_` RPCs, our main goals are to enforce a clean separation of wallet and app concerns, enable developers to make use of things like paymasters and batch transactions, and to create a clear way for more safely discoverable features to be added over time with minimal coordination.

## Specification

Four new JSON-RPC methods are added: three are for handling batches of onchain calls, and one is for querying support for wallet capabilities, such as to make better use of the three batching methods.
Apps may begin using these first three methods immediately, falling back to `eth_sendTransaction` and `eth_getTransactionReceipt` when they are not available.

### `wallet_sendCalls`

Requests that a wallet submits a batch of calls. `from` and `chainId` are identified by [EIP-155](./eip-155.md) integers expressed in hexadecimal notation,
with `0x` prefix and no leading zeroes for the `chainId` value.
The items in the `calls` field are simple `{to, data, value}` tuples.

The capabilities field is how an app can communicate with a wallet about capabilities a wallet supports. For example, this is where an app can specify a paymaster service URL from which an [ERC-4337](./eip-4337.md) wallet can request a `paymasterAndData` input for a user operation.

Each capability defined in the "capabilities" member can define global or call specific fields.
These fields are set inside this capability's entry in the `capabilities` object.
Each entity in the `calls` field may contain an optional `capabilities` object.
This object allows the applications to attach a capability-specific metadata to individual calls.

The `atomicRequired` field specifies if a wallet is required to handle the batch of calls atomically or not. The wallet capacity to execute batch calls atomically is exposed through the built in `atomic` capability and can be sourced via `wallet_getCapabilities`..

Unless these requirements are explicitly overridden by a certain `capability`, the wallet must adhere to the following rules.
Note that such a `capability` is not in the scope of this EIP and should be defined in its own ERC.

The wallet:

* MUST send the calls in the order specified in the request
* MUST send the calls on the same chain identified by the request's `chainId` property
* MUST send the calls from the address specified in the request's `from` property, if provided
  * If `from` is not provided the wallet SHOULD present the user with an opportunity to view and select the `from` address during confirmation
* MUST NOT await for any calls to be finalized to complete the batch
* MUST NOT send any calls from the request if the user rejects the request
* When `atomicRequired` is set to `true`:
  * MUST execute all calls atomically, meaning that either all calls execute successfully or no material effects appear on chain.
  * MUST execute all calls contiguously, meaning no other transactions/calls may be interleaved with the calls from this batch.
  * If a wallet is able to upgrade its atomicity guarantees from `ready` to `supported` but has not yet done so, it MUST upgrade before proceeding to submit the calls with the above guarantees.
* When `atomicRequired` is set to `false`:
  * MAY execute all calls sequentially without any atomicity/contiguity guarantees.
  * If a wallet is capable of providing atomicity guarantees, it MAY execute the batch atomically.
  * If a wallet is able to upgrade its atomicity guarantees to `supported` (see `atomic` capability definition below), it MAY do so and then execute the batch atomically.

* MAY reject the request if the from address does not match the enabled account
* MAY reject the request if one or more calls in the batch is expected to fail, when simulated sequentially
* MUST reject the request if it contains a `capability` (either top-level or call-level) that is not supported by the wallet and the `capability` is not explicitly marked as optional.
  * Applications may mark a capability as optional by setting `optional` to `true`. See the RPC Specification section below for details.

If provided, the wallet MUST respect the `id` field and return it in the response.

Identifiers, whether provided by the app or generated by the wallet, MUST be a unique string up to 4096 bytes (8194 characters including leading `0x`).

App-provided `id`s MUST be unique per sender per app, where each "app" SHOULD be identified by their domain.

Wallets MUST reject requests with duplicate `id`s.

Within 24 hours from the corresponding `wallet_sendCalls`, wallets SHOULD return a call-batch status when `wallet_getCallsStatus` is called with the same `id`.

The `capabilities` response object allows the wallets to attach a capability-specific metadata to the response.


#### `wallet_sendCalls` RPC Specification

```typescript
type Capability = {
  [key: string]: unknown;
  optional?: boolean;
}

type SendCallsParams = {
  version: string;
  id?: string;
  from?: `0x${string}`;
  chainId: `0x${string}`; // Hex chain id
  atomicRequired: boolean;
  calls: {
    to?: `0x${string}`;
    data?: `0x${string}`;
    value?: `0x${string}`; // Hex value
    capabilities?: Record<string, Capability>;
  }[];
  capabilities?: Record<string, Capability>;
};

type SendCallsResult = {
  id: string;
  capabilities?: Record<string, any>;
};
```

##### `wallet_sendCalls` Example Parameters

```json
[
  {
    "version": "2.0.0",
    "from": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
    "chainId": "0x01",
    "atomicRequired": true,
    "calls": [
      {
        "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
        "value": "0x9184e72a",
        "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
      },
      {
        "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
        "value": "0x182183",
        "data": "0xfbadbaf01"
      }
    ],
    "capabilities": {
      "paymasterService": {
        "url": "https://...",
        "optional": true
      }
    }
  }
]
```

Note that since the `paymasterService` `capability` is marked as optional, wallets that do not support it will still process and handle the request as if the capability had not been present. If this `optional` field were set to `false` or absent from the request, wallets that do not support the `capability` MUST reject the request.

##### `wallet_sendCalls` Example Return Value

```json
{
  "id": "0x00000000000000000000000000000000000000000000000000000000000000000e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331",
}
```

### `wallet_getCallsStatus`

Returns the status of a call batch that was sent via `wallet_sendCalls`.
The identifier of the batch is the value returned from the `wallet_sendCalls` RPC.
Note that the `receipts` objects of this method's response is a strict subset of the object returned by `eth_getTransactionReceipt`.

The `capabilities` object allows the wallets to attach a capability-specific metadata to the response.

The `atomic` field specifies how the wallet handled the batch of calls, which influences the structure of the `receipts` field.

* The receipts in the `receipts` field MUST be in the order that they are included onchain.
* If a wallet executes multiple calls **atomically**, `wallet_getCallsStatus` MAY return an object with a `receipts` field that contains a single transaction receipt or an array of receipts, corresponding to how the batch of transactions were included onchain. It also MUST be explicit and return an `atomic` field set to `true`.
* If a wallet executes multiple calls **non-atomically**, `wallet_getCallsStatus` MUST return an object with a `receipts` field that contains **an array of receipts** for all transactions containing batch calls that were included onchain. This includes the batch calls that were included on-chain but eventually reverted. It also MUST be explicit and return a `atomic` field set to `false`.
* The `logs` in the receipt objects MUST only include logs relevant to the calls submitted using `wallet_sendCalls`. For example, in the case of a transaction submitted onchain by an [ERC-4337](./eip-4337.md) bundler, the logs must only include those relevant to the user operation constructed using the calls submitted via `wallet_sendCalls`. I.e. the logs should not include those from other unrelated user operations submitted in the same bundle.
  * Similarly, if a user upgrades their wallet to support atomicity before submitting a batch of calls from an app, the logs MUST NOT include those emitted as part of the upgrade process.

#### `wallet_getCallsStatus` RPC Specification

```typescript
type GetCallsParams = [string];

type GetCallsResult = {
  version: string;
  id: `0x${string}`;
  chainId: `0x${string}`;
  status: number; // See "Status Codes"
  atomic: boolean;
  receipts?: {
    logs: {
      address: `0x${string}`;
      data: `0x${string}`;
      topics: `0x${string}`[];
    }[];
    status: `0x${string}`; // Hex 1 or 0 for success or failure, respectively
    blockHash: `0x${string}`;
    blockNumber: `0x${string}`;
    gasUsed: `0x${string}`;
    transactionHash: `0x${string}`;
  }[];
  capabilities?: Record<string, any>;
};
```

##### Status Codes for `status` field

The purpose of the `status` field is to provide a short summary of the current status of the batch.
It provides some off-chain context to the array of inner transaction `receipts`.

Status codes follow these categories:

* 1xx: Pending states
* 2xx: Confirmed states
* 4xx: Offchain failures
* 5xx: Chain rules failures

| Code | Description                                                                                                                       |
|------|-----------------------------------------------------------------------------------------------------------------------------------|
| 100  | Batch has been received by the wallet but has not completed execution onchain (pending)                                           |
| 200  | Batch has been included onchain without reverts, receipts array contains info of all calls (confirmed)                            |
| 400  | Batch has not been included onchain and wallet will not retry (offchain failure)                                                  |
| 500  | Batch reverted **completely** and only changes related to gas charge may have been included onchain (chain rules failure)         |
| 600  | Batch reverted **partially** and some changes related to batch calls may have been included onchain (partial chain rules failure) |

More specific status codes within these categories should be proposed and agreed upon in separate ERCs.

##### `wallet_getCallsStatus` Example Parameters

The `id` batch identifier is a unique 64 bytes represented as a hex encoded string returned from `wallet_sendCalls`.

```json
[
  "0x00000000000000000000000000000000000000000000000000000000000000000e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"
]
```

##### `wallet_getCallsStatus` Example Return Value

```json
{
  "version": "2.0.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`

Requests that a wallet shows information about a given call bundle that was sent with `wallet_sendCalls`. Note that this method does not return anything for a known `id` batch identifier. If the identifier is not known, or in case of any other failure to execute `wallet_showCallsStatus` returns an RPC call error.

#### `wallet_showCallsStatus` RPC Specification

```typescript
type ShowCallsParams = string; // Call bundle identifier returned by wallet_sendCalls
```

##### `wallet_showCallsStatus` Example Parameters

This method accepts a call bundle identifier returned by a `wallet_sendCalls` call.

```json
["0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"]
```

### `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. For more on the difference between requesting capabilities and discovering features, see the ["Privacy Considerations" section](#privacy-considerations).

This method SHOULD return an `4100 Unauthorized` error if the user has not already authorized a connection between the application and the requested address.

We expect the community to align on the definition of additional capabilities in separate ERCs over time.

Note that in addition to, or instead of, querying the wallet directly for capabilities, the same capability objects MAY be exposed out-of-band, such as in a `sessionProperties` and/or `scopedProperties` collections persisted in a [CAIP-25](https://github.com/ChainAgnostic/CAIPs/blob/c599f7601d0ce83e6dd9f350c6c21d158d56fd6d/CAIPs/caip-25.md)-conformant wallet provider interface (see the ethereum usage profile for CAIP-25 for an example request and response), or in some other a well-known location (such as a URL derived from an [EIP-6963](./eip-6963.md) `rdns` identifier).
Provider abstractions MAY also cache capabilities from previous requests or otherwise inject them from out-of-band to facilitate better user experience.
If any of these supplemental expressions of capabilities are contradicted by capabilities expressed in live wallet RPC responses, these latter values SHOULD be taken as the canonical and current expression of capabilities.

#### `wallet_getCapabilities` RPC Specification

Capabilities are returned in key/value pairs, with the key naming a capability and a value conforming to a shape defined for that name, in an object keyed to the relevant [EIP-155](./eip-155.md) `chainId` expressed in hexadecimal notation.
Capabilities are nested in per-chain objects because wallets may support different capabilities across multiple chains authorized in a given session.
Capabilities that the wallet supports on all the chains SHOULD be included only once, using a special `chainID` value `"0x0"`, and SHOULD NOT be repeated in nested per-chain objects.
If a wallet does not support a chain that is requested in the `wallet_getCapabilities` method, the wallet MUST NOT respond with an error, and MUST instead not include a key for the unsupported chain(s) in the response.

```typescript
type GetCapabilitiesParams = [`0x${string}`, [`0x${string}`]]; // Wallet address, array of queried chain ids (optional)

type GetCapabilitiesResult = Record<`0x${string}`, <Record<string, any>>; // Hex chain id
```

##### `wallet_getCapabilities` Example Parameters

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

##### `wallet_getCapabilities` Example Return Value

The capabilities below are for illustrative purposes.

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

### `atomic` Capability

Like the illustrative examples given above and other capabilities to be defined in future EIPs, the `atomic` capability specifies how the wallet will execute the batches of transactions requested through `wallet_sendCalls` method.

The valid JSON-RPC values for this `atomic` capability's only property, `status`, are `supported`, `ready`, and `unsupported`:

* `supported` means that the wallet will execute the calls atomically and contiguously.
* `ready` means that the wallet is able to upgrade to `supported` pending user approval.
* `unsupported` means that the wallet does not provide any atomicity or contiguity guarantees, nor will it suggest an upgrade to the user.

This capability is expressed separately on each chain and should be interpreted as a guarantee only for batches of transactions on that chain.

If the `atomic` capability is not present for a given chain, and unless it is explicitly overridden by another `capability` (not in scope of this EIP), it means that the wallet does not support batching for that given chain.

#### `atomic` Capability Specification

```typescript
type AtomicCapability = {
  status: 'supported' | 'ready' | 'unsupported';
};
```


#### `wallet_getCapabilities` Example Return Value including `atomic`

```json
{
  "0x2105": {
    "atomic": {
      "status": "supported"
    }
  },
  "0x14A34": {
    "atomic": {
      "status": "unsupported"
    }
  }
}
```

### Error Codes

The following error codes are defined for the methods specified in this EIP. These errors follow the JSON-RPC 2.0 specification for error objects, which require a `code` and `message` field.

| Code | Message | Description | Related RPCs |
|------|---------|-------------|--------------|
| -32602 | Invalid params | The wallet cannot parse this request (e.g., missing 0x prefix, leading zeros in chain id, request fails schema validation) | `wallet_sendCalls`, `wallet_getCallsStatus`, `wallet_showCallsStatus`, `wallet_getCapabilities` |
| 4001 | User Rejected Request | The user rejected submitting the batch of calls (from [EIP-1193](./eip-1193.md)) | `wallet_sendCalls` |
| 4100 | Unauthorized | The specified address is not connected or not in the wallet (from [EIP-1193](./eip-1193.md)) | `wallet_sendCalls`, `wallet_getCapabilities` |
| 5700 | Unsupported non-optional capability | This wallet does not support a capability that was not marked as optional | `wallet_sendCalls` |
| 5710 | Unsupported chain id | This wallet does not support the specified chain id | `wallet_sendCalls` |
| 5720 | Duplicate ID | There is already a bundle submitted with this id | `wallet_sendCalls` |
| 5730 | Unknown bundle id | This bundle id is unknown / has not been submitted | `wallet_getCallsStatus`, `wallet_showCallsStatus` |
| 5740 | Bundle too large | The call bundle is too large for the wallet to process | `wallet_sendCalls` |
| 5750 | Atomic-ready wallet rejected upgrade | The wallet can support atomicity after an upgrade, but the user rejected the upgrade | `wallet_sendCalls` |
| 5760 | Atomicity not supported | The wallet does not support atomic execution but the request requires it | `wallet_sendCalls` |

## Rationale

### On Naming

We considered modifying `eth_sendTransaction` to add support for these new capabilities, but the method is ultimately an artifact of when nodes were used to sign transactions. We decided it is better to move forward with `wallet_`-namespaced methods that better describe what they are used for.

We also debated whether the methods should be called `wallet_sendTransaction`, `wallet_sendCalls`, or something else. We ultimately landed on `wallet_sendCalls` because in the case of EOA wallets the `wallet_send*` method might send more than one transaction. Similarly, we decided against `wallet_sendTransactions` because in the case of other wallet implementations (e.g. [ERC-4337](./eip-4337.md)) multiple calls could result in a single transaction.

### Call Execution Atomicity

The `wallet_sendCalls` method accepts an array of `calls`. However, this proposal does not require that these calls be executed as part of a single transaction. It enables EOA wallets to express their ability to execute calls as part of a single transaction or as part of multiple transactions. It also enables Apps to express their minimum atomicity requirements for how calls must be executed.

The `atomic` special capability was made an integral part of this specification in order promote expressiveness and facilitate adoption (from both wallets and apps). And due to its importance to reduce ambiguity between the App and the Wallet, the capability is expressed as a top-level field in the `wallet_sendCalls` request (through the `atomicRequired` parameter) and the `wallet_getCallsStatus` response (through the `atomic` field).

We initially proposed that multiple calls must be executed atomically, but after some debate we ultimately decided this was too opinionated. Instead, we are including a specification for an `atomic` capability. This allows for EOA wallets to accept multiple calls and still gives developers the option to only submit batched calls if they are executed atomically.

### Call Gas Limit

Our initial proposal included an optional `gas` field for each call in the `calls` field accepted by the `walletSendCalls` method. However, we realized this could be misleading because in the case of [ERC-4337](./eip-4337.md) wallets you cannot specify a gas limit per call, only a single gas limit for all calls in the user operation. We then proposed a single `gas` value that would apply to all of the calls. This works for [ERC-4337](./eip-4337.md) wallets, but not for EOA wallets. When we decided that EOA wallets should be able to handle multiple calls, the common `gas` field became untenable across use cases and we removed it altogether.

## Backwards Compatibility

Wallets that do not support the methods defined here SHOULD return error responses when these new JSON-RPC methods are called. Apps MAY attempt to send the same batch of calls serially via `eth_sendTransaction` when a call to these methods fails for lack of wallet support, or they MAY indicate to the user that their wallet is not supported and the request was not processed.

## Security Considerations

Regardless of the `atomic` value specified, App developers MUST NOT assume that all calls will be sent in a single transaction. An example could be an L2 resistant to reorgs that implements a sendBundle or similar functionality.

Wallets MUST ensure that batch identifiers returned by `wallet_sendCalls` are unpredictable to prevent malicious apps from inferring information about other users' transactions.

Wallets MUST NOT leak sensitive information in `wallet_getCallsStatus` `capabilities` responses.

### Privacy Considerations

Progressive authorization and progressive consent paradigms are important to modern user experience, as well as to preserving the anonymity of user agents. To protect these patterns from the cross-incentives of feature-discovery that enables better user experiences, capability semantics are used and the difference between lack of feature support and lack of feature permission explicitly occluded in the design of the `wallet_` RPC for querying capabilities.

Furthermore, wallets are recommended to avoid exposing capabilities to untrusted callers or to more callers than necessary, as this may allow their "user-agent" (i.e. client software) to be "fingerprinted" or probabilistically identified, which combined with other deanonymization vectors inherent to the web platform could contribute to the deanonymization of the individual user or to the deanonymization of all users of a given client in aggregate. Similarly, applications over-querying capabilities or incentivizing capability oversharing (including third-party capability oversharing) is an anti-pattern to be avoided in the implementation of capability exchanges serving to discover features.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).
