---
eip: 7836
title: Wallet Call Preparation API
description: Adds JSON-RPC methods for requesting unsigned EIP-5792 calls based on the wallet's implementation, and then sending those calls once signed.
author: Lukas Rosario (@lukasrosario), Conner Swenberg (@ilikesymmetry), Adam Hodges (@ajhodges), Paaras Bhandari (@paarasbhandari), Jake Moxey (@jxom)
discussions-to: https://ethereum-magicians.org/t/new-erc-wallet-call-preparation-api/22456
status: Draft
type: Standards Track
category: ERC
created: 2024-12-06
requires: 1193, 5792
---

## Abstract

This proposal defines complementary JSON-RPC methods to [EIP-5792's `wallet_sendCalls`](./eip-5792.md) to enable an Application to sign over a call bundle (instead of the Wallet). Methods defined in this proposal are purposed for the Application to sign over `calls` and submit them to the Wallet with an accompanying signature. This is in contrast to `wallet_sendCalls`, where a Wallet itself signs over the call bundle.

## Motivation

Applications are increasingly seeking to use session keys and scoped permissions to make transactions on a user's behalf, without the user having to approve and sign each transaction in their wallet's interface. One example is an application that automates a user's decentralised exchange trading. As Smart Contract Accounts (SCAs) contain arbitrary execution interfaces that lead to varying calldata formats, it is not possible for an Application to know how to sign over an action for any arbitrary Account implementation, without maintaining a mapping of Account implementations to their signing logic. Apps need a simple way to request the payload that their session keys should sign, given a call or set of calls they wish to make, and a way to execute the calls once signed.

## Specification

In this specification, we define two new JSON-RPC methods: `wallet_prepareCalls` and `wallet_sendPreparedCalls`.

### `wallet_prepareCalls`

Instructs a Wallet to prepare a call bundle according to the Account's implementation. It returns a `digest` of the call bundle to sign over, as well as the parameters required to fulfil a `wallet_sendPreparedCalls` request (ie. `capabilities`, `chainId`, `context`, and `version`).

> After calling `wallet_prepareCalls`, consumers are expected to sign over the `digest` and submit the `signature` and prepared calls to the Wallet via `wallet_sendPreparedCalls`.

#### Request

> The request is identical to that of [`wallet_sendCalls`](./eip-5792.md).

```typescript
type Request = {
  method: "wallet_prepareCalls";
  params: [
    {
      // Calls to be executed.
      calls: {
        to: `0x${string}`;
        data?: `0x${string}`;
        value?: `0x${string}`;
        capabilities?: Record<string, any>;
      }[];
      // Capabilities.
      capabilities?: Record<string, any>;
      // Chain ID of the chain the calls are being submitted to.
      chainId: `0x${string}`;
      // Sender address.
      from?: `0x${string}`;
      // Key (hint) that will be used to sign the call bundle.
      key?: {
        // Whether the digest will be prehashed by the key (default behavior of WebCrypto APIs).
        prehash?: boolean;
        // Public key.
        publicKey: `0x${string}`;
        // Key type.
        type: "secp256k1" | "p256" | "webauthn-p256";
      };
      // JSON-RPC method version.
      version: string;
    }
  ];
};
```

#### Response

> The response is intended to be forwarded to `wallet_sendPreparedCalls` (minus the `digest`).

```typescript
type Response = {
  // Capabilities to be forwarded to `wallet_sendPreparedCalls`.
  capabilities: Record<string, any>;
  // Chain ID of the chain the calls are being submitted to.
  chainId: `0x${string}`;
  // Data specific to the Wallet to be forwarded to `wallet_sendPreparedCalls`
  // (e.g. ERC-4337 UserOperation or alternative).
  context: unknown;
  // Key (hint) that will be used to sign the call bundle.
  key?: {
    // Whether the digest will be prehashed by the key (default behavior of WebCrypto APIs).
    prehash: boolean;
    // Public key.
    publicKey: `0x${string}`;
    // Key type.
    type: "secp256k1" | "p256" | "webauthn-p256" | "webcrypto-p256";
  };
  // Digest of the call bundle to sign over.
  digest: `0x${string}`;
  // JSON-RPC method version.
  version: string;
};
```

#### Example

```typescript
const response = await provider.request({
  method: "wallet_prepareCalls",
  params: [
    {
      calls: [
        {
          to: "0xcafebabecafebabecafebabecafebabecafebabe",
          data: "0xdeadbeef",
        },
      ],
      capabilities: {
        paymasterService: {
          url: "https://...",
        },
      },
      chainId: "0x1",
      key: {
        prehash: false,
        publicKey:
          "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
        type: "p256",
      },
      version: "1",
    },
  ],
});
/**
 * {
 *   capabilities: {
 *     paymasterService: {
 *       url: 'https://...'
 *     }
 *   },
 *   chainId: '0x1',
 *   context: { ... },
 *   digest: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
 *   key: {
 *     prehash: false,
 *     publicKey: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
 *     type: 'p256',
 *   },
 *   version: '1',
 * }
 */
```

### `wallet_sendPreparedCalls`

Instructs a Wallet to execute a prepared call bundle (response of `wallet_prepareCalls`) with an accompanying `signature`.

#### Parameters

> The request is identical to the response of `wallet_prepareCalls`, except that it includes a `signature`.

```typescript
type Request = {
  method: "wallet_sendPreparedCalls";
  params: [
    {
      // Capabilities.
      capabilities: Record<string, any>;
      // Chain ID of the chain the calls are being submitted to.
      chainId: `0x${string}`;
      // Data specific to the Wallet from the `wallet_prepareCalls` response.
      // (e.g. ERC-4337 UserOperation or alternative).
      context: unknown;
      // Key that was used to sign the call bundle.
      key: {
        // Whether the digest will be prehashed by the key (default behavior of WebCrypto APIs).
        prehash?: boolean;
        // Public key.
        publicKey: `0x${string}`;
        // Key type.
        type: "secp256k1" | "p256" | "webauthn-p256" | "webcrypto-p256";
      };
      // Signature of the call bundle.
      signature: `0x${string}`;
      // JSON-RPC method version.
      version: string;
    }
  ];
};
```

#### Response

> The response is identical to that of `wallet_sendCalls`.

```typescript
type Response = {
  id: string;
  capabilities: Record<string, any>;
};
```

#### Example

```typescript
const { digest, ...request } = await provider.request({
  method: "wallet_prepareCalls",
  params: [
    {
      calls: [
        {
          to: "0xcafebabecafebabecafebabecafebabecafebabe",
          data: "0xdeadbeef",
        },
      ],
      capabilities: {
        paymasterService: {
          url: "https://...",
        },
      },
      chainId: "0x1",
      key: {
        prehash: false,
        publicKey:
          "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
        type: "p256",
      },
      version: "1",
    },
  ],
});

const signature = p256.sign(digest, privateKey);

const response = await provider.request({
  method: "wallet_sendPreparedCalls",
  params: [
    {
      ...request,
      signature,
    },
  ],
});
/**
 * [
 *   {
 *     id: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
 *   }
 * ]
 */
```

## Rationale

These endpoints extend the interface established by EIP-5792, given the emergent needs of application developers.

Adding new endpoints for this specific use case is simpler than adding additional options to the `wallet_sendCalls` endpoint.

Surfacing the prepared calls should be relatively simple for wallets, who already need to do preparation internally in order to support `wallet_sendCalls`, and who then submit signed calls on chain.

## Backwards Compatibility

This specification is currently compatible with EIP-5792 and does not introduce breaking changes to existing `wallet_sendCalls` flows.

- It does not modify or deprecate `wallet_sendCalls`; wallets compliant with EIP-5792 continue to work unchanged.
- `wallet_prepareCalls` mirrors the `wallet_sendCalls` request shape and returns values intended to be forwarded to `wallet_sendPreparedCalls`, preserving field formats such as `capabilities`, `chainId`, `context`, and `version`.
- `wallet_sendPreparedCalls` consumes the same data the wallet would otherwise construct internally for EIP-5792, with the addition of an externally produced `signature`.
- Any additional key types or hints (e.g., WebCrypto/WebAuthn variants) are optional and do not affect EIP-5792 behavior.

## Security Considerations

- Key authorization and scope: Wallets MUST verify that the provided `key.publicKey` is authorized for the account and that the requested `capabilities` are within that key’s permissions (scopes, limits, validity windows).

- Prehashing consistency: Honor `key.prehash` consistently. A mismatch between signer and verifier (e.g., double-hashing vs prehashed input) can cause verification failures. Wallets SHOULD fix the hash function per key type.

- Preparation-to-execution linkage: Wallets SHOULD ensure `wallet_sendPreparedCalls` corresponds to a `digest` they could have produced (e.g., by recomputing it) and MAY track a preparation identifier and/or validity window to mitigate long-lived replay.

- WebAuthn/origin considerations: For `webauthn-p256`, prefer user-verification and origin-bound credentials. Applications SHOULD keep session keys non-extractable and hardware-backed where available, and avoid presenting opaque digests for end-user approval.

- Resource usage and DoS: Wallets MAY rate-limit `wallet_prepareCalls`, cap bundle sizes, and validate inputs early to avoid expensive context generation for malformed or adversarial requests.

## Copyright

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