Skip to main content
This page has been updated for Wallets SDK V1. If you are using the previous version, see the previous version docs or the V1 migration guide.
Recovery is the process of regaining signing access to a wallet when the original signer is no longer available. The most common trigger is a user switching to a new device — the device signer on the old phone or laptop cannot be transferred, so the user must authenticate with their recovery signer and enroll a new device key.

Why Recovery Signers Are Separate

In Crossmint’s dual-layer architecture, every wallet has at least one recovery signer in addition to its day-to-day signer. These are separate because they solve different problems:
  • Signers are optimized for speed and low friction. A device signer signs silently using the device’s hardware security module — no OTP, no network call, no user interruption.
  • Recovery signers are optimized for security at the cost of convenience. They use higher-friction authentication (email OTP, SMS OTP, or server-held keys) to ensure that only the rightful owner can restore access to a wallet.
If a single signer handled both roles, you would either sacrifice security (a frictionless signer that also controls recovery) or sacrifice UX (requiring OTP verification for every transaction).

When Recovery Triggers

Recovery is needed when the wallet detects that no valid signer is available on the current device. The most common scenarios are:
  • New device — the user opens your app on a phone or browser where no device signer has been created yet
  • Cleared storage — the user cleared browser data or reinstalled the app, deleting the locally stored device key
  • Key mismatch — the local device key does not match any signer registered onchain for the wallet (for example, after a key rotation)
The SDK detects these conditions automatically. When a wallet is loaded via getWallet(), it checks whether a valid device signer exists locally. If not, it sets an internal needsRecovery flag. You can check this flag explicitly using wallet.needsRecovery().

How Recovery Works

The recovery flow for device signers follows these steps:
  1. Detection — the SDK loads the wallet and finds no valid local device key. needsRecovery() returns true.
  2. Authentication — the recovery signer authenticates the user. For email or phone OTP signers, this means sending a one-time code and verifying the user’s response. For server signers, the server authenticates using its secret.
  3. New key generation — the SDK generates a new P256 keypair in the device’s secure enclave (or browser credential store).
  4. Signer registration — the SDK calls addSigner() to register the new device key onchain. This operation is authorized by the recovery signer — the smart contract verifies that the caller is an approved recovery signer before accepting the new key.
  5. Signer activation — the new device signer becomes the active signer. needsRecovery() returns false.
Recovery runs automatically before every signing operation. If the SDK detects that recovery is needed, it triggers the recovery flow transparently via recover() before proceeding with the transaction. The user experiences a one-time OTP prompt (or no prompt at all, for server signers), after which all subsequent transactions on that device sign silently.

Preemptive Recovery

While recovery runs automatically when needed, you can also trigger it explicitly — for example, on app startup — to avoid interrupting the user’s first transaction with an OTP prompt:
import { useWallet } from "@crossmint/client-sdk-react-ui";

const { wallet } = useWallet();

if (wallet?.needsRecovery()) {
  await wallet.recover();
}
This is optional. If you do not call recover() explicitly, the SDK calls it automatically before the first signing operation.

The OTP Flow

For wallets using email or phone OTP as the recovery signer, the recovery authentication flow works as follows:
  1. The SDK requests an OTP to be sent to the user’s email address or phone number.
  2. The user receives the code and enters it in your application.
  3. The SDK verifies the code and uses the authenticated recovery signer to register the new device key.
In React applications, Crossmint provides built-in OTP dialog components that handle the UI automatically.

Recovery and Custody

Recovery is enforced onchain by the wallet’s smart contract. Crossmint’s backend does not have the ability to add signers, transfer assets, or bypass the recovery signer — all authorization logic lives in the smart contract. This means:
  • In non-custodial configurations, only the user (via their recovery signer) can authorize new device keys.
  • In custodial configurations using a server signer for recovery, the organization holding the server secret controls recovery.
See Custody Models for how signer choices affect custody classification.

Solana and Recovery

Solana wallets do not currently support device signers. For Solana, the recovery signer (typically email or phone OTP) serves as both the recovery mechanism and the transaction signer. When a Solana user needs to sign a transaction, the SDK automatically uses the recovery signer as a fallback, which means the user will see an OTP prompt for each signing operation.

See Also

Signers

Understanding the different signer types and when to use each one

Custody Models

How signer and recovery choices map to custody architectures