Web3 Frontend (wagmi + viem)
Build Web3 frontends with wagmi v2 and viem: wallet connection, contract reads/writes, transaction status, and multi-chain support.
Web3 frontends connect users' wallets to smart contracts. Modern Web3 development uses wagmi v2 (React hooks) + viem (TypeScript-native Ethereum client) as the de-facto standard, replacing the older web3.js/ethers.js stack.
Use wagmi v2 + viem for type-safe, modern Web3 development. Handle wallet connection, transaction state, and error recovery explicitly. Never assume a wallet is connected. Show clear feedback for all blockchain interactions.
Workflow
- Set up wagmi with RainbowKit or ConnectKitWallet connection is complex: multiple wallets, mobile deep links, WalletConnect protocol. Pre-built kits handle all of it.
- Read contract data with useReadContractContract reads are free (no gas) and should be cached and refetched automatically.
- Write transactions with useWriteContractWrites need user signing, gas estimation, and status tracking through pending→confirmed→finalized.
- Handle multi-chain and network switchingUsers may be on the wrong chain; silent failures confuse users.
- Handle errors and edge cases gracefullyBlockchain UX is notoriously poor; clear error messages differentiate good dApps.
Output Format
RainbowKit wallet connection, typed contract reads with useReadContract, writes with useWriteContract + status tracking, multi-chain support, error handling.
Examples
Read balance: `const { data: balance } = useReadContract({ address: USDC, abi: parseAbi(["function balanceOf(address) view returns (uint256)"]), functionName: "balanceOf", args: [address] })`Write with status: `const { writeContract, data: hash } = useWriteContract(); const { isSuccess } = useWaitForTransactionReceipt({ hash }); // show "Success!" when isSuccess`Chain guard: `if (chain?.id !== base.id) return <button onClick={() => switchChain({ chainId: base.id })}>Switch to Base</button>`Edge Cases & Gotchas
- ENS resolution: use viem's `getEnsAddress()` or wagmi's `useEnsAddress` - don't assume user input is always a 0x address
- Transaction replacement: users may speed up transactions (higher gas), invalidating the original hash; use `useWaitForTransactionReceipt` with `confirmations: 1` to handle this
- Mobile wallets: WalletConnect v2 is required; test with MetaMask mobile and Coinbase Wallet, not just browser extension
When to Break These Rules
- For read-only blockchain explorers or analytics dashboards, viem's `createPublicClient` without wagmi is simpler and avoids React dependency.
Reference Files
wagmi v2 docs: https://wagmi.sh/viem docs: https://viem.sh/RainbowKit: https://www.rainbowkit.com/OpenZeppelin ERC ABIs: https://docs.openzeppelin.com/contracts/4.x/api/token/erc20