Skip to content
Back to skills

Wagmi

ASecurity

wagmi is a set of React hooks for Ethereum, built on viem, for connecting wallets, reading contracts, sending transactions and switching chains. Use it when a user asks to connect wallets in React, read blockchain data in components, send transactions from a frontend, upgrade wagmi v2 to v3, or build a Web3 user interface in React or Next.js.

  • 142 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 6, 2026
developmenttypescriptgobashreactnextjsnodegitfrontend

Works with

  • terminal
  • cli

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned October 4, 2026

npx -y skills add TerminalSkills/skills --skill wagmi --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Wagmi?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Wagmi
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/terminalskills-wagmi/badge)](https://www.skillsdirectory.com/skills/terminalskills-wagmi)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: wagmi
description: >-
  wagmi is a set of React hooks for Ethereum, built on viem, for connecting
  wallets, reading contracts, sending transactions and switching chains. Use it
  when a user asks to connect wallets in React, read blockchain data in
  components, send transactions from a frontend, upgrade wagmi v2 to v3, or
  build a Web3 user interface in React or Next.js.
license: Apache-2.0
compatibility: 'wagmi 3 needs React 18+, viem 2.x, @tanstack/react-query 5 and TypeScript 5.9.3+'
metadata:
  author: terminal-skills
  version: 1.1.0
  category: development
  repository: https://github.com/wevm/wagmi
  tags:
    - wagmi
    - viem
    - react
    - wallet
    - dapp
---

# wagmi

## Overview

wagmi provides React hooks for Ethereum: wallet connection, contract reads and writes, transaction signing and chain switching. It is built on viem (the TypeScript Ethereum library) and TanStack Query, so every read hook returns query state (`data`, `isLoading`, `refetch`) and every write hook is a mutation.

Version checked: wagmi 3.7 (peer deps: `viem` 2.x, `react` >= 18, `@tanstack/react-query` >= 5, `typescript` >= 5.9.3). If a project is on wagmi 2, `useAccount`, `connect`, `writeContract` and `useConnect().connectors` still work there; v3 renames them (see Guidelines) and keeps the old names as deprecated aliases for now.

## Instructions

### Step 1: Install and configure

```bash
npm install wagmi viem@2.x @tanstack/react-query
npm install @walletconnect/ethereum-provider   # only if you use the walletConnect connector
```

In wagmi 3, connector SDKs are optional peer dependencies: install the one your connector needs (`walletConnect` needs `@walletconnect/ethereum-provider`, `coinbaseWallet` needs `@coinbase/wallet-sdk`, `metaMask` needs `@metamask/connect-evm`, `safe` needs the Safe apps packages). `injected()` needs nothing.

```typescript
// lib/wagmi.ts
import { createConfig, http, cookieStorage, createStorage } 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: process.env.NEXT_PUBLIC_WC_PROJECT_ID! }),
  ],
  ssr: true,                                   // Next.js: avoid hydration mismatch
  storage: createStorage({ storage: cookieStorage }),
  transports: {
    [mainnet.id]: http(process.env.NEXT_PUBLIC_MAINNET_RPC_URL),
    [base.id]: http(process.env.NEXT_PUBLIC_BASE_RPC_URL),
    [arbitrum.id]: http(process.env.NEXT_PUBLIC_ARBITRUM_RPC_URL),
  },
})

declare module 'wagmi' {
  interface Register { config: typeof config }  // makes hooks infer your chains
}
```

`http()` with no URL uses the chain's public RPC, which is rate limited; put a provider URL in an env var for production. The WalletConnect project id comes from the Reown dashboard.

### Step 2: Providers

```tsx
// app/providers.tsx
'use client'
import { useState, type ReactNode } from 'react'
import { WagmiProvider } from 'wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { config } from '@/lib/wagmi'

export function Providers({ children }: { children: ReactNode }) {
  const [queryClient] = useState(() => new QueryClient())
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
    </WagmiProvider>
  )
}
```

### Step 3: Connect a wallet

```tsx
'use client'
import { useConnection, useConnect, useConnectors, useDisconnect } from 'wagmi'

export function ConnectButton() {
  const { address, isConnected } = useConnection()   // v2: useAccount()
  const { mutate: connect } = useConnect()           // v2: const { connect } = useConnect()
  const connectors = useConnectors()                 // v2: useConnect().connectors
  const { mutate: disconnect } = useDisconnect()

  if (isConnected) {
    return (
      <div>
        <p>{address?.slice(0, 6)}...{address?.slice(-4)}</p>
        <button onClick={() => disconnect()}>Disconnect</button>
      </div>
    )
  }
  return (
    <div>
      {connectors.map((connector) => (
        <button key={connector.uid} onClick={() => connect({ connector })}>
          Connect {connector.name}
        </button>
      ))}
    </div>
  )
}
```

### Step 4: Read and write contracts

```tsx
'use client'
import { useReadContract, useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
import { erc20Abi, parseUnits, formatUnits, type Address } from 'viem'

const USDC_BASE: Address = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'

export function UsdcBalance({ owner }: { owner: Address }) {
  const { data: balance, isLoading } = useReadContract({
    address: USDC_BASE,
    abi: erc20Abi,
    functionName: 'balanceOf',
    args: [owner],
    chainId: 8453,
  })
  if (isLoading) return <p>Loading…</p>
  return <p>USDC: {balance !== undefined ? formatUnits(balance, 6) : '—'}</p>
}

export function SendUsdc({ to, amount }: { to: Address; amount: string }) {
  const { mutate: writeContract, data: hash, isPending, error } = useWriteContract()
  const { isLoading: confirming, isSuccess } = useWaitForTransactionReceipt({ hash })

  return (
    <>
      <button
        disabled={isPending || confirming}
        onClick={() =>
          writeContract({
            address: USDC_BASE,
            abi: erc20Abi,
            functionName: 'transfer',
            args: [to, parseUnits(amount, 6)],
            chainId: 8453,
          })
        }
      >
        {isPending ? 'Confirm in wallet…' : confirming ? 'Confirming…' : isSuccess ? 'Sent' : 'Send USDC'}
      </button>
      {error && <p role="alert">{error.message}</p>}
    </>
  )
}
```

`useSimulateContract` before `writeContract` catches reverts before the wallet prompt. Use `useWatchContractEvent` for live logs and `useSwitchChain` to move the wallet to the right network.

## Examples

### Example 1: Add wallet login to a Next.js app

**User request:** "Add a Connect Wallet button to my Next.js 15 app with MetaMask and WalletConnect, and show the ETH balance."

Install the packages from Step 1, create `lib/wagmi.ts` and `app/providers.tsx`, wrap `app/layout.tsx` children in `<Providers>`, and render `ConnectButton`. For the balance, `const { address } = useConnection(); const { data } = useBalance({ address })` then show `data?.formatted`-style output with `formatUnits(data.value, data.decimals)`. Result: the button lists "Connect Injected" and "Connect WalletConnect"; after connecting it shows `0x71C7…976F` and the balance, with no hydration warning thanks to `ssr: true` and cookie storage.

### Example 2: Upgrade a wagmi 2 project to 3

**User request:** "We are on wagmi 2.x, bump it to 3 and fix the build."

Run `npm install wagmi@3 viem@2 @tanstack/react-query@5` and raise `typescript` to 5.9.3 or newer. Install the connector SDKs your config uses. Rename `useAccount` to `useConnection`, `useAccountEffect` to `useConnectionEffect`, `useSwitchAccount` to `useSwitchConnection`; change `const { connect } = useConnect()` to `const { mutate: connect } = useConnect()` (same for `writeContract`, `disconnect`, `switchChain`), and replace `useConnect().connectors` with `useConnectors()` and `useSwitchChain().chains` with `useChains()`. Run `npx tsc --noEmit`; deprecated names still compile but are flagged.

## Guidelines

- Always handle the wrong-network case: pass `chainId` to hooks, and offer `useSwitchChain` when the wallet is on another chain.
- Never hard-code RPC keys in client code; use env vars and a provider allowlist, because `NEXT_PUBLIC_*` values are public.
- Amounts are `bigint` in token units: use `parseUnits` and `formatUnits` with the token's decimals (USDC has 6, not 18).
- Contract hooks are only fully typed when the ABI is declared `as const` (or comes from `viem`'s exported ABIs or `@wagmi/cli` codegen).
- Import `type Address` from viem and type addresses as `0x${string}`.
- Use viem directly (`createPublicClient`) for server-side reads; hooks need a client component.
- Add RainbowKit, ConnectKit or Reown AppKit if you need a ready-made wallet modal; they track wagmi's major versions, so check compatibility before upgrading.

Files in this skill

  • SKILL.md4 KB
  • _scores.json1.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…