Wagmi
Wagmi Overview¶
Wagmi is an Ethereum development Hooks library designed for React applications, providing over 20 Hooks to handle common needs such as account connection, contract interaction, transaction sending, and ENS resolution. Built on Viem, Wagmi has become the preferred library for React Web3 development thanks to its type safety, high performance, and modular design. It not only simplifies the complexity of blockchain interactions but also provides enterprise-grade features such as caching, request deduplication, and multi-chain support.
Official Website: https://wagmi.sh/
Core Features¶
1. Rich Hooks¶
Comprehensive feature coverage:
- Account Management: useAccount, useConnect, useDisconnect, useSwitchAccount
- Network Management: useChainId, useSwitchChain, useChains
- Balance Queries: useBalance, useToken
- Contract Interaction: useReadContract, useWriteContract, useWatchContractEvent
- Transaction Operations: useSendTransaction, useWaitForTransactionReceipt
- ENS Support: useEnsName, useEnsAddress, useEnsAvatar
- Signing Features: useSignMessage, useSignTypedData
2. Type Safety¶
Complete TypeScript support:
- Automatic Type Inference: Automatically infers function parameters and return types based on ABI
- Compile-Time Checks: Discover type errors at compile time
- Smart Suggestions: IDE auto-completion and parameter hints
- Type Guards: Ensure runtime type safety
- Generic Support: Supports generic contracts and custom types
3. Query Caching¶
Based on TanStack Query:
- Automatic Caching: Intelligently caches query results
- Request Deduplication: Identical requests are automatically merged
- Background Updates: Automatically refreshes expired data in the background
- Optimistic Updates: Supports optimistic UI updates
- Cache Persistence: Optional local storage persistence
4. Multi-Chain Support¶
Simplified cross-chain development:
- Chain Configuration: Pre-defined configurations for mainstream blockchains
- Dynamic Switching: One-click network switching for users
- Multi-Chain State: Manage state across multiple chains simultaneously
- Custom Chains: Easily add custom networks
- Testnets: Built-in testnet support
Quick Start¶
Installation¶
Basic Configuration¶
import { WagmiProvider, createConfig, http } from 'wagmi'
import { mainnet, sepolia } from 'wagmi/chains'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
// Create configuration
const config = createConfig({
chains: [mainnet, sepolia],
transports: {
[mainnet.id]: http(),
[sepolia.id]: http()
}
})
const queryClient = new QueryClient()
function App() {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
{/* Your App */}
</QueryClientProvider>
</WagmiProvider>
)
}
Connect Wallet¶
import { useConnect, useAccount, useDisconnect } from 'wagmi'
import { injected } from 'wagmi/connectors'
function Connect() {
const { connect } = useConnect()
const { address, isConnected } = useAccount()
const { disconnect } = useDisconnect()
if (isConnected) {
return (
<div>
<p>Connected: {address}</p>
<button onClick={() => disconnect()}>Disconnect</button>
</div>
)
}
return (
<button onClick={() => connect({ connector: injected() })}>
Connect MetaMask
</button>
)
}
Common Hooks¶
1. Account and Network¶
Get account and network information:
import { useAccount, useChainId, useBalance } from 'wagmi'
function Account() {
const { address, isConnected, connector } = useAccount()
const chainId = useChainId()
const { data: balance } = useBalance({ address })
return (
<div>
<p>Address: {address}</p>
<p>Chain ID: {chainId}</p>
<p>Balance: {balance?.formatted} {balance?.symbol}</p>
<p>Connector: {connector?.name}</p>
</div>
)
}
2. Read Contract¶
Read smart contract data:
import { useReadContract } from 'wagmi'
import { erc20Abi } from 'viem'
function TokenBalance({ address, tokenAddress }) {
const { data: balance } = useReadContract({
address: tokenAddress,
abi: erc20Abi,
functionName: 'balanceOf',
args: [address]
})
return <p>Token Balance: {balance?.toString()}</p>
}
3. Write Contract¶
Execute contract write operations:
import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
import { erc20Abi, parseUnits } from 'viem'
function Transfer() {
const { data: hash, writeContract } = useWriteContract()
const { isLoading, isSuccess } = useWaitForTransactionReceipt({
hash
})
const handleTransfer = () => {
writeContract({
address: '0x...',
abi: erc20Abi,
functionName: 'transfer',
args: ['0xRecipient...', parseUnits('1', 18)]
})
}
return (
<div>
<button onClick={handleTransfer} disabled={isLoading}>
{isLoading ? 'Sending...' : 'Send Tokens'}
</button>
{isSuccess && <p>Transaction Successful!</p>}
</div>
)
}
4. Watch Events¶
Watch contract events:
import { useWatchContractEvent } from 'wagmi'
import { erc20Abi } from 'viem'
function TransferListener() {
useWatchContractEvent({
address: '0x...',
abi: erc20Abi,
eventName: 'Transfer',
onLogs(logs) {
console.log('Transfer event received:', logs)
}
})
return <p>Watching Transfer events...</p>
}
5. Send Transaction¶
Send ETH transactions:
import { useSendTransaction, useWaitForTransactionReceipt } from 'wagmi'
import { parseEther } from 'viem'
function SendETH() {
const { data: hash, sendTransaction } = useSendTransaction()
const { isLoading, isSuccess } = useWaitForTransactionReceipt({ hash })
const handleSend = () => {
sendTransaction({
to: '0xRecipient...',
value: parseEther('0.01')
})
}
return (
<div>
<button onClick={handleSend} disabled={isLoading}>
Send 0.01 ETH
</button>
{isSuccess && <p>Sent Successfully!</p>}
</div>
)
}
6. ENS Resolution¶
Use ENS domain names:
import { useEnsName, useEnsAddress, useEnsAvatar } from 'wagmi'
function ENSProfile({ address }) {
const { data: ensName } = useEnsName({ address })
const { data: avatar } = useEnsAvatar({ name: ensName })
return (
<div>
{avatar && <img src={avatar} alt="ENS Avatar" />}
<p>{ensName ?? address}</p>
</div>
)
}
Advanced Features¶
1. Multi-Chain Configuration¶
Support for multiple blockchains:
import { createConfig, http } from 'wagmi'
import { mainnet, polygon, arbitrum, optimism } from 'wagmi/chains'
const config = createConfig({
chains: [mainnet, polygon, arbitrum, optimism],
transports: {
[mainnet.id]: http('https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY'),
[polygon.id]: http('https://polygon-mainnet.g.alchemy.com/v2/YOUR_KEY'),
[arbitrum.id]: http(),
[optimism.id]: http()
}
})
2. Connector Configuration¶
Configure multiple wallet connection methods:
import { createConfig, http } from 'wagmi'
import { injected, walletConnect, coinbaseWallet } from 'wagmi/connectors'
const config = createConfig({
chains: [mainnet],
connectors: [
injected(),
walletConnect({ projectId: 'YOUR_PROJECT_ID' }),
coinbaseWallet({ appName: 'My App' })
],
transports: {
[mainnet.id]: http()
}
})
3. Batch Requests¶
Multicall batch queries:
import { useReadContracts } from 'wagmi'
import { erc20Abi } from 'viem'
function BatchRead() {
const { data } = useReadContracts({
contracts: [
{
address: '0xToken1',
abi: erc20Abi,
functionName: 'balanceOf',
args: ['0xUser']
},
{
address: '0xToken2',
abi: erc20Abi,
functionName: 'balanceOf',
args: ['0xUser']
}
]
})
return (
<div>
<p>Token1: {data?.[0].result?.toString()}</p>
<p>Token2: {data?.[1].result?.toString()}</p>
</div>
)
}
4. Custom Hooks¶
Create custom Hooks:
import { useReadContract } from 'wagmi'
import { erc20Abi } from 'viem'
function useTokenBalance(address, tokenAddress) {
const { data: balance, isLoading } = useReadContract({
address: tokenAddress,
abi: erc20Abi,
functionName: 'balanceOf',
args: [address],
watch: true // Auto-refresh
})
return {
balance: balance?.toString(),
isLoading
}
}
Best Practices¶
1. Error Handling¶
Comprehensive error handling:
import { useWriteContract } from 'wagmi'
function Transfer() {
const { writeContract, error, isError } = useWriteContract()
if (isError) {
return <p>Error: {error.message}</p>
}
// ...
}
2. Loading States¶
Elegant loading state management:
import { useReadContract } from 'wagmi'
function Data() {
const { data, isLoading, isError, error } = useReadContract({
// ...
})
if (isLoading) return <p>Loading...</p>
if (isError) return <p>Error: {error.message}</p>
return <p>Data: {data}</p>
}
3. Performance Optimization¶
Optimize rendering performance:
- Use appropriate cache times and refresh intervals
- Avoid unnecessary Hook calls
- Use React.memo to optimize components
- Use the watch parameter judiciously for auto-updates
4. Type Safety¶
Fully leverage TypeScript:
import { useReadContract } from 'wagmi'
import { Abi } from 'viem'
const myAbi = [...] as const // Use as const to preserve literal types
function MyComponent() {
const { data } = useReadContract({
abi: myAbi,
functionName: 'myFunction', // Type-safe function name
args: [...] // Automatically inferred parameter types
})
// data type is automatically inferred
}
Ecosystem¶
Official Tools¶
- Wagmi CLI: Generate React Hooks from ABIs
- *Viem*: Underlying Ethereum library
- TanStack Query: Data fetching and caching
- Wagmi Dev Tools: Development debugging tools
Integration Solutions¶
- RainbowKit: UI component library
- ConnectKit: Another UI solution
- Web3Modal: Wallet connection UI
- Dynamic: Wallet and authentication solution
Related Concepts and Technologies¶
- Viem: Wagmi's underlying library providing type-safe Ethereum interactions
- RainbowKit: Wallet connection UI library built on Wagmi
- TanStack Query: React data fetching and state management library
- Ethers.js: Another Ethereum JavaScript library
- Web3.js: Classic Ethereum JavaScript library
Summary¶
Wagmi greatly simplifies Ethereum DApp development by providing type-safe, high-performance React Hooks. Its modular design, powerful caching mechanism, and comprehensive TypeScript support make it the de facto standard for React Web3 development. Whether for simple wallet connections or complex DeFi protocol interactions, Wagmi provides elegant solutions. Combined with UI libraries like RainbowKit, developers can quickly build Web3 applications with an outstanding user experience.