dApp Wallet Integration Pre-Launch Checklist
A practical pre-launch checklist for dApp wallet integration covering security, UX, mobile, error handling, and chain configuration before you ship to users.
Wallet integration bugs found in production are the worst kind. They happen when real users with real funds hit a broken approval flow, a wrong-chain transaction, or a session that silently expires. A few hours of structured pre-launch review prevents weeks of emergency patches and trust damage that is difficult to recover from.
This checklist covers what to verify before your dApp goes live. Work through it sequentially — later items depend on earlier ones being solid.
Wallet Connection
- Multiple wallet types are supported. At minimum: injected providers (MetaMask, Rabby, Brave), WalletConnect v2, and Coinbase Wallet. If your audience includes non-crypto users, include an embedded wallet option.
- WalletConnect project ID is environment-specific. Dev, staging, and production each use a separate registered project ID. A shared ID will rate-limit and break production sessions.
- Connection state hydrates correctly on page refresh. The user should not need to reconnect on every load. Wagmi and similar libraries persist connection state in localStorage — verify this works across browsers.
- Disconnect is complete. When a user disconnects, all local session state, cached addresses, and authenticated tokens are cleared. Test both in-wallet disconnect and in-dApp disconnect.
- No hydration mismatch on SSR. If you are using Next.js or another SSR framework, wallet-dependent UI must render consistently between server and client. Use mounted state guards where needed.
Chain Configuration
- Only supported chains are listed. Every chain in your configuration appears in the wallet's network switcher. If your contracts are not on a chain, remove it.
- Wrong-network state is handled. When a user is on an unsupported chain, show a clear prompt and a one-click switch button that calls
wallet_switchEthereumChain. Do not show a broken UI or silent errors. - Chain ID is validated before every contract call. Do not assume the user is on the correct chain just because they connected on it. Wallets allow chain switching at any time.
- Contract addresses are environment-gated. Mainnet addresses are never accessible in development builds. Staging builds point to testnet addresses. Misrouted contract calls burn real funds.
Signing and Approvals
- Every signature request has a plain-language explanation. Before the wallet modal opens, show a UI step that explains what is being signed, what it authorizes, and what it costs.
- Token approval amounts are specific. Do not request
uint256.max(unlimited approval) unless your product genuinely requires it and you have explained the risk. Prefer exact amounts orpermitsignatures where the token supports EIP-2612. - EIP-712 typed data is used for structured signatures. Raw
eth_signis deprecated and shows a warning in most wallets. Useeth_signTypedData_v4for all structured data signing. - Signature replay protection is in place. Any off-chain signature that triggers an on-chain action must include a nonce, chain ID, and contract address in the signed payload.
- User rejection is handled gracefully. If a user rejects a signature or transaction, your UI recovers cleanly and allows them to try again. No unhandled promise rejections, no broken UI state.
Transaction Handling
- Gas estimates are shown before confirmation. Display an estimated fee in USD or a familiar unit before the user reaches the wallet confirmation step.
- Transaction pending state is tracked. Show a loading indicator while a transaction is in the mempool. Do not let the user trigger duplicate transactions by clicking the button again.
- Transaction receipt is verified, not just hash. A transaction hash being returned does not mean the transaction succeeded. Wait for the receipt and check
status === 1before showing a success state. - Failed transactions have actionable error messages. Parse revert reasons from the receipt and translate them into human-readable messages. "Insufficient allowance" is more useful than "Transaction reverted."
- Nonce management is handled for rapid transactions. If your product submits multiple transactions in sequence, track the nonce manually rather than relying on
getTransactionCount, which may not reflect pending transactions.
Mobile and Cross-Browser
- WalletConnect deep link flow works on iOS and Android. Test with actual devices. The QR code flow is unreliable on mobile — deep links that open the user's installed wallet app are the correct mobile path.
- The connect flow works in Safari. Safari has stricter popup and storage restrictions than Chrome. Test localStorage persistence and popup-based redirects specifically in Safari.
- No extension-dependent UX exists. Do not show instructions like "click the MetaMask extension icon" — extension UI varies by browser and is not available on mobile.
Security
- No private keys, mnemonics, or sensitive data appear in client code or logs. Run a grep across your codebase before shipping.
- Content Security Policy headers are set. CSP headers prevent injected scripts from accessing wallet state or intercepting signatures.
- RPC endpoints are authenticated. Do not expose raw, unauthenticated Infura or Alchemy API keys in client-side code. Use environment-specific keys with domain restrictions set in the provider dashboard.
- Phishing simulation has been run. Open your app URL with a trailing slash, query parameter variation, or similar typo. Confirm that your domain validation and SIWE message includes the exact expected origin.
Monitoring
- Wallet errors are tracked in your error monitoring tool. Failed connections, rejected signatures, and revert errors should create events in your observability stack so you see them before users report them.
- Funnel analytics are instrumented. Track conversion from modal open through first transaction confirmed. You need this data to improve post-launch.
If your team wants an integration review before launch, or needs to ship a wallet integration that passes this checklist from the start, Start a build with Clixo.