Get the FREE Ultimate OpenClaw Setup Guide →

wagmi

Scanned
npx machina-cli add skill 0xSardius/onchain-typescript-skills/wagmi --openclaw
Files (1)
SKILL.md
6.8 KB

Wagmi Skill

Version: Wagmi 3.x | Official Docs | Requires TypeScript 5.7.3+

Wagmi provides React hooks for Ethereum. This skill ensures correct patterns for provider setup, hooks usage, and React-specific pitfalls.

Quick Setup (Wagmi v3)

1. Config Setup

// config.ts
import { http, createConfig } from 'wagmi'
import { mainnet, polygon, arbitrum } from 'wagmi/chains'
// v3: Install connectors separately: npm i @wagmi/connectors
import { injected, coinbaseWallet, walletConnect } from '@wagmi/connectors'

export const config = createConfig({
  chains: [mainnet, polygon, arbitrum],
  connectors: [
    injected(),
    coinbaseWallet({ appName: 'My App' }),
    walletConnect({ projectId: 'YOUR_PROJECT_ID' }),
  ],
  transports: {
    [mainnet.id]: http('https://eth-mainnet.g.alchemy.com/v2/KEY'),
    [polygon.id]: http('https://polygon-mainnet.g.alchemy.com/v2/KEY'),
    [arbitrum.id]: http('https://arb-mainnet.g.alchemy.com/v2/KEY'),
  },
})

v3 Note: Connectors are now in @wagmi/connectors package for better dependency control.

2. Provider Setup

// providers.tsx
'use client' // Required for Next.js App Router

import { WagmiProvider } from 'wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { config } from './config'

const queryClient = new QueryClient()

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        {children}
      </QueryClientProvider>
    </WagmiProvider>
  )
}

Core Hooks

useAccount

import { useAccount } from 'wagmi'

function Profile() {
  const { address, isConnected, isConnecting, chain } = useAccount()
  
  if (isConnecting) return <div>Connecting...</div>
  if (!isConnected) return <div>Not connected</div>
  
  return <div>Connected: {address} on {chain?.name}</div>
}

useConnect / useDisconnect / useConnectors

import { useAccount, useConnect, useDisconnect, useConnectors } from 'wagmi'

function ConnectButton() {
  // v3: Use useConnectors() hook instead of getting from useConnect()
  const connectors = useConnectors()
  const { connect, isPending } = useConnect()
  const { disconnect } = useDisconnect()
  const { isConnected } = useAccount()

  if (isConnected) {
    return <button onClick={() => disconnect()}>Disconnect</button>
  }

  return (
    <div>
      {connectors.map((connector) => (
        <button
          key={connector.id}
          onClick={() => connect({ connector })}
          disabled={isPending}
        >
          {connector.name}
        </button>
      ))}
    </div>
  )
}

useReadContract (REPLACES useContractRead)

import { useReadContract } from 'wagmi'

function Balance() {
  const { data, isLoading, error, refetch } = useReadContract({
    address: '0x...',
    abi, // Use `as const` for type safety
    functionName: 'balanceOf',
    args: ['0x...'],
  })

  if (isLoading) return <div>Loading...</div>
  if (error) return <div>Error: {error.message}</div>
  
  return <div>Balance: {data?.toString()}</div>
}

useWriteContract (REPLACES useContractWrite)

import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'

function Transfer() {
  const { data: hash, writeContract, isPending, error } = useWriteContract()
  
  const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({
    hash,
  })

  async function handleTransfer() {
    writeContract({
      address: '0x...',
      abi,
      functionName: 'transfer',
      args: ['0x...', 1000n],
    })
  }

  return (
    <div>
      <button onClick={handleTransfer} disabled={isPending}>
        {isPending ? 'Confirming...' : 'Transfer'}
      </button>
      {isConfirming && <div>Waiting for confirmation...</div>}
      {isSuccess && <div>Transaction confirmed!</div>}
      {error && <div>Error: {error.message}</div>}
    </div>
  )
}

Critical Patterns

ABI Type Safety (CRITICAL)

// ✅ CORRECT - as const for full type inference
const abi = [
  {
    name: 'transfer',
    type: 'function',
    stateMutability: 'nonpayable',
    inputs: [
      { name: 'to', type: 'address' },
      { name: 'amount', type: 'uint256' },
    ],
    outputs: [{ name: '', type: 'bool' }],
  },
] as const

// ❌ WRONG - no type inference
const abi = [{ ... }] // Missing `as const`

Conditional Hook Calls (NEVER conditional)

// ❌ WRONG - Violates Rules of Hooks
function BadComponent({ shouldFetch }) {
  if (shouldFetch) {
    const { data } = useReadContract({ ... })
  }
}

// ✅ CORRECT - Use enabled option
function GoodComponent({ shouldFetch }) {
  const { data } = useReadContract({
    ...params,
    query: { enabled: shouldFetch },
  })
}

Stale Closure Prevention

// ❌ WRONG - Captures stale values
function BadComponent() {
  const [amount, setAmount] = useState(0n)
  
  const { writeContract } = useWriteContract()
  
  // This captures `amount` at render time!
  const handleClick = () => {
    writeContract({
      ...params,
      args: [amount], // May be stale!
    })
  }
}

// ✅ CORRECT - Pass fresh values
function GoodComponent() {
  const [amount, setAmount] = useState(0n)
  const { writeContract } = useWriteContract()

  const handleClick = () => {
    writeContract({
      ...params,
      args: [amount], // Fresh from closure
    })
  }
}

Common Mistakes

MistakeFix
useContractRead (v1)Use useReadContract
useContractWrite (v1)Use useWriteContract
connectors from useConnect (v2)Use useConnectors() hook (v3)
chains from useSwitchChain (v2)Use useChains() hook (v3)
Conditional hooksUse query: { enabled: bool }
Missing QueryClientProviderWagmi requires TanStack Query
Not awaiting hashUse useWaitForTransactionReceipt
String amountsUse BigInt: 1000n
Connectors from wagmi/connectorsUse @wagmi/connectors package (v3)

References

For detailed patterns, see:

Source

git clone https://github.com/0xSardius/onchain-typescript-skills/blob/main/skills/wagmi/SKILL.mdView on GitHub

Overview

Wagmi provides React hooks to connect wallets, read and write contracts, and manage blockchain state in React and Next.js apps. It standardizes provider setup, hook usage, and React-specific patterns for seamless Ethereum integration, with v3 connector handling and TypeScript 5.7.3+ support.

How This Skill Works

Configure supported chains and wallet connectors with createConfig, then wrap your app in WagmiProvider. Use core hooks like useAccount, useConnect, useReadContract (replacing useContractRead), and useWriteContract (replacing useContractWrite), often alongside RainbowKit or ConnectKit for a polished UI. Connectors are sourced from @wagmi/connectors to keep dependencies modular.

When to Use It

  • Building a React or Next.js DApp that requires wallet connections and on-chain state
  • Reading contract data (e.g., balances, totalSupply) with useReadContract
  • Submitting contract transactions via useWriteContract and tracking receipt status
  • Responding to wallet changes or network/chain updates to drive UI
  • Integrating Wagmi with wallet UI kits like RainbowKit or ConnectKit for a polished UX

Quick Start

  1. Step 1: Install required packages (e.g., npm install wagmi @wagmi/connectors)
  2. Step 2: Create a config.ts with chains, transports, and connectors using createConfig
  3. Step 3: Wrap your app with WagmiProvider (and optionally RainbowKit/ConnectKit) to enable hooks

Best Practices

  • Wrap your app with WagmiProvider at the root and load the config early
  • Use connectors from @wagmi/connectors; keep dependencies modular
  • Pass ABI with as const for type safety in useReadContract/useWriteContract
  • Prefer useReadContract/useWriteContract for contract interactions and monitor with useWaitForTransactionReceipt
  • Adopt 'use client' in Next.js pages and avoid Node-only scripts with Wagmi

Example Use Cases

  • A dashboard showing the connected address, chain, and ETH balance using useAccount and useReadContract
  • A token transfer button wired to a contract via useWriteContract with transaction status tracking
  • Reading on-chain values like token balances or totalSupply with useReadContract
  • UI reacts to connect/disconnect events to update user experience
  • Wallet onboarding with RainbowKit/ConnectKit integrated through WagmiProvider

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers