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

# Wallet Verification User Experience

> What your users see when they verify a wallet, how to return users to your app or embed the page, and which wallets are supported.

The verification page is where your user connects a wallet and signs the verification message. You get its link as the `url` when you [create a verification](/wallet-verification/quickstart.md).

## What your user sees

![Wallet Verification page asking the user to connect a wallet, with a searchable wallet list and a QR code to connect on mobile](https://mintcdn.com/walletconnect_pay_docs/NTAC-zItrJgRsb90/images/wallet-verification/connect-wallet.png?fit=max\&auto=format\&n=NTAC-zItrJgRsb90\&q=85\&s=f20729618c368f024f81b4492e9eb104)

The first screen: your business name at the top, the wallet list, and a QR code for mobile wallets.

**1. Open the link**

The page shows your business name, page title, and logo from [Customization](/wallet-verification/dashboard.md#customization).

**2. Connect a wallet**

The user picks a wallet from the list, or on desktop scans the QR code with a mobile wallet. More than 700 wallets connect through WalletConnect.

**3. Review**

The user reviews the address and taps **Verify address**. The page names the wallet that will ask for approval and states that no funds move.

![Review screen showing the Solana network and shortened address, the wallet that will ask for approval, and a Verify address button](https://mintcdn.com/walletconnect_pay_docs/NTAC-zItrJgRsb90/images/wallet-verification/review.png?fit=max\&auto=format\&n=NTAC-zItrJgRsb90\&q=85\&s=02ac86acc0e75ae06013c7d1c2bde59c)

**4. Add personal details**

Only shown if your account collects user information. After tapping **Verify address**, the user enters their full name, date of birth, and city and country of birth, then accepts the terms.

![Personal details form asking for full name, date of birth, city of birth and country of birth, with an I agree checkbox and a Confirm button](https://mintcdn.com/walletconnect_pay_docs/NTAC-zItrJgRsb90/images/wallet-verification/personal-details.png?fit=max\&auto=format\&n=NTAC-zItrJgRsb90\&q=85\&s=a71015ac34a632da9579ce9001aef413)

**5. Sign**

The user signs the message in their wallet. The [signed message](/wallet-verification/attestations.md#signed-message) names your business and the purpose.

**6. Done**

The page shows **Wallet verified** if you set `expected_address`, or **Wallet added** if you didn't. With a `return_url`, it sends the user back to your app after 5 seconds, or right away when they tap **Return to** your business name.

![Success screen titled Wallet verified, counting down 5 seconds before returning the user to Acme Inc, with a Return to Acme Inc button](https://mintcdn.com/walletconnect_pay_docs/NTAC-zItrJgRsb90/images/wallet-verification/verified.png?fit=max\&auto=format\&n=NTAC-zItrJgRsb90\&q=85\&s=ad1c3c4e90ee16846dba59974c577dca)

### Errors the user can see

| Error | What it means |
| - | - |
| Wrong wallet | The connected address does not match `expected_address`. |
| Wrong network | The wallet is on a different network than `chain_id`. |
| Invalid signature | The signature did not verify. This is terminal: the verification ends as `failed`, and the user needs a fresh link from you. |
| Unsupported wallet type | The wallet type is not supported. See [Supported wallets and networks](#supported-wallets-and-networks). |
| Unsupported network | The network is not supported. |
| Chain temporarily unavailable | The page could not reach the chain. The user can retry. |

## Return to your app

Set `return_url` when you create a verification to send the user back to your app. After a successful verification the page returns the user automatically after 5 seconds, unless it is [in an iframe](#embed-in-an-iframe). The **Return to** button (it shows your business name) on the success and error screens, and the **Cancel** button, navigate to `return_url` exactly as you gave it. Nothing is appended, so look up the result by polling.

Without a `return_url`, the success screen tells the user they can close the page, and the other buttons close the tab.

The `return_url` must be HTTPS, and its origin must be on your account's allowed list (exact `https://host[:port]`, up to 20 origins). Otherwise create returns `400 invalid_return_url`. See [Integration settings](/wallet-verification/dashboard.md#integration-settings) to register origins.

## Embed in an iframe

You can show the verification page inside your app in an iframe. The page can only be framed by origins on your account's embedding list. Without one, the page refuses to be framed (`frame-ancestors 'none'`).

Embedding origins are `https://host` or `https://*.host`, up to 20. Each host must be a registrable domain. IP addresses, `localhost`, and bare platform suffixes such as `*.vercel.app` are not allowed. See [Integration settings](/wallet-verification/dashboard.md#integration-settings) to register origins.

The page is served from these origins:

| Environment | Verification page origin |
| - | - |
| Production | `https://wallet-verification.walletconnect.com` |
| Staging | `https://staging.wallet-verification.walletconnect.com` |

When embedded:

* **When the user verifies**, the page posts a `verified` message to the parent window right away, without waiting for a click.
* **No automatic return** when framed. The 5-second return only runs when the page is not in an iframe. Close the frame or move on when you get `verified`.
* **With a `return_url`**, the Return and Cancel buttons navigate the top window. If your iframe is sandboxed, add `allow-top-navigation-by-user-activation`. Otherwise only the iframe navigates.
* **Without a `return_url`**, the Return and Cancel buttons post a message to the parent window instead of navigating:

```json postMessage payload theme={null}
{ "type": "wallet_verification:return", "state": "verified" }
```

`state` is one of `verified`, `cancelled`, `failed`, `expired`, `not_found`, `pending`, or `unknown`. The message is only sent to an origin on your embedding list, never to `*`.

```javascript Listen for the return message theme={null}
window.addEventListener("message", (event) => {
  if (event.origin !== "https://wallet-verification.walletconnect.com") return;
  if (event.data?.type !== "wallet_verification:return") return;

  // Treat this as a hint. Confirm the result on your backend.
  closeVerificationFrame();
  refreshVerificationStatus();
});
```

> [!WARNING]
>
> Browsers that do not expose the parent origin, such as Firefox without a referrer, receive no message. Always confirm the result server-side by polling `GET /verifications/{id}`.

## Supported wallets and networks

| Network | Supported | Not supported |
| - | - | - |
| EVM | Regular accounts (EOA), EIP-7702 accounts, smart contract wallets (ERC-1271), smart wallets that are not deployed yet (ERC-6492) | Multi-signature wallets that need several approvers |
| Solana | Regular accounts (ed25519) | Program-derived addresses |

An EVM address is the same on every EVM chain. A verification proves control of the address.

## Limitations

* Multi-signature wallets that need more than one approver, such as a Safe with a threshold above 1, are not supported yet. Today such a verification ends as `failed`. Multisig support is planned.
* Solana program-derived addresses are not supported.
* Allowed return-URL and embedding origins are not self-serve yet. See [Integration settings](/wallet-verification/dashboard.md#integration-settings).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.