Wagmi v2 - How to Generate Instant, Type-Safe Hooks for Your Smart Contracts
In the fast-moving world of Web3, developer experience (DX) used to be an afterthought. We spent hours copy-pasting JSON ABIs, manually typing contract addresses, and wrestling with hex-encoded data.
Then came Wagmi.
Wagmi v2, paired with the Wagmi CLI, has fundamentally changed the game. Instead of manual setup, you can now generate type-safe React hooks that "know" your smart contract's functions before you even finish typing them.
Step 1: Installation
First, we need the core Wagmi library, its peer dependency Viem (the lightweight alternative to ethers.js), and TanStack Query for state management.
pnpm install wagmi viem @tanstack/react-queryNext, install the Wagmi CLI as a development dependency. This is the magic tool that will handle your ABIs.
pnpm install --save-dev @wagmi/cliStep 2: Configure Wagmi
Before we get to the CLI, we need a standard configuration for our app. Create a file named wagmi.ts (or config.ts).
// config/config.ts
import { http, createConfig } from 'wagmi'
import { mainnet, sepolia } from 'wagmi/chains'
import { injected, metaMask } from 'wagmi/connectors'
export const config = createConfig({
chains: [mainnet, sepolia],
connectors: [
injected(),
metaMask(),
],
transports: {
[mainnet.id]: http(),
[sepolia.id]: http(),
},
})Step 3: Initialize the Wagmi CLI
The CLI needs its own configuration file to know where to fetch your ABIs and where to output the generated code. Run the following command:
npx wagmi initThis creates a wagmi.config.ts file. This is where you tell Wagmi about your smart contracts.
Automating ABI Generation
You have two main ways to get your ABIs:
- From a local project (Hardhat/Foundry)
- From a block explorer (Etherscan)
Here is a powerhouse configuration that fetches an ABI directly from Etherscan and generates React hooks for it:
import { defineConfig, loadEnv } from "@wagmi/cli";
import { etherscan, react } from "@wagmi/cli/plugins";
import { mainnet } from "wagmi/chains";
export default defineConfig(() => {
const env = loadEnv({
envDir: process.cwd(),
});
return {
out: "lib/generated.ts",
plugins: [
etherscan({
apiKey: env.ETHERSCAN_API_KEY!,
chainId: mainnet.id,
contracts: [
{
name: "MyContract",
// Your smart contract address
address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
},
],
}),
react(), // This generates the custom hooks!
],
};
});Step 4: Run the Generator
Once your config is ready, run the generation command:
npx wagmi generateWagmi will now:
- Reach out to Etherscan
- Grab the ABI for the
MyContract - Create a file at
lib/generated.tscontaining custom hooks likeuseReadEnsRegistryOwner
Step 5: Put it All Together
Create a config/providers.tsx file, and wrap your application with the WagmiProvider and the QueryClientProvider.
// config/providers.tsx
"use client";
import { WagmiProvider } from "wagmi";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { config } from "./config";
import { ReactNode, useState } from "react";
export function Providers({ children }: { children: ReactNode }) {
const [queryClient] = useState(() => new QueryClient());
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</WagmiProvider>
);
}// app/layout.tsx
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}Using Your Generated Hook
Now, instead of writing useReadContract and passing in a messy ABI object, you can do this:
import { useReadEnsRegistryOwner } from './generated'
function MyComponent() {
const { data, isLoading } = useReadEnsRegistryOwner({
args: ['0x...'], // Your arguments are now type-checked!
})
if (isLoading) return <div>Loading...</div>
return <div>Owner: {data}</div>
}Why This Matters
By using the CLI to generate your ABIs and hooks:
- Type Safety: If a function name changes or you pass the wrong number of arguments, TypeScript will throw an error immediately.
- Speed: No more manual JSON imports.
- Maintainability: If you update your contract, just run
npx wagmi generateagain, and your entire frontend updates its types.
References
-
Wagmi Documentation
- https://wagmi.sh
- Official Wagmi library documentation and guides
-
Wagmi CLI Plugin Documentation
- https://wagmi.sh/cli
- Complete reference for CLI configuration and plugins
-
Viem Documentation
- https://viem.sh
- Lightweight Ethereum library as alternative to ethers.js
-
TanStack Query (React Query)
- https://tanstack.com/query/latest
- State management library for fetching and caching data
-
Etherscan API
- https://docs.etherscan.io
- Reference for retrieving smart contract ABIs from Etherscan