protocols/wagmi-viem-integration

wagmi + viem Frontend Integration

ethereumguide🏛️ Officialconfidence highhealth 100%
v1.0.0·Updated 3/20/2026

Installation

npm install wagmi viem @tanstack/react-query

Configuration Setup

// config.ts
import { createConfig, http } from 'wagmi'
import { mainnet, sepolia, polygon, base } from 'wagmi/chains'
import { injected, walletConnect, coinbaseWallet } from 'wagmi/connectors'

export const config = createConfig({
  chains: [mainnet, sepolia, polygon, base],
  connectors: [
    injected(),
    walletConnect({ projectId: 'YOUR_PROJECT_ID' }),
    coinbaseWallet({ appName: 'My App' }),
  ],
  transports: {
    [mainnet.id]: http(),
    [sepolia.id]: http(),
  },
})
// App.tsx
import { WagmiProvider } from 'wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { config } from './config'

const queryClient = new QueryClient()

export function App() {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <YourApp />
      </QueryClientProvider>
    </WagmiProvider>
  )
}

Common Hooks

import { useAccount, useConnect, useDisconnect, useBalance, useReadContract, useWriteContract, useWaitForTransactionReceipt } from 'wagmi'

// Connection status
const { address, isConnected, chain } = useAccount()

// Balance
const { data: balance } = useBalance({ address, token: USDC_ADDRESS })

// Read contract
const { data: totalSupply } = useReadContract({
  address: TOKEN_ADDRESS, abi: ERC20_ABI, functionName: 'totalSupply',
})

// Write contract
const { writeContract, data: hash } = useWriteContract()
const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ hash })

function sendTx() {
  writeContract({ address: CONTRACT, abi: ABI, functionName: 'transfer', args: [to, amount] })
}

Direct viem Usage (Without React)

import { createPublicClient, createWalletClient, http, parseEther } from 'viem'
import { mainnet } from 'viem/chains'

// Read
const publicClient = createPublicClient({ chain: mainnet, transport: http() })
const balance = await publicClient.getBalance({ address: '0x...' })
const result = await publicClient.readContract({ address, abi, functionName: 'balanceOf', args: [userAddr] })

// Write
const walletClient = createWalletClient({ account, chain: mainnet, transport: http() })
const hash = await walletClient.writeContract({ address, abi, functionName: 'transfer', args: [to, parseEther('1')] })
await publicClient.waitForTransactionReceipt({ hash })

TypeScript ABI Type Inference

// Use const assertion to preserve type information
const ERC20_ABI = [...] as const
// Or use viem's parseAbi
import { parseAbi } from 'viem'
const abi = parseAbi(['function balanceOf(address) returns (uint256)', 'event Transfer(address indexed from, address indexed to, uint256 value)'])

Common Pitfalls

  • useReadContract has a default refetch interval of 4s; set watch: true for real-time monitoring
  • After writeContract returns a hash, you still need useWaitForTransactionReceipt to wait for confirmation
  • In multi-chain projects, note that when switching chains the address remains the same but chainId changes—monitor chain.id
  • WalletConnect projectId must be obtained from cloud.walletconnect.com