# ethers.js vs viem vs wagmi Selection Guide ## Positioning | Library | Positioning | Use Cases | |----|------|------| | **ethers.js v6** | Full-featured EVM library, longest history | Backend scripts, Node.js tools | | **viem** | Lightweight, type-safe, high-performance | Modern frontend/backend, ethers alternative | | **wagmi** | React Hooks wrapper (built on viem) | Top choice for React DApp frontends | | **web3.js** | Oldest library, gradually being phased out | Legacy project maintenance only | ## Why viem is Replacing ethers Bundle size: viem ~35KB vs ethers ~280KB (gzipped) Tree-shaking: Import only what you need, unused code excluded Type safety: Automatic ABI type inference, better IDE autocomplete Performance: Faster execution for equivalent requests ```typescript // ethers v6 const provider = new ethers.JsonRpcProvider(RPC_URL) const balance = await provider.getBalance(address) // viem (same functionality, more lightweight) import { createPublicClient, http } from 'viem' import { mainnet } from 'viem/chains' const client = createPublicClient({ chain: mainnet, transport: http(RPC_URL) }) const balance = await client.getBalance({ address }) ``` ## wagmi Complete Example (React DApp) ```bash npm install wagmi viem @tanstack/react-query ``` ```tsx // wagmi config import { createConfig, http } from 'wagmi' import { mainnet, base, arbitrum } from 'wagmi/chains' import { injected, walletConnect } from 'wagmi/connectors' export const config = createConfig({ chains: [mainnet, base, arbitrum], connectors: [injected(), walletConnect({ projectId: 'YOUR_ID' })], transports: { [mainnet.id]: http(), [base.id]: http(), [arbitrum.id]: http() }, }) // Hooks usage import { useAccount, useBalance, useReadContract, useWriteContract } from 'wagmi' function MyDApp() { const { address, isConnected } = useAccount() const { data: balance } = useBalance({ address }) const { data: tokenBal } = useReadContract({ address: TOKEN_ADDRESS, abi: ERC20_ABI, functionName: 'balanceOf', args: [address!], query: { enabled: !!address } }) const { writeContract, isPending } = useWriteContract() return ( ) } ``` ## Decision Tree What is your project? - React DApp frontend → wagmi (Hooks wrapper, ready out of the box) - Next.js/pure frontend, don't want Hooks → viem - Node.js backend scripts/CLI → viem or ethers v6 - Maintaining legacy project (ethers v5) → Continue using, no rush to migrate - Maintaining legacy project (web3.js) → Use viem for new features ## npm Downloads (2024) - ethers: ~2.5M/week (still highest, growth slowing) - viem: ~2M/week (fastest growth) - wagmi: ~700K/week (rapid growth) - web3.js: ~500K/week (declining)