Skip to content

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

npm install wagmi viem@2.x @tanstack/react-query

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
  • 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.