# Wallet Verification

Source: https://docs.settlemint.com/docs/architecture/security/wallet-verification
Wallet verification gates blockchain write operations as a second security
layer beyond session authentication, using PIN, TOTP, or backup-code checks.




## Overview [#overview]

Wallet verification is the per-request check that protects blockchain write operations from browser sessions. Even with a valid authenticated session, a signing request must include PIN, TOTP, or backup-code evidence before DALP passes the operation to the signing flow.

## Related [#related]

* [Authentication](/docs/architecture/security/authentication)
* [Authorization](/docs/architecture/security/authorization)
* [Signing Flow](/docs/architecture/flows/signing-flow)
* [Key Guardian](/docs/architecture/components/infrastructure/key-guardian)

## System context [#system-context]

<Mermaid
  chart="`sequenceDiagram
  participant Operator as Authenticated operator
  participant Session as Platform session
  participant Challenge as Wallet verification
  participant API as Unified API transaction gate
  participant Signer as Signer or custody service
  participant Chain as Configured EVM network

  Operator->>Session: Submit blockchain write request
  Session->>Challenge: Require PIN, TOTP, or backup code
  alt verification accepted
    Challenge->>API: Release request to signing gate
    API->>Signer: Request signature or custody approval
    Signer->>Chain: Submit EVM transaction
  else missing or failed check
    Challenge-->>Operator: Reject before signing
  end

`"
/>

## Why wallet verification exists [#why-wallet-verification-exists]

Session authentication proves identity. Wallet verification proves intent for the request that will consume a wallet secret. Separating these checks means a browser session alone cannot trigger asset transfers, minting, burning, or other signing operations protected by the wallet-verification middleware.

The check runs before signing. DALP rejects the request before the signing flow starts when verification evidence is missing, the selected method is not configured for the user, or the credential is wrong.

See the [security overview](/docs/architecture/security) for how this check combines with authentication, authorization, custody policy, and on-chain transfer controls.

## Verification methods [#verification-methods]

Transaction-signing APIs accept these wallet verification methods. Organizations can enable one or more based on their security posture.

### PINCODE [#pincode]

A 6-digit PIN set during initial wallet setup. PIN verification provides quick confirmation for routine transactions where the user is already authenticated and working within the platform.

* **Setup:** User defines PIN during wallet creation
* **Usage:** Enter 6-digit code alongside the transaction request
* **Trade-off:** Fastest verification, lower resistance to shoulder-surfing compared to TOTP

### Two-factor authentication (TOTP) [#two-factor-authentication-totp]

Time-based one-time passwords generated by an authenticator app. Codes rotate every 30 seconds following RFC 6238.

* **Setup:** User scans a QR code into their authenticator app during wallet setup
* **Usage:** Enter the current 6-digit code from the authenticator app
* **Trade-off:** Stronger than PIN (codes expire), requires the user's authenticator device

### Backup codes [#backup-codes]

Backup codes are one-time recovery codes generated during wallet setup. DALP generates 16 codes in `xxxxx-xxxxx` format. Each code can pass verification once; reuse fails because DALP records used codes.

* **Setup:** Platform generates and stores the active code set during wallet configuration; user stores the codes securely offline
* **Usage:** Enter any unused code when PIN or TOTP is unavailable
* **Trade-off:** Last-resort recovery mechanism; limited supply, one use per code

## Passkeys and wallet verification [#passkeys-and-wallet-verification]

Passkeys can be used for account authentication when enabled for the deployment. DALP documents passkey sign-in on the [Authentication](/docs/architecture/security/authentication) page.

For blockchain write requests, the wallet verification middleware accepts PINCODE, OTP, or SECRET\_CODES. Do not send PASSKEY as the `walletVerification.verificationType` for transaction-signing API calls; the request will be rejected.

## How verification works in requests [#how-verification-works-in-requests]

API procedures that trigger blockchain write operations accept a `walletVerification` object in the request body:

| Field                                       | Value                                     | Description                                         |
| ------------------------------------------- | ----------------------------------------- | --------------------------------------------------- |
| `walletVerification.verificationType`       | `PINCODE`, `OTP`, or `SECRET_CODES`       | Which wallet verification method the user presents  |
| `walletVerification.secretVerificationCode` | 6-digit string, TOTP code, or backup code | The credential for the selected verification method |

The Unified API validates the credential before forwarding the operation to the Execution Engine. If verification fails, the request is rejected immediately. No gas is consumed, no custody provider interaction occurs, and no on-chain state changes.

### API key sessions bypass verification [#api-key-sessions-bypass-verification]

When a request is authenticated via API key, wallet verification is not required. The `walletVerification` field can be omitted from the request body. API keys are scoped credentials intended for machine-to-machine use. The API key is the authorization factor, so a second interactive challenge is not part of that path.

## Failure cases [#failure-cases]

Wallet verification fails before the signing flow starts. The request is rejected when:

| Condition                                                               | Result                                               |
| ----------------------------------------------------------------------- | ---------------------------------------------------- |
| No authenticated user is available                                      | `UNAUTHORIZED` with `Authentication required`        |
| The user has no PIN, backup-code, or TOTP method configured             | `USER_MISSING_2FA` with setup guidance               |
| The request omits `walletVerification` for a browser-session write      | `BAD_REQUEST` with `Wallet verification is required` |
| The selected method is not configured for the user                      | `FORBIDDEN`                                          |
| The submitted PIN, backup code, or TOTP code is invalid or already used | `FORBIDDEN`                                          |
| `PASSKEY` is sent as the wallet verification type                       | `FORBIDDEN`                                          |

Passkeys authenticate account sign-in. PINCODE, OTP, and SECRET\_CODES are the accepted wallet verification values for transaction-signing requests.

## Security considerations [#security-considerations]

* **Separate credential path:** Wallet verification uses wallet-specific PIN, backup-code, or TOTP records rather than the browser session token.
* **Method-level configuration:** A user must have the selected method enabled before that method can satisfy a signing request.
* **Replay prevention:** Backup codes are recorded on use, and TOTP tokens are tracked so the same token cannot be replayed.
* **API-key exception:** Machine-to-machine API-key sessions skip the interactive wallet-verification challenge.

## See also [#see-also]

* [Security overview](/docs/architecture/security) for the full defense-in-depth model
* [Signing Flow](/docs/architecture/flows/signing-flow) for how wallet verification fits into the transaction lifecycle
* [Authentication](/docs/architecture/security/authentication) for API-level rate limiting and RBAC
