Web3 Frontend Skill
Master Web3 frontend development with wallet integration, modern libraries (viem/wagmi), and production dApp patterns.
Quick Start
Invoke this skill for Web3 frontend development
Skill("web3-frontend", topic="wallet", framework="react")
Topics Covered 1. Wallet Integration
Connect users to Web3:
RainbowKit: Beautiful wallet modal WalletConnect: Mobile support Account Abstraction: ERC-4337 Multi-chain: Network switching 2. Transaction Management
Handle blockchain interactions:
Write Operations: Contract writes State Tracking: Pending, confirmed Gas Estimation: Fee display Error Handling: User-friendly messages 3. Signing & Auth
Verify user identity:
EIP-712: Typed data signing SIWE: Sign-In with Ethereum Permit: Gasless approvals Message Signing: Personal sign 4. React Hooks
Modern patterns with wagmi:
useAccount: Connection state useWriteContract: Transactions useReadContract: Data fetching useWaitForTransactionReceipt: Confirmations Code Examples Connect Wallet 'use client';
import { ConnectButton } from '@rainbow-me/rainbowkit'; import { useAccount } from 'wagmi';
export function WalletConnect() { const { address, isConnected } = useAccount();
return (
Connected: {address}
}Write Contract import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'; import { parseEther } from 'viem';
export function MintButton() { const { writeContract, data: hash, isPending } = useWriteContract(); const { isLoading, isSuccess } = useWaitForTransactionReceipt({ hash });
const mint = () => { writeContract({ address: '0x...', abi: [...], functionName: 'mint', args: [1n], value: parseEther('0.08'), }); };
return ( ); }
Sign Typed Data (EIP-712) import { useSignTypedData } from 'wagmi';
const DOMAIN = { name: 'My App', version: '1', chainId: 1, verifyingContract: '0x...', };
export function useSignOrder() { const { signTypedDataAsync } = useSignTypedData();
const sign = async (order: Order) => { return await signTypedDataAsync({ domain: DOMAIN, types: { Order: [...] }, primaryType: 'Order', message: order, }); };
return { sign }; }
Error Handling export function parseError(error: unknown): string { const msg = error instanceof Error ? error.message : String(error);
if (msg.includes('user rejected')) return 'Transaction cancelled'; if (msg.includes('insufficient funds')) return 'Insufficient balance'; if (msg.includes('execution reverted')) { const reason = msg.match(/reason="([^"]+)"/)?.[1]; return reason || 'Transaction would fail'; }
return 'Transaction failed'; }
Package Setup npm install wagmi viem @rainbow-me/rainbowkit @tanstack/react-query
// providers/Web3.tsx import { WagmiProvider } from 'wagmi'; import { RainbowKitProvider } from '@rainbow-me/rainbowkit'; import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; import { config } from './config';
const queryClient = new QueryClient();
export function Web3Provider({ children }) {
return (
Common Patterns Pattern Use Case Hook Connect wallet User auth useAccount Read data Display balances useReadContract Write tx Mint, transfer useWriteContract Wait for tx Confirm state useWaitForTransactionReceipt Sign message Auth, permit useSignMessage Common Pitfalls Pitfall Issue Solution Hydration error SSR mismatch Use dynamic with ssr: false BigInt serialization JSON.stringify Custom serializer Stale data Cache issues Use refetchInterval Troubleshooting "Wallet not connecting" // Ensure client-side only import dynamic from 'next/dynamic';
const ConnectButton = dynamic( () => import('./ConnectButton'), { ssr: false } );
"Transaction pending forever"
Check gas settings or speed up:
await wallet.sendTransaction({ ...tx, maxFeePerGas: tx.maxFeePerGas * 120n / 100n, });
Security Checklist Never expose private keys Validate contract addresses Sanitize user inputs Use proper error boundaries Implement CSP headers Cross-References Bonded Agent: 05-web3-frontend Related Skills: ethereum-development, solidity-development Version History Version Date Changes 2.0.0 2025-01 Production-grade with wagmi v2, viem 1.0.0 2024-12 Initial release