> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rhinestone.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# History and recovery

> Let users review deposits and recover eligible failures from the deposit or withdraw modal.

Available from `@rhinestone/deposit-modal` v0.15.0, history is the normal self-service recovery path for both host modals. It lists deposits for the account in context and can recover an eligible failure when you provide `signRecovery`.

<Tabs>
  <Tab title="Deposit modal">
    ```tsx theme={null}
    <DepositModal
      // ...required props
      recipient={recipient}
      signRecovery={({ typedData, signer, chainId }) =>
        getRecoveryWallet({ address: signer, chainId }).signTypedData(typedData)
      }
    />
    ```

    History lists deposits for the configured `recipient`.
  </Tab>

  <Tab title="Withdraw modal">
    ```tsx theme={null}
    <WithdrawModal
      // ...required props
      recipient={withdrawalDestination}
      signRecovery={({ typedData, signer, chainId }) =>
        getRecoveryWallet({ address: signer, chainId }).signTypedData(typedData)
      }
    />
    ```

    History follows the currently valid withdrawal destination, not `accountAddress`. Changing the destination re-scopes the list and status badge. An invalid or absent destination has no history entry point. Provide `signRecovery` only when your app can sign for destinations the user selects.
  </Tab>
</Tabs>

## Where history appears

The history entry point is available before a transaction and on terminal success or failure screens. It is hidden while the modal is signing, submitting, polling, or showing an external provider. Opening history during a flow preserves the underlying form or step, so Back returns the user to it.

The entry-point badge summarizes the visible account:

| Badge       | Meaning                                                                    |
| ----------- | -------------------------------------------------------------------------- |
| `needs_you` | At least one failed row can be recovered. Takes precedence over `progress` |
| `progress`  | At least one row is pending or processing                                  |
| `none`      | Neither condition applies                                                  |

Without `signRecovery`, history remains available but read-only. The transaction-hash fallback is hidden and the badge does not use `needs_you` because the integration cannot offer recovery.

Your [proxy](/deposits/widget/backend#required-routes) must forward `GET /deposits` for lookup and `POST /deposits/recover` for signed recovery. These are existing routes; history adds no backend handler or header.

## Recover from a history row

An eligible failed row opens a review, signing, and outcome flow. The refund destination starts as the deposit recipient, remains editable, and is covered by the signature.

Recovery is offered only when all of these conditions hold:

* The raw deposit status is `failed` or `rejected`.
* Both source and destination are EVM chains.
* The deposit names a valid recipient matching the account whose history is open.
* Your integration supplies `signRecovery` for that recipient.

Completed, pending, processing, non-EVM, recipient-less, and otherwise ineligible rows remain visible without a recovery action.

## Recover by transaction hash

When signing is enabled, history also offers transaction-hash lookup for a recoverable deposit omitted from the list, including a spam-filtered deposit. The lookup is scoped to the account whose history is open—even in the withdraw modal. A hash that belongs only to another account returns no match.

Recovering an unlisted deposit does not add it to the history list afterward.

For support cases that must look up another account's deposit, use the deprecated [`ClaimModal`](/deposits/widget/claim-modal). Its lookup is intentionally unscoped and should not replace account-scoped self-service history.

## Signing contract

`signRecovery` is optional on `DepositModal` and `WithdrawModal` and has the exported `SignRecovery` type:

```ts theme={null}
import type { SignRecovery } from "@rhinestone/deposit-modal";

const signRecovery: SignRecovery = async ({ typedData, signer, chainId }) => {
  const wallet = getRecoveryWallet({ address: signer, chainId });
  return wallet.signTypedData(typedData);
};
```

`getRecoveryWallet` represents your app's account lookup. Select the wallet by both `signer` and `chainId`, then use the signing API expected by its SDK. The callback receives the complete typed data, so do not reconstruct it.

| Field         | Type                  | Description                                                             |
| ------------- | --------------------- | ----------------------------------------------------------------------- |
| `typedData`   | `TypedDataDefinition` | EIP-712 `RecoverDeposit` data naming the deposit and refund destination |
| `signer`      | `Address`             | Deposit recipient whose signature the service verifies                  |
| `chainId`     | `number`              | Deposit destination chain, where the recipient's verifier lives         |
| `depositId`   | `string`              | Deposit being recovered                                                 |
| `destination` | `Address`             | Editable refund destination covered by the signature                    |

`chainId` is **not** the source chain from which funds are refunded. Use it to select the verifier context for a smart account. This matters for ERC-1271 and ERC-6492 accounts whose deployment or owners differ by chain; EOA signatures are unaffected.

Return whatever the recipient verifies:

| Recipient                | Return value                                            |
| ------------------------ | ------------------------------------------------------- |
| EOA                      | Raw 65-byte EIP-712 signature                           |
| Deployed smart account   | Signature accepted by ERC-1271 `isValidSignature`       |
| Undeployed smart account | Account signature wrapped with ERC-6492 deployment data |

A raw smart-account owner signature is usually insufficient. Sign through the account SDK so it produces the wallet's expected ERC-1271 or ERC-6492 format. The signed destination prevents the page or service from redirecting the refund.

## Host callbacks and analytics

History navigation emits the [deposit or withdraw history events](/deposits/widget/status-tracking#history-analytics) in the current host session. Starting recovery creates a correlated claim session, and its `ClaimAnalyticsEvent` values arrive through the host modal's `onEvent` callback:

```ts theme={null}
DepositModalProps["onEvent"]
// DepositAnalyticsEvent | ClaimAnalyticsEvent | AnalyticsIngestFailureEvent

WithdrawModalProps["onEvent"]
// WithdrawAnalyticsEvent | ClaimAnalyticsEvent | AnalyticsIngestFailureEvent
```

History does not add claim events to `onLifecycle`. `enableAnalyticsIngest={false}` disables Rhinestone collection but does not change what `onEvent` receives, and analytics delivery never blocks recovery.

## Other recovery models

Choose the authorization model that matches the caller:

* **User self-service:** use account-scoped history with `signRecovery`.
* **Cross-account support lookup:** use the deprecated standalone [`ClaimModal`](/deposits/widget/claim-modal), supported until the next major release.
* **Recipient cannot sign:** authorize an operator flow on your server with [`createRefundHandler`](/deposits/widget/claim-modal#when-the-user-cant-sign). It is not called by either modal and must never be exposed as a browser proxy route.
