Web37 min read

Web3 Frontend (wagmi + viem)

Build Web3 frontends with wagmi v2 and viem: wallet connection, contract reads/writes, transaction status, and multi-chain support.

web3wagmiethereumreact

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

  1. Set up wagmi with RainbowKit or ConnectKitWallet connection is complex: multiple wallets, mobile deep links, WalletConnect protocol. Pre-built kits handle all of it.
  2. Read contract data with useReadContractContract reads are free (no gas) and should be cached and refetched automatically.
  3. Write transactions with useWriteContractWrites need user signing, gas estimation, and status tracking through pending→confirmed→finalized.
  4. Handle multi-chain and network switchingUsers may be on the wrong chain; silent failures confuse users.
  5. 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

More skills in this library

Browse all technical skills - Mobile, AI/ML, Web, Backend, Design, and Product.