WalletConnect Wallet Integration
WalletConnect v2 — this is not just "add a Connect Wallet button". Protocol built on relay servers from Walletconnect Cloud, uses its own JSON-RPC over WebSocket, and requires understanding session management to avoid broken UX on network switching or disconnect.
How It Works Under the Hood
WalletConnect v2 uses Sign API and Auth API over its relay protocol. A key pair (topic + symmetric key) created on session init, QR code encodes URI format wc:topic@2?relay-protocol=irn&symKey=.... Wallet (MetaMask Mobile, Trust, Rainbow) scans QR, establishes encrypted channel via relay.walletconnect.com.
For dApp development don't work directly with WalletConnect SDK — this handled by wagmi + @web3modal/wagmi (or ConnectKit, RainbowKit).
Integration via wagmi v2 + Web3Modal
// config.ts
import { createConfig, http } from 'wagmi'
import { mainnet, polygon, arbitrum } from 'wagmi/chains'
import { walletConnect, injected, coinbaseWallet } from 'wagmi/connectors'
export const config = createConfig({
chains: [mainnet, polygon, arbitrum],
connectors: [
injected(),
walletConnect({ projectId: process.env.NEXT_PUBLIC_WC_PROJECT_ID! }),
coinbaseWallet({ appName: 'Your App' }),
],
transports: {
[mainnet.id]: http(),
[polygon.id]: http(),
[arbitrum.id]: http(),
},
})
projectId obtained at cloud.walletconnect.com — without it connection works only in dev through public relay, in production will fail with rate limit.
Session Management
Critical moment often overlooked: WalletConnect sessions persistent. User closed tab, opened again — session should restore without new QR. wagmi handles this automatically via localStorage, but need to properly initialize WagmiProvider before any hook usage:
// app/providers.tsx
'use client'
import { WagmiProvider } from 'wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { config } from './config'
const queryClient = new QueryClient()
export function Providers({ children }: { children: React.ReactNode }) {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</WagmiProvider>
)
}
Network Switching
wallet_switchEthereumChain — standard RPC method. If network not added to wallet, need wallet_addEthereumChain. wagmi abstracts this via useSwitchChain, but behavior differs across wallets: MetaMask shows popup, WalletConnect-connected mobile wallets may ignore request or require manual confirmation in app.
Common Problems
Hydration mismatch in Next.js — useAccount() returns different state on server and client. Solution: ssr: false for components with wallet state, or useEffect for reading state only on client.
Mobile deep links — on iOS/Android WalletConnect should open wallet via universal link. Web3Modal handles this, but if writing custom UI — need to pass redirect parameter on session init.
Session expiry — sessions live 7 days by default. Need to handle session_expire event and show user offer to reconnect.
Development takes 2–3 days: setup wagmi config, integrate Web3Modal or RainbowKit, test on real mobile wallets (MetaMask Mobile, Trust Wallet), handle edge cases with network switching and session persistence.







