# Table of Contents - [Getting Started | Wagmi](#getting-started-wagmi) - [Wagmi | Reactivity for Ethereum apps](#wagmi-reactivity-for-ethereum-apps) - [Getting Started | Wagmi](#getting-started-wagmi) - [Getting Started | Wagmi](#getting-started-wagmi) - [Getting Started | Wagmi](#getting-started-wagmi) - [Contributing | Wagmi](#contributing-wagmi) - [Why Wagmi | Wagmi](#why-wagmi-wagmi) - [Installation | Wagmi](#installation-wagmi) - [TypeScript | Wagmi](#typescript-wagmi) - [Hooks | Wagmi](#hooks-wagmi) - [Comparison | Wagmi](#comparison-wagmi) - [Connectors | Wagmi](#connectors-wagmi) - [TanStack Query | Wagmi](#tanstack-query-wagmi) - [Viem | Wagmi](#viem-wagmi) - [Error Handling | Wagmi](#error-handling-wagmi) - [Why Wagmi | Wagmi](#why-wagmi-wagmi) - [Ethers.js Adapters | Wagmi](#ethers-js-adapters-wagmi) - [Chain Properties | Wagmi](#chain-properties-wagmi) - [Installation | Wagmi](#installation-wagmi) - [Why Wagmi Core | Wagmi](#why-wagmi-core-wagmi) - [SSR | Wagmi](#ssr-wagmi) - [Why Wagmi CLI | Wagmi](#why-wagmi-cli-wagmi) - [Installation | Wagmi](#installation-wagmi) - [TypeScript | Wagmi](#typescript-wagmi) - [Connect Wallet | Wagmi](#connect-wallet-wagmi) - [Installation | Wagmi](#installation-wagmi) - [TanStack Query | Wagmi](#tanstack-query-wagmi) - [TypeScript | Wagmi](#typescript-wagmi) - [Send Transaction | Wagmi](#send-transaction-wagmi) - [Creating Connectors | Wagmi](#creating-connectors-wagmi) - [Migrate from v1 to v2 | Wagmi CLI](#migrate-from-v1-to-v2-wagmi-cli) - [Viem | Wagmi](#viem-wagmi) - [Viem | Wagmi](#viem-wagmi) - [Read from Contract | Wagmi](#read-from-contract-wagmi) - [Configuring CLI | Wagmi](#configuring-cli-wagmi) - [Error Handling | Wagmi](#error-handling-wagmi) - [Framework Adapters | Wagmi](#framework-adapters-wagmi) - [Write to Contract | Wagmi](#write-to-contract-wagmi) - [Config Options | Wagmi](#config-options-wagmi) - [Error Handling | Wagmi](#error-handling-wagmi) - [Chain Properties | Wagmi](#chain-properties-wagmi) - [FAQ / Troubleshooting | Wagmi](#faq-troubleshooting-wagmi) - [Commands | Wagmi](#commands-wagmi) - [SSR | Wagmi](#ssr-wagmi) - [Ethers.js Adapters | Wagmi](#ethers-js-adapters-wagmi) - [generate | Wagmi](#generate-wagmi) - [Migrate from v1 to v2 | Wagmi](#migrate-from-v1-to-v2-wagmi) - [Connect Wallet | Wagmi](#connect-wallet-wagmi) - [Chain Properties | Wagmi](#chain-properties-wagmi) - [init | Wagmi](#init-wagmi) - [createConfig | Wagmi](#createconfig-wagmi) - [Send Transaction | Wagmi](#send-transaction-wagmi) - [FAQ / Troubleshooting | Wagmi](#faq-troubleshooting-wagmi) - [createStorage | Wagmi](#createstorage-wagmi) - [Plugins | Wagmi](#plugins-wagmi) - [Read from Contract | Wagmi](#read-from-contract-wagmi) --- # Getting Started | Wagmi Return to top Getting Started [​](#getting-started) ====================================== Overview [​](#overview) ------------------------ Wagmi is a React Hooks library for Ethereum. You can learn more about the rationale behind the project in the [Why Wagmi](/react/why) section. Automatic Installation [​](#automatic-installation) ---------------------------------------------------- For new projects, it is recommended to set up your Wagmi app using the [`create-wagmi`](/cli/create-wagmi) command line interface (CLI). This will create a new Wagmi project using TypeScript and install the required dependencies. pnpmnpmyarnbun bash pnpm create wagmi bash npm create wagmi@latest bash yarn create wagmi bash bun create wagmi Once the command runs, you'll see some prompts to complete. Project name: wagmi-project Select a framework: React / Vanilla ... After the prompts, `create-wagmi` will create a directory with your project name and install the required dependencies. Check out the `README.md` for further instructions (if required). Manual Installation [​](#manual-installation) ---------------------------------------------- To manually add Wagmi to your project, install the required packages. pnpmnpmyarnbun bash pnpm add wagmi viem@2.x @tanstack/react-query bash npm install wagmi viem@2.x @tanstack/react-query bash yarn add wagmi viem@2.x @tanstack/react-query bash bun add wagmi viem@2.x @tanstack/react-query * [Viem](https://viem.sh) is a TypeScript interface for Ethereum that performs blockchain operations. * [TanStack Query](https://tanstack.com/query/v5) is an async state manager that handles requests, caching, and more. * [TypeScript](/react/typescript) is optional, but highly recommended. Learn more about [TypeScript support](/react/typescript) . ### Create Config [​](#create-config) Create and export a new Wagmi config using `createConfig`. config.ts ts import { http, createConfig } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) In this example, Wagmi is configured to use the Mainnet and Sepolia chains, and `injected` connector. Check out the [`createConfig` docs](/react/api/createConfig) for more configuration options. TypeScript Tip If you are using TypeScript, you can "register" the Wagmi config or use the hook `config` property to get strong type-safety across React Context in places that wouldn't normally have type info. register confighook config property ts import { } from 'wagmi' ({ chainId: 123 })Type '123' is not assignable to type '1 | 11155111 | undefined'. declare module 'wagmi' { interface Register { : typeof } } ts import { } from 'wagmi' ({ chainId: 123, })Type '123' is not assignable to type '1 | 11155111 | undefined'. By registering or using the hook `config` property, `useBlockNumber`'s `chainId` is strongly typed to only allow Mainnet and Sepolia IDs. Learn more by reading the [TypeScript docs](/react/typescript#config-types) . ### Wrap App in Context Provider [​](#wrap-app-in-context-provider) Wrap your app in the `WagmiProvider` React Context Provider and pass the `config` you created earlier to the `value` property. app.tsxconfig.ts tsx import { WagmiProvider } from 'wagmi' import { config } from './config' function App() { return ( {/** ... */} ) } ts import { http, createConfig } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Check out the [`WagmiProvider` docs](/react/api/WagmiProvider) to learn more about React Context in Wagmi. ### Setup TanStack Query [​](#setup-tanstack-query) Inside the `WagmiProvider`, wrap your app in a TanStack Query React Context Provider, e.g. `QueryClientProvider`, and pass a new `QueryClient` instance to the `client` property. app.tsxconfig.ts tsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { WagmiProvider } from 'wagmi' import { config } from './config' const queryClient = new QueryClient() function App() { return ( {/** ... */} ) } ts import { http, createConfig } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Check out the [TanStack Query docs](https://tanstack.com/query/latest/docs/framework/react) to learn about the library, APIs, and more. ### Use Wagmi [​](#use-wagmi) Now that everything is set up, every component inside the Wagmi and TanStack Query Providers can use Wagmi React Hooks. profile.tsxapp.tsxconfig.ts tsx import { useAccount, useEnsName } from 'wagmi' export function Profile() { const { address } = useAccount() const { data, error, status } = useEnsName({ address }) if (status === 'pending') return
Loading ENS name
if (status === 'error') return
Error fetching ENS name: {error.message}
return
ENS name: {data}
} tsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { WagmiProvider } from 'wagmi' import { config } from './config' import { Profile } from './profile' const queryClient = new QueryClient() function App() { return ( ) } ts import { http, createConfig } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Next Steps [​](#next-steps) ---------------------------- For more information on what to do next, check out the following topics. * [**TypeScript**](/react/typescript) Learn how to get the most out of Wagmi's type-safety and inference for an enlightened developer experience. * [**Connect Wallet**](/react/guides/connect-wallet) Learn how to enable wallets to connect to and disconnect from your apps and display information about connected accounts. * [**React Hooks**](/react/api/hooks) Browse the collection of React Hooks and learn how to use them. * [**Viem**](/react/guides/viem) Learn about Viem and how it works with Wagmi. --- # Wagmi | Reactivity for Ethereum apps Looking for the 1.x docs? Check out [1.x.wagmi.sh](https://1.x.wagmi.sh) . Wagmi ===== Reactivity for Ethereum apps Type Safe, Extensible, and Modular by design. Build high-performance blockchain frontends. [Get Started](/react/getting-started) [Why Wagmi](/react/why) [View on GitHub](https://github.com/wevm/wagmi) ![Wagmi Logo](/logo-dark.svg) [🚀\ \ 20+ React Hooks\ ---------------\ \ React Hooks for accounts, wallets, contracts, transactions, signing, ENS, and more.\ \ See all hooks](/react/api/hooks) [🦄\ \ TypeScript Ready\ ----------------\ \ Infer types from ABIs and EIP-712 Typed Data and autocomplete your way to productivity.\ \ Learn about TypeScript support](/react/typescript) [💼\ \ Connect Wallet\ --------------\ \ Official connectors for MetaMask, EIP-6963, WalletConnect, Coinbase Wallet, and more.\ \ See all connectors](/react/api/connectors) [👟\ \ Caching. Deduplication. Persistence.\ ------------------------------------\ \ Built-in caching, deduplication, persistence powered by TanStack Query.\ \ How to use TanStack Query](/react/guides/tanstack-query) [🌳\ \ Modular By Design\ -----------------\ \ Don't use React or Vue? Use VanillaJS or build an adapter for your favorite framework.\ \ Learn about Wagmi Core](/core/getting-started) [✌️\ \ Built on Viem\ -------------\ \ The modern, low-level TypeScript interface for Ethereum that performs blockchain operations.\ \ Check out Viem](https://viem.sh) Meet The Team ------------- ![tmm](https://www.github.com/tmm.png) tmm === [](https://github.com/tmm) [](https://bsky.app/profile/tmm.dev) [](https://twitter.com/awkweb) [](https://warpcast.com/awkweb) ![jxom](https://www.github.com/jxom.png) jxom ==== [](https://github.com/jxom) [](https://bsky.app/profile/jxom.dev) [](https://twitter.com/_jxom) [](https://warpcast.com/jxom) Sponsored by ------------ [Become a sponsor](https://github.com/sponsors/wevm) --- # Getting Started | Wagmi Return to top Getting Started [​](#getting-started) ====================================== Overview [​](#overview) ------------------------ Wagmi is a collection of Vue composition utilities for Ethereum. You can learn more about the rationale behind the project in the [Why Wagmi](/vue/why) section. Automatic Installation [​](#automatic-installation) ---------------------------------------------------- For new projects, it is recommended to set up your Wagmi app using the [`create-wagmi`](/cli/create-wagmi) command line interface (CLI). This will create a new Wagmi project using TypeScript and install the required dependencies. pnpmnpmyarnbun bash pnpm create wagmi bash npm create wagmi@latest bash yarn create wagmi bash bun create wagmi Once the command runs, you'll see some prompts to complete. Project name: wagmi-project Select a framework: Vue / Vanilla ... After the prompts, `create-wagmi` will create a directory with your project name and install the required dependencies. Check out the `README.md` for further instructions (if required). Manual Installation [​](#manual-installation) ---------------------------------------------- To manually add Wagmi to your project, install the required packages. pnpmnpmyarnbun bash pnpm add @wagmi/vue viem@2.x @tanstack/vue-query bash npm install @wagmi/vue viem@2.x @tanstack/vue-query bash yarn add @wagmi/vue viem@2.x @tanstack/vue-query bash bun add @wagmi/vue viem@2.x @tanstack/vue-query * [Viem](https://viem.sh) is a TypeScript interface for Ethereum that performs blockchain operations. * [TanStack Query](https://tanstack.com/query/v5) is an async state manager that handles requests, caching, and more. * [TypeScript](/vue/typescript) is optional, but highly recommended. Learn more about [TypeScript support](/vue/typescript) . ### Create Config [​](#create-config) Create and export a new Wagmi config using `createConfig`. config.ts ts import { http, createConfig } from '@wagmi/vue' import { mainnet, sepolia } from '@wagmi/vue/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) In this example, Wagmi is configured to use the Mainnet and Sepolia chains, and `injected` connector. Check out the [`createConfig` docs](/vue/api/createConfig) for more configuration options. TypeScript Tip If you are using TypeScript, you can "register" the Wagmi config or use the hook `config` property to get strong type-safety in places that wouldn't normally have type info. register confighook config property ts import { } from '@wagmi/vue' ({ chainId: 123 })Type '123' is not assignable to type 'DeepMaybeRef<1 | 11155111 | undefined>'. declare module '@wagmi/vue' { interface Register { : typeof } } ts import { } from '@wagmi/vue' ({ chainId: 123, })Type '123' is not assignable to type 'DeepMaybeRef<1 | 11155111 | undefined>'. By registering or using the hook `config` property, `useBlockNumber`'s `chainId` is strongly typed to only allow Mainnet and Sepolia IDs. Learn more by reading the [TypeScript docs](/vue/typescript#config-types) . ### Add Plugin to App [​](#add-plugin-to-app) App the `WagmiPlugin` to your app instance and pass the `config` you created earlier to the plugin options. main.tsApp.vueconfig.ts tsx import { WagmiPlugin } from '@wagmi/vue' import { createApp } from 'vue' import { config } from './config' import App from './App.vue' createApp(App) .use(WagmiPlugin, { config }) .mount('#app') vue ts import { http, createConfig } from '@wagmi/vue' import { mainnet, sepolia } from '@wagmi/vue/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Check out the [`WagmiPlugin` docs](/vue/api/WagmiPlugin) to learn more about the plugin API. ### Setup TanStack Query [​](#setup-tanstack-query) After the `WagmiPlugin`, attach the `VueQueryPlugin` to your app, and pass a new `QueryClient` instance to the `queryClient` property. main.tsApp.vueconfig.ts tsx import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query' import { WagmiPlugin } from '@wagmi/vue' import { createApp } from 'vue' import { config } from './config' import App from './App.vue' const queryClient = new QueryClient() createApp(App) .use(WagmiPlugin, { config }) .use(VueQueryPlugin, { queryClient }) .mount('#app') vue ts import { http, createConfig } from '@wagmi/vue' import { mainnet, sepolia } from '@wagmi/vue/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Check out the [TanStack Query docs](https://tanstack.com/query/latest/docs/framework/vue) to learn about the library, APIs, and more. ### Use Wagmi [​](#use-wagmi) Now that everything is set up, every component inside your app can use Wagmi Vue Composables. App.vuemain.tsconfig.ts vue tsx import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query' import { WagmiPlugin } from '@wagmi/vue' import { createApp } from 'vue' import { config } from './config' import App from './App.vue' const queryClient = new QueryClient() createApp(App) .use(WagmiPlugin, { config }) .use(VueQueryPlugin, { queryClient }) .mount('#app') ts import { http, createConfig } from '@wagmi/vue' import { mainnet, sepolia } from '@wagmi/vue/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Next Steps [​](#next-steps) ---------------------------- For more information on what to do next, check out the following topics. * [**TypeScript**](/vue/typescript) Learn how to get the most out of Wagmi's type-safety and inference for an enlightened developer experience. * [**Connect Wallet**](/vue/guides/connect-wallet) Learn how to enable wallets to connect to and disconnect from your apps and display information about connected accounts. * [**Vue Composables**](/vue/api/composables) Browse the collection of Vue Composables and learn how to use them. * [**Viem**](/vue/guides/viem) Learn about Viem and how it works with Wagmi. --- # Getting Started | Wagmi Return to top Getting Started [​](#getting-started) ====================================== Overview [​](#overview) ------------------------ Wagmi Core is a VanillaJS library for Ethereum. You can learn more about the rationale behind the project in the [Why Wagmi](/core/why) section. Manual Installation [​](#manual-installation) ---------------------------------------------- To manually add Wagmi to your project, install the required packages. pnpmnpmyarnbun bash pnpm add @wagmi/core @wagmi/connectors viem@2.x bash npm install @wagmi/core @wagmi/connectors viem@2.x bash yarn add @wagmi/core @wagmi/connectors viem@2.x bash bun add @wagmi/core @wagmi/connectors viem@2.x * [Wagmi Connectors](/core/api/connectors) is a collection of interfaces for linking accounts/wallets to Wagmi. * [Viem](https://viem.sh) is a TypeScript interface for Ethereum that performs blockchain operations. * [TypeScript](/react/typescript) is optional, but highly recommended. Learn more about [TypeScript support](/core/typescript) . ### Create Config [​](#create-config) Create and export a new Wagmi config using `createConfig`. config.ts ts import { http, createConfig } from '@wagmi/core' import { mainnet, sepolia } from '@wagmi/core/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) In this example, Wagmi is configured to use the Mainnet and Sepolia chains. Check out the [`createConfig` docs](/core/api/createConfig) for more configuration options. ### Use Wagmi [​](#use-wagmi) Now that everything is set up, you can pass the `config` to use actions. index.tsconfig.ts tsx import { getAccount, getEnsName } from '@wagmi/core' import { config } from './config' const { address } = getAccount(config) const ensName = await getEnsName(config, { address }) ts import { http, createConfig } from '@wagmi/core' import { mainnet, sepolia } from '@wagmi/core/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Next Steps [​](#next-steps) ---------------------------- For more information on what to do next, check out the following topics. * [**TypeScript**](/core/typescript) Learn how to get the most out of Wagmi's type-safety and inference for an enlightened developer experience. * [**Actions**](/core/api/actions) Browse the collection of actions and learn how to use them. * [**Framework Adapters**](/core/guides/framework-adapters) Learn how to create a Wagmi-like adapter for your favorite framework. * [**Viem docs**](https://viem.sh) Wagmi Core is a wrapper around Viem that manages account and client reactivity. Learn more about Viem and how to use it. --- # Getting Started | Wagmi Return to top Getting Started [​](#getting-started) ====================================== Overview [​](#overview) ------------------------ Wagmi CLI is a command line interface for managing ABIs (from Etherscan/block explorers, Foundry/Hardhat projects, etc.), generating code (e.g. React Hooks), and much more. It makes working with Ethereum easier by automating manual work so you can build faster. You can learn more about the rationale behind the project in the [Why Wagmi CLI](/cli/why) section. Manual Installation [​](#manual-installation) ---------------------------------------------- To manually add Wagmi CLI to your project, install the required packages. pnpmnpmyarnbun bash pnpm add -D @wagmi/cli bash npm install --save-dev @wagmi/cli bash yarn add -D @wagmi/cli bash bun add -D @wagmi/cli Create Config File [​](#create-config-file) -------------------------------------------- Run the `init` command to generate a configuration file: either `wagmi.config.ts` if TypeScript is detected, otherwise `wagmi.config.js`. You can also create the configuration file manually. See [Configuring CLI](/cli/config/configuring-cli) for more info. pnpmnpmyarnbun bash pnpm wagmi init bash npx wagmi init bash yarn wagmi init bash bun wagmi init The generated configuration file will look something like this: wagmi.config.ts ts import { defineConfig } from '@wagmi/cli' export default defineConfig({ out: 'src/generated.ts', contracts: [], plugins: [], }) Add Contracts And Plugins [​](#add-contracts-and-plugins) ---------------------------------------------------------- Once the configuration file is set up, you can add contracts and plugins to it. These contracts and plugins are used to manage ABIs (fetch from block explorers, resolve from the file system, etc.), generate code (React hooks, etc.), and much more! For example, we can add the ERC-20 contract from Viem, and the [`etherscan`](/cli/api/plugins/etherscan) and [`react`](/cli/api/plugins/react) plugins. wagmi.config.ts ts import { defineConfig } from '@wagmi/cli' import { etherscan, react } from '@wagmi/cli/plugins' import { erc20Abi } from 'viem' import { mainnet, sepolia } from 'wagmi/chains' export default defineConfig({ out: 'src/generated.ts', contracts: [\ {\ name: 'erc20',\ abi: erc20Abi,\ },\ ], plugins: [\ etherscan({\ apiKey: process.env.ETHERSCAN_API_KEY!,\ chainId: mainnet.id,\ contracts: [\ {\ name: 'EnsRegistry',\ address: {\ [mainnet.id]: '0x314159265dd8dbb310642f98f50c066173c1259b',\ [sepolia.id]: '0x112234455c3a32fd11230c42e7bccd4a84e02010',\ },\ },\ ],\ }),\ react(),\ ], }) Run Code Generation [​](#run-code-generation) ---------------------------------------------- Now that we added a few contracts and plugins to the configuration file, we can run the [`generate`](/cli/api/commands/generate) command to resolve ABIs and generate code to the `out` file. pnpmnpmyarnbun bash pnpm wagmi generate bash npx wagmi generate bash yarn wagmi generate bash bun wagmi generate In this example, the `generate` command will do the following: * Validate the `etherscan` and `react` plugins * Fetch and cache the ENS Registry ABI from the Mainnet Etherscan API * Pull in the `erc20Abi` using the name `'ERC20'` * Generate React Hooks for both ABIs * Save ABIs, ENS Registry deployment addresses, and React Hooks to the `out` file Use Generated Code [​](#use-generated-code) -------------------------------------------- Once `out` is created, you can start using the generated code in your project. ts import { useReadErc20, useReadErc20BalanceOf } from './generated' // Use the generated ERC-20 read hook const { data } = useReadErc20({ address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', functionName: 'balanceOf', args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], }) // Use the generated ERC-20 "balanceOf" hook const { data } = useReadErc20BalanceOf({ address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], }) TIP Instead of committing the `out` file, you likely want to add `out` to your `.gitignore` and run `generate` during the build process or before you start your dev server in a `"predev"` script. Next Steps [​](#next-steps) ---------------------------- For more information on what to do next, check out the following topics. * [**Configuring CLI**](/cli/config/configuring-cli) Learn how to configure the CLI to work best for your project. * [**Commands**](/cli/api/commands) Learn more about the CLI commands and how to use them. * [**Plugins**](/cli/api/plugins) Browse the collection of plugins and set them up with your config. --- # Contributing | Wagmi Return to top Contributing [​](#contributing) ================================ Thanks for your interest in contributing to Wagmi! Please take a moment to review this document **before submitting a pull request.** Overview [​](#overview) ------------------------ This guide is intended to help you get started with contributing. By following these steps, you will understand the development process and workflow. If you want to contribute, but aren't sure where to start, you can create a [new discussion](https://github.com/wevm/wagmi/discussions/new/choose) . WARNING **Please ask first before starting work on any significant new features. This includes things like adding new hooks, actions, connectors, etc.** It's never a fun experience to have your pull request declined after investing time and effort into a new feature. To avoid this from happening, we request that contributors first create a [feature request](https://github.com/wevm/wagmi/discussions/new?category=ideas) to discuss any API changes or significant new ideas. 1\. Cloning the repository [​](#_1-cloning-the-repository) ----------------------------------------------------------- To start contributing to the project, clone it to your local machine using git: bash git clone https://github.com/wevm/wagmi.git Or the [GitHub CLI](https://cli.github.com) : bash gh repo clone wevm/wagmi 2\. Installing Node.js and pnpm [​](#_2-installing-node-js-and-pnpm) --------------------------------------------------------------------- Wagmi uses Node.js with [pnpm workspaces](https://pnpm.io/workspaces) to manage multiple projects. You can run the following command in your terminal to check your local Node.js version. bash node -v If **`node@22.x`** is not installed, you can install via [fnm](https://github.com/Schniz/fnm) or from the [official website](https://nodejs.org) . Once Node.js is installed, run the following to install [Corepack](https://nodejs.org/api/corepack.html) . Corepack automatically installs and manages **`pnpm@9.11.0`**. bash corepack enable 3\. Installing dependencies [​](#_3-installing-dependencies) ------------------------------------------------------------- Once in the project's root directory, run the following command to install pnpm (via Corepack) and the project's dependencies: bash pnpm install After the install completes, pnpm links packages across the project for development and [git hooks](https://github.com/toplenboren/simple-git-hooks) are set up. 4\. Adding the env variables [​](#_4-adding-the-env-variables) --------------------------------------------------------------- The [dev playgrounds](#_5-running-the-dev-playgrounds) and [test suite](#_6-running-the-test-suite) require environment variables to be set. Copy over the following environment variables to `.env`, and fill them out. bash VITE_MAINNET_FORK_URL=https://cloudflare-eth.com VITE_OPTIMISM_FORK_URL=https://mainnet.optimism.io NEXT_PUBLIC_WC_PROJECT_ID=3fbb6bba6f1de962d911bb5b5c9dba88 NUXT_PUBLIC_WC_PROJECT_ID=3fbb6bba6f1de962d911bb5b5c9dba88 VITE_WC_PROJECT_ID=3fbb6bba6f1de962d911bb5b5c9dba88 NEXT_TELEMETRY_DISABLED=1 NUXT_TELEMETRY_DISABLED=1 You might want to change `*_FORK_URL` to a paid RPC provider for better performance. 5\. Running the dev playgrounds [​](#_5-running-the-dev-playgrounds) --------------------------------------------------------------------- To start the local development playgrounds, run one of the following commands. These commands run playground apps, located at `./playgrounds`, that are set up for trying out code while making changes. bash pnpm dev # `wagmi` playground pnpm dev:core # `@wagmi/core` playground pnpm dev:create-wagmi # `create-wagmi` cli tool pnpm dev:cli # `@wagmi/cli` tool pnpm dev:next # `wagmi` playground with Next.js pnpm dev:nuxt # `@wagmi/vue` playground with Nuxt.js pnpm dev:react # `wagmi` playground (same as `pnpm dev`) pnpm dev:vue # `@wagmi/vue` playground Once a playground dev server is running, you can make changes to any of the package source files (e.g. `packages/react`) and it will automatically update the playground. 6\. Running the test suite [​](#_6-running-the-test-suite) ----------------------------------------------------------- Wagmi uses [Vitest](https://vitest.dev) to run tests and [Prool](https://github.com/wevm/prool) to execute tests against locally running chain forks. First, install [Anvil](https://github.com/foundry-rs/foundry/tree/master/anvil) via [Foundryup](https://book.getfoundry.sh/getting-started/installation) . bash curl -L https://foundry.paradigm.xyz | bash foundryup Next, make sure you have set up your [env variables](#_4-adding-the-env-variables) . Now you are ready to run the tests! You have the following options for running tests: * `pnpm test [package?]` — runs tests in watch mode * `pnpm test:cov` — runs tests and reports coverage * `pnpm test:core` — runs `@wagmi/core` tests * `pnpm test:react` — runs `wagmi` tests * `pnpm test:vue` — runs `@wagmi/vue` tests When adding new features or fixing bugs, it's important to add test cases to cover the new or updated behavior. If snapshot tests fail, you can run the `test:update` command to update the snapshots. 7\. Writing documentation [​](#_7-writing-documentation) --------------------------------------------------------- Documentation is crucial to helping developers of all experience levels use Wagmi. Wagmi uses [VitePress](https://vitepress.dev) for the documentation site (located at `./site`). To start the site in dev mode, run: bash pnpm docs:dev Try to keep documentation brief and use plain language so folks of all experience levels can understand. If you think something is unclear or could be explained better, you are welcome to open a pull request. 8\. Submitting a pull request [​](#_8-submitting-a-pull-request) ----------------------------------------------------------------- When you're ready to submit a pull request, you can follow these naming conventions: * Pull request titles use the [Imperative Mood](https://en.wikipedia.org/wiki/Imperative_mood) (e.g., `Add something`, `Fix something`). * [Changesets](#versioning) use past tense verbs (e.g., `Added something`, `Fixed something`). When you submit a pull request, GitHub will automatically lint, build, and test your changes. If you see an ❌, it's most likely a bug in your code. Please, inspect the logs through the GitHub UI to find the cause. **Please make sure that "Allow edits from maintainers" is enabled so the core team can make updates to your pull request if necessary.** 9\. Versioning [​](#_9-versioning) ----------------------------------- When adding new features or fixing bugs, we'll need to bump the package versions. We use [Changesets](https://github.com/changesets/changesets) to do this. TIP Only changes to the codebase that affect the public API or existing behavior (e.g. bugs) need changesets. Each changeset defines which packages should be published and whether the change should be a major/minor/patch release, as well as providing release notes that will be added to the changelog upon release. To create a new changeset, run `pnpm changeset`. This will run the Changesets CLI, prompting you for details about the change. You’ll be able to edit the file after it’s created — don’t worry about getting everything perfect up front. Even though you can technically use any markdown formatting you like, headings should be avoided since each changeset will ultimately be nested within a bullet list. Instead, bold text should be used as section headings. If your PR is making changes to an area that already has a changeset (e.g. there’s an existing changeset covering theme API changes but you’re making further changes to the same API), you should update the existing changeset in your PR rather than creating a new one. ### Releasing to npm [​](#releasing-to-npm) The first time a PR with a changeset is merged after a release, a new PR will automatically be created called `chore: version packages`. Any subsequent PRs with changesets will automatically update this existing version packages PR. Merging this PR triggers the release process by publishing to npm and cleaning up the changeset files. ### Creating a snapshot release [​](#creating-a-snapshot-release) If a PR has changesets, you can create a [snapshot release](https://github.com/changesets/changesets/blob/main/docs/snapshot-releases.md) by [manually dispatching](https://github.com/wevm/wagmi/actions/workflows/canary.yml) the Canary workflow. This publishes a tagged version to npm with the PR branch name and timestamp. 10\. Updating dependencies [​](#_10-updating-dependencies) ----------------------------------------------------------- Use [Taze](https://github.com/antfu/taze) by running: bash pnpm deps # prints outdated deps pnpm deps patch # print outdated deps with new patch versions pnpm deps -w # updates deps (best done with clean working tree) [Socket](https://socket.dev) checks pull requests for vulnerabilities when new dependencies and versions are added, but you should also be vigilant! When updating dependencies, you should check release notes and source code as well as lock versions when possible. --- # Why Wagmi | Wagmi Return to top Why Wagmi [​](#why-wagmi) ========================== The Problems [​](#the-problems) -------------------------------- Building Ethereum applications is hard. Apps need to support connecting wallets, multiple chains, signing messages and data, sending transactions, listening for events and state changes, refreshing stale blockchain data, and much more. This is all on top of solving for app-specific use-cases and providing polished user experiences. The ecosystem is also continuously evolving, meaning you need to adapt to new improvements or get left behind. App developers should not need to worry about connecting tens of different wallets, the intricacies of multi-chain support, typos accidentally sending an order of magnitude more ETH or calling a misspelled contract function, or accidentally spamming their RPC provider, costing thousands in compute units. Wagmi solves all these problems and more — allowing app developers to focus on building high-quality and performant experiences for Ethereum — by focusing on **developer experience**, **performance**, **feature coverage**, and **stability.** Developer Experience [​](#developer-experience) ------------------------------------------------ Wagmi delivers a great developer experience through modular and composable APIs, automatic type safety and inference, and comprehensive documentation. It provides developers with intuitive building blocks to build their Ethereum apps. While Wagmi's APIs might seem more verbose at first, it makes Wagmi's modular building blocks extremely flexible. Easy to move around, change, and remove. It also allows developers to better understand Ethereum concepts as well as understand _what_ and _why_ certain properties are being passed through. Learning how to use Wagmi is a great way to learn how to interact with Ethereum in general. Wagmi also provides [strongly typed APIs](/react/typescript) , allowing consumers to get the best possible experience through [autocomplete](https://twitter.com/awkweb/status/1555678944770367493) , [type inference](https://twitter.com/jakemoxey/status/1570244174502588417?s=20) , as well as static validation. You often just need to provide an ABI and Wagmi can help you autocomplete your way to success, identify type errors before your users do, drill into blockchain errors [at compile and runtimes](/react/guides/error-handling) with surgical precision, and much more. The API documentation is comprehensive and contains usage info for _every_ module in Wagmi. The core team uses a [documentation](https://gist.github.com/zsup/9434452) and [test driven](https://en.wikipedia.org/wiki/Test-driven_development#:~:text=Test%2Ddriven%20development%20(TDD),software%20against%20all%20test%20cases.) development approach to building modules, which leads to predictable and stable APIs. Performance [​](#performance) ------------------------------ Performance is critical for applications on all sizes. Slow page load and interactions can cause users to stop using applications. Wagmi uses and is built by the same team behind [Viem](https://viem.sh) , the most performant production-ready Ethereum library. End users should not be required to download a module of over 100kB in order to interact with Ethereum. Wagmi is optimized for tree-shaking and dead-code elimination, allowing apps to minimize bundle size for fast page load times. Data layer performance is also critical. Slow, unnecessary, and manual data fetching can make apps unusable and cost thousands in RPC compute units. Wagmi supports caching, deduplication, persistence, and much more through [TanStack Query](/react/guides/tanstack-query) . Feature Coverage [​](#feature-coverage) ---------------------------------------- Wagmi supports the most popular and commonly-used Ethereum features out of the box with 40+ React Hooks for accounts, wallets, contracts, transactions, signing, ENS, and more. Wagmi also supports just about any wallet out there through it's official [connectors](/react/api/connectors) , [EIP-6963 support](/react/api/createConfig#multiinjectedproviderdiscovery) , and [extensible API](/dev/creating-connectors) . If you need lower-level control, you can always drop down to [Wagmi Core](/core/getting-started) or [Viem](https://viem.sh) , which Wagmi uses internally to perform blockchain operations. Wagmi also manages multi-chain support automatically so developers can focus on their applications instead of adding custom code. Finally, Wagmi has a [CLI](/cli/getting-started) to manage ABIs as well as a robust ecosystem of third-party libraries, like [ConnectKit](https://docs.family.co/connectkit) , [RainbowKit](https://www.rainbowkit.com) , [AppKit](https://walletconnect.com/appkit) , [Dynamic](https://www.dynamic.xyz) , [Privy](https://privy.io) , and many more, so you can get started quickly without needing to build everything from scratch. Stability [​](#stability) -------------------------- Stability is a fundamental principle for Wagmi. Many organizations, large and small, rely heavily on Wagmi and expect it to be entirely stable for their users and applications. Wagmi's test suite runs against forked Ethereum nodes to make sure functions work across chains. The test suite also runs type tests against many different versions of peer dependencies, like TypeScript, to ensure compatibility with the latest releases of other popular software. Wagmi follows semver so developers can upgrade between versions with confidence. Starting with Wagmi v2, new functionality will be opt-in with old functionality being deprecated alongside the new features. This means upgrading to the latest major versions will not require immediate changes. Lastly, the core team works full-time on Wagmi and [related projects](https://github.com/wevm) , and is constantly improving Wagmi and keeping it up-to-date with industry trends and changes. --- # Installation | Wagmi Return to top Installation [​](#installation) ================================ Install Wagmi via your package manager, a ` Check out the React docs for info on how to use [React without JSX](https://react.dev/reference/react/createElement#creating-an-element-without-jsx) . Requirements [​](#requirements) -------------------------------- Wagmi is optimized for modern browsers. It is compatible with the latest versions of the following browsers. ![chrome](/browsers/chrome.png)![edge](/browsers/edge.png)![firefox](/browsers/firefox.png)![opera](/browsers/opera.png)![safari](/browsers/safari.png) TIP Depending on your environment, you might need to add polyfills. See [Viem Platform Compatibility](https://viem.sh/docs/compatibility.html) for more info. Using Unreleased Commits [​](#using-unreleased-commits) -------------------------------------------------------- If you can't wait for a new release to test the latest features, you can either install from the `canary` tag (tracks the [`main`](https://github.com/wevm/wagmi/tree/main) branch). pnpmnpmyarnbun bash pnpm add wagmi@canary bash npm install wagmi@canary bash yarn add wagmi@canary bash bun add wagmi@canary Or clone the [Wagmi repo](https://github.com/wevm/wagmi) to your local machine, build, and link it yourself. bash gh repo clone wevm/wagmi cd wagmi pnpm install pnpm build cd packages/react pnpm link --global Then go to the project where you are using Wagmi and run `pnpm link --global wagmi` (or the package manager that you used to link Wagmi globally). Make sure you installed any [required peer dependencies](#package-manager) and their versions are correct. Security [​](#security) ------------------------ Ethereum-related projects are often targeted in attacks to steal users' assets. Make sure you follow security best-practices for your project. Some quick things to get started. * Pin package versions, upgrade mindfully, and inspect lockfile changes to minimize the risk of [supply-chain attacks](https://nodejs.org/en/guides/security/#supply-chain-attacks) . * Install the [Socket Security](https://socket.dev) [GitHub App](https://github.com/apps/socket-security) to help detect and block supply-chain attacks. * Add a [Content Security Policy](https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html) to defend against external scripts running in your app. --- # TypeScript | Wagmi Return to top TypeScript [​](#typescript) ============================ Requirements [​](#requirements) -------------------------------- Wagmi is designed to be as type-safe as possible! Things to keep in mind: * Types currently require using TypeScript >=5.0.4. * [TypeScript doesn't follow semver](https://www.learningtypescript.com/articles/why-typescript-doesnt-follow-strict-semantic-versioning) and often introduces breaking changes in minor releases. * Changes to types in this repository are considered non-breaking and are usually released as patch changes (otherwise every type enhancement would be a major version!). * It is highly recommended that you lock your `wagmi` and `typescript` versions to specific patch releases and upgrade with the expectation that types may be fixed or upgraded between any release. * The non-type-related public API of Wagmi still follows semver very strictly. To ensure everything works correctly, make sure your `tsconfig.json` has [`strict`](https://www.typescriptlang.org/tsconfig#strict) mode set to `true`. tsconfig.json json { "compilerOptions": { "strict": true } } Config Types [​](#config-types) -------------------------------- By default React Context does not work well with type inference. To support strong type-safety across the React Context boundary, there are two options available: * Declaration merging to "register" your `config` globally with TypeScript. * `config` property to pass your `config` directly to hooks. ### Declaration Merging [​](#declaration-merging) [Declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) allows you to "register" your `config` globally with TypeScript. The `Register` type enables Wagmi to infer types in places that wouldn't normally have access to type info via React Context alone. To set this up, add the following declaration to your project. Below, we co-locate the declaration merging and the `config` set up. ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' declare module 'wagmi' { interface Register { config: typeof config } } export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Since the `Register` type is global, you only need to add it once in your project. Once set up, you will get strong type-safety across your entire project. For example, query hooks will type `chainId` based on your `config`'s `chains`. ts import { } from 'wagmi' ({ chainId: 123 })Type '123' is not assignable to type '1 | 11155111 | undefined'. You just saved yourself a runtime error and you didn't even need to pass your `config`. 🎉 ### Hook `config` Property [​](#hook-config-property) For cases where you have more than one Wagmi `config` or don't want to use the declaration merging approach, you can pass a specific `config` directly to hooks via the `config` property. ts import { createConfig, http } from 'wagmi' import { mainnet, optimism } from 'wagmi/chains' export const configA = createConfig({ chains: [mainnet], transports: { [mainnet.id]: http(), }, }) export const configB = createConfig({ chains: [optimism], transports: { [optimism.id]: http(), }, }) As you expect, `chainId` is inferred correctly for each `config`. ts import { } from 'wagmi' ({ chainId: 123, : })Type '123' is not assignable to type '1'.({ chainId: 123, : })Type '123' is not assignable to type '10'. This approach is more explicit, but works well for advanced use-cases, if you don't want to use React Context or declaration merging, etc. Const-Assert ABIs & Typed Data [​](#const-assert-abis-typed-data) ------------------------------------------------------------------ Wagmi can infer types based on [ABIs](https://docs.soliditylang.org/en/latest/abi-spec.html#json) and [EIP-712](https://eips.ethereum.org/EIPS/eip-712) Typed Data definitions, powered by [Viem](https://viem.sh) and [ABIType](https://github.com/wevm/abitype) . This achieves full end-to-end type-safety from your contracts to your frontend and enlightened developer experience by autocompleting ABI item names, catching misspellings, inferring argument and return types (including overloads), and more. For this to work, you must either [const-assert](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) ABIs and Typed Data (more info below) or define them inline. For example, `useReadContract`'s `abi` configuration parameter: ts const { data } = useReadContract({ abi: […], // <--- defined inline }) ts const abi = […] as const // <--- const assertion const { data } = useReadContract({ abi }) If type inference isn't working, it's likely you forgot to add a `const` assertion or define the configuration parameter inline. Also, make sure your ABIs, Typed Data definitions, and [TypeScript configuration](#requirements) are valid and set up correctly. TIP Unfortunately [TypeScript doesn't support importing JSON `as const` yet](https://github.com/microsoft/TypeScript/issues/32063) . Check out the [Wagmi CLI](/cli/getting-started) to help with this! It can automatically fetch ABIs from Etherscan and other block explorers, resolve ABIs from your Foundry/Hardhat projects, generate React Hooks, and more. Anywhere you see the `abi` or `types` configuration property, you can likely use const-asserted or inline ABIs and Typed Data to get type-safety and inference. These properties are also called out in the docs. Here's what [`useReadContract`](/react/api/hooks/useReadContract) looks like with and without a const-asserted `abi` property. Const-AssertedNot Const-Asserted ts import { } from 'wagmi' const { } = ({ : '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', : , : 'balanceOf', : ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], }) ts import { } from 'wagmi' const { } = ({ : '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', : , : 'balanceOf', : ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], }) You can prevent runtime errors and be more productive by making sure your ABIs and Typed Data definitions are set up appropriately. 🎉 ts import { } from 'wagmi' ({ : , functionName: 'balanecOf',Type '"balanecOf"' is not assignable to type '"balanceOf" | "isApprovedForAll" | "getApproved" | "ownerOf" | "tokenURI" | undefined'. Did you mean '"balanceOf"'?}) Configure Internal Types [​](#configure-internal-types) -------------------------------------------------------- For advanced use-cases, you may want to configure Wagmi's internal types. Most of Wagmi's types relating to ABIs and EIP-712 Typed Data are powered by [ABIType](https://github.com/wevm/abitype) . See the [ABIType docs](https://abitype.dev) for more info on how to configure types. --- # Hooks | Wagmi Return to top Hooks [​](#hooks) ================== React Hooks for accounts, wallets, contracts, transactions, signing, ENS, and more. Import [​](#import) -------------------- ts import { useAccount } from 'wagmi' Available Hooks [​](#available-hooks) -------------------------------------- * [useAccount](/react/api/hooks/useAccount) * [useAccountEffect](/react/api/hooks/useAccountEffect) * [useBalance](/react/api/hooks/useBalance) * [useBlock](/react/api/hooks/useBlock) * [useBlockNumber](/react/api/hooks/useBlockNumber) * [useBlockTransactionCount](/react/api/hooks/useBlockTransactionCount) * [useBytecode](/react/api/hooks/useBytecode) * [useCall](/react/api/hooks/useCall) * [useChainId](/react/api/hooks/useChainId) * [useChains](/react/api/hooks/useChains) * [useClient](/react/api/hooks/useClient) * [useConfig](/react/api/hooks/useConfig) * [useConnect](/react/api/hooks/useConnect) * [useConnections](/react/api/hooks/useConnections) * [useConnectorClient](/react/api/hooks/useConnectorClient) * [useConnectors](/react/api/hooks/useConnectors) * [useDeployContract](/react/api/hooks/useDeployContract) * [useDisconnect](/react/api/hooks/useDisconnect) * [useEnsAddress](/react/api/hooks/useEnsAddress) * [useEnsAvatar](/react/api/hooks/useEnsAvatar) * [useEnsName](/react/api/hooks/useEnsName) * [useEnsResolver](/react/api/hooks/useEnsResolver) * [useEnsText](/react/api/hooks/useEnsText) * [useEstimateFeesPerGas](/react/api/hooks/useEstimateFeesPerGas) * [useEstimateGas](/react/api/hooks/useEstimateGas) * [useEstimateMaxPriorityFeePerGas](/react/api/hooks/useEstimateMaxPriorityFeePerGas) * [useFeeHistory](/react/api/hooks/useFeeHistory) * [useGasPrice](/react/api/hooks/useGasPrice) * [useInfiniteReadContracts](/react/api/hooks/useInfiniteReadContracts) * [usePrepareTransactionRequest](/react/api/hooks/usePrepareTransactionRequest) * [useProof](/react/api/hooks/useProof) * [usePublicClient](/react/api/hooks/usePublicClient) * [useReadContract](/react/api/hooks/useReadContract) * [useReadContracts](/react/api/hooks/useReadContracts) * [useReconnect](/react/api/hooks/useReconnect) * [useSendTransaction](/react/api/hooks/useSendTransaction) * [useSignMessage](/react/api/hooks/useSignMessage) * [useSignTypedData](/react/api/hooks/useSignTypedData) * [useSimulateContract](/react/api/hooks/useSimulateContract) * [useStorageAt](/react/api/hooks/useStorageAt) * [useSwitchAccount](/react/api/hooks/useSwitchAccount) * [useSwitchChain](/react/api/hooks/useSwitchChain) * [useToken](/react/api/hooks/useToken) * [useTransaction](/react/api/hooks/useTransaction) * [useTransactionConfirmations](/react/api/hooks/useTransactionConfirmations) * [useTransactionCount](/react/api/hooks/useTransactionCount) * [useTransactionReceipt](/react/api/hooks/useTransactionReceipt) * [useVerifyMessage](/react/api/hooks/useVerifyMessage) * [useVerifyTypedData](/react/api/hooks/useVerifyTypedData) * [useWaitForTransactionReceipt](/react/api/hooks/useWaitForTransactionReceipt) * [useWalletClient](/react/api/hooks/useWalletClient) * [useWatchAsset](/react/api/hooks/useWatchAsset) * [useWatchBlockNumber](/react/api/hooks/useWatchBlockNumber) * [useWatchBlocks](/react/api/hooks/useWatchBlocks) * [useWatchContractEvent](/react/api/hooks/useWatchContractEvent) * [useWatchPendingTransactions](/react/api/hooks/useWatchPendingTransactions) * [useWriteContract](/react/api/hooks/useWriteContract) --- # Comparison | Wagmi Return to top Comparison [​](#comparison) ============================ There are multiple options when it comes to React libraries for Ethereum that help manage wallet connections, provide utility methods/hooks, etc. TIP Comparisons strive to be as accurate and as unbiased as possible. If you use any of these libraries and feel the information could be improved, feel free to suggest changes. Overview [​](#overview) ------------------------ | | [wagmi](https://github.com/wagmi-dev/wagmi) | [web3-react](https://github.com/NoahZinsmeister/web3-react) | [useDApp](https://github.com/EthWorks/useDApp) | | --- | --- | --- | --- | | GitHub Stars | ![wagmi star count](https://img.shields.io/github/stars/wagmi-dev/wagmi?colorB=27292E&label=) | ![web3-react star count](https://img.shields.io/github/stars/Uniswap/web3-react?colorB=27292E&label=) | ![useDApp star count](https://img.shields.io/github/stars/EthWorks/useDApp?colorB=27292E&label=) | | Open Issues | ![wagmi issue count](https://img.shields.io/github/issues/wagmi-dev/wagmi?colorB=27292E&label=) | ![web3-react issue count](https://img.shields.io/github/issues/Uniswap/web3-react?colorB=27292E&label=) | ![useDApp issue count](https://img.shields.io/github/issues/EthWorks/useDApp?colorB=27292E&label=) | | Downloads | ![wagmi downloads](https://img.shields.io/npm/dw/wagmi?colorB=27292E&label=) | ![web3-react downloads](https://img.shields.io/npm/dw/@web3-react/core?colorB=27292E&label=) | ![useDApp downloads](https://img.shields.io/npm/dw/@usedapp/core?colorB=27292E&label=) | | License | ![wagmi license](https://img.shields.io/github/license/wagmi-dev/wagmi?colorB=27292E&label=) | ![web3-react license](https://img.shields.io/github/license/Uniswap/web3-react?colorB=27292E&label=) | ![useDApp license](https://img.shields.io/github/license/EthWorks/useDApp?colorB=27292E&label=) | | Their Comparison | – | none | none | | Supported Frameworks | React, Vanilla JS | React | React | | Documentation | ✅ | 🛑 | ✅ | | TypeScript | ✅ | 🔶 | 🔶 | | EIP-6963 Support | ✅ | 🔴 | 🔴 | | Test Suite | ✅ | 🔶 | 🔶 | | Examples | ✅ | 🔶 | ✅ | Comparison Key 1. Documentation * Comprehensive documentation for all library features ✅ * No documentation 🔴 2. Typescript * Infer types from ABIs, EIP-712 Typed Data, etc. ✅ * Can add types with explicit generics, type annotations, etc. 🔶 3. Test Suite * Runs against forked Ethereum network(s) ✅ * Mocking functionality (i.e. RPC calls) is 🔶 4. EIP-6963 Support * Fully compatible with EIP-6963 ✅ * Not compatible with EIP-6963 🔴 5. Examples * Has multiple examples ✅ * Has single example 🔶 [Wagmi](https://github.com/wagmi-dev/wagmi) [​](#wagmi) --------------------------------------------------------- ### Pros [​](#pros) * 20+ hooks for working with wallets, ENS, contracts, transactions, signing, etc. * Built-in wallet connectors for injected providers (EIP-6963 support), WalletConnect, MetaMask, Coinbase Wallet * Caching, request deduplication, and persistence powered by TanStack Query * Auto-refresh data on wallet, block, and network changes * Multicall support * Test suite running against forked Ethereum networks * TypeScript ready (infer types from ABIs and EIP-712 Typed Data) * Extensive documentation and examples * Used by Coinbase, Stripe, Shopify, Uniswap, Optimism, ENS, Sushi, and [many more](https://github.com/wagmi-dev/wagmi/discussions/201) * MIT License ### Cons [​](#cons) * Not as many built-in connectors as `web3-react` [web3-react](https://github.com/Uniswap/web3-react) [​](#web3-react) ---------------------------------------------------------------------- ### Pros [​](#pros-1) * Supports many different connectors (conceptually similar to Wagmi's connectors) * Basic hooks for managing account ### Cons [​](#cons-1) * Need to set up connectors and method for connecting wallet on your own * Need to install connectors separately * Almost no tests or documentation; infrequent updates * GPL-3.0 License [useDApp](https://github.com/EthWorks/useDApp) [​](#usedapp) -------------------------------------------------------------- ### Pros [​](#pros-2) * Auto-refresh on new blocks and wallet changes * Multicall support * Transaction notifications * Chrome extension and Firefox add-on * MIT License ### Cons [​](#cons-2) * Non-standard hook API --- # Connectors | Wagmi Return to top Connectors [​](#connectors) ============================ Connectors for popular wallet providers and protocols. Import [​](#import) -------------------- Import via the `'wagmi/connectors'` entrypoint. ts import { injected } from 'wagmi/connectors' Available Connectors [​](#available-connectors) ------------------------------------------------ * [coinbaseWallet](/react/api/connectors/coinbaseWallet) * [injected](/react/api/connectors/injected) * [metaMask](/react/api/connectors/metaMask) * [mock](/react/api/connectors/mock) * [safe](/react/api/connectors/safe) * [walletConnect](/react/api/connectors/walletConnect) --- # TanStack Query | Wagmi Return to top TanStack Query [​](#tanstack-query) ==================================== Wagmi Hooks are not only a wrapper around the core [Wagmi Actions](/core/api/actions) , but they also utilize [TanStack Query](https://tanstack.com/query/v5) to enable trivial and intuitive fetching, caching, synchronizing, and updating of asynchronous data in your React applications. Without an asynchronous data fetching abstraction, you would need to handle all the negative side-effects that comes as a result, such as: representing finite states (loading, error, success), handling race conditions, caching against a deterministic identifier, etc. Queries & Mutations [​](#queries-mutations) -------------------------------------------- Wagmi Hooks represent either a **Query** or a **Mutation**. **Queries** are used for fetching data (e.g. fetching a block number, reading from a contract, etc), and are typically invoked on mount by default. All queries are coupled to a unique [Query Key](#query-keys) , and can be used for further operations such as refetching, prefetching, or modifying the cached data. **Mutations** are used for mutating data (e.g. connecting/disconnecting accounts, writing to a contract, switching chains, etc), and are typically invoked in response to a user interaction. Unlike **Queries**, they are not coupled with a query key. Terms [​](#terms) ------------------ * **Query**: An asynchronous data fetching (e.g. read data) operation that is tied against a unique Query Key. * **Mutation**: An asynchronous mutating (e.g. create/update/delete data or side-effect) operation. * **Query Key**: A unique identifier that is used to deterministically identify a query. It is typically a tuple of the query name and the query arguments. * **Stale Data**: Data that is unused or inactive after a certain period of time. * **Query Fetching**: The process of invoking an async query function. * **Query Refetching**: The process of refetching **rendered** queries. * **[Query Invalidation](https://tanstack.com/query/v5/docs/react/guides/query-invalidation) **: The process of marking query data as stale (e.g. inactive/unused), and refetching **rendered** queries. * **[Query Prefetching](https://tanstack.com/query/v5/docs/react/guides/prefetching) **: The process of prefetching queries and seeding the cache. Persistence via External Stores [​](#persistence-via-external-stores) ---------------------------------------------------------------------- By default, TanStack Query persists all query data in-memory. This means that if you refresh the page, all in-memory query data will be lost. If you want to persist query data to an external storage, you can utilize TanStack Query's [`createSyncStoragePersister`](https://tanstack.com/query/v5/docs/react/plugins/createSyncStoragePersister) or [`createAsyncStoragePersister`](https://tanstack.com/query/v5/docs/react/plugins/createAsyncStoragePersister) to plug external storage like `localStorage`, `sessionStorage`, [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) or [`AsyncStorage`](https://reactnative.dev/docs/asyncstorage) (React Native). ### Sync Storage [​](#sync-storage) Below is an example of how to set up Wagmi + TanStack Query with sync external storage like `localStorage` or `sessionStorage`. #### Install [​](#install) pnpmnpmyarnbun bash pnpm i @tanstack/query-sync-storage-persister @tanstack/react-query-persist-client bash npm i @tanstack/query-sync-storage-persister @tanstack/react-query-persist-client bash yarn add @tanstack/query-sync-storage-persister @tanstack/react-query-persist-client bash bun i @tanstack/query-sync-storage-persister @tanstack/react-query-persist-client #### Usage [​](#usage) tsx // 1. Import modules. import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister' import { QueryClient } from '@tanstack/react-query' import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client' import { WagmiProvider, deserialize, serialize } from 'wagmi' // 2. Create a new Query Client with a default `gcTime`. const queryClient = new QueryClient({ defaultOptions: { queries: { gcTime: 1_000 * 60 * 60 * 24, // 24 hours }, }, }) // 3. Set up the persister. const persister = createSyncStoragePersister({ serialize, storage: window.localStorage, deserialize, }) function App() { return ( {/* 4. Wrap app in PersistQueryClientProvider */} {/* ... */} ) } Read more about [Sync Storage Persistence](https://tanstack.com/query/v5/docs/react/plugins/createSyncStoragePersister) . ### Async Storage [​](#async-storage) Below is an example of how to set up Wagmi + TanStack Query with async external storage like [`IndexedDB`](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) or [`AsyncStorage`](https://reactnative.dev/docs/asyncstorage) . #### Install [​](#install-1) pnpmnpmyarnbun bash pnpm i @tanstack/query-async-storage-persister @tanstack/react-query-persist-client bash npm i @tanstack/query-async-storage-persister @tanstack/react-query-persist-client bash yarn add @tanstack/query-async-storage-persister @tanstack/react-query-persist-client bash bun i @tanstack/query-async-storage-persister @tanstack/react-query-persist-client #### Usage [​](#usage-1) tsx // 1. Import modules. import AsyncStorage from '@react-native-async-storage/async-storage' import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister' import { QueryClient } from '@tanstack/react-query' import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client' import { WagmiProvider, deserialize, serialize } from 'wagmi' // 2. Create a new Query Client with a default `gcTime`. const queryClient = new QueryClient({ defaultOptions: { queries: { gcTime: 1_000 * 60 * 60 * 24, // 24 hours }, }, }) // 3. Set up the persister. const persister = createAsyncStoragePersister({ serialize, storage: AsyncStorage, deserialize, }) function App() { return ( {/* 4. Wrap app in PersistQueryClientProvider */} {/* ... */} ) } Read more about [Async Storage Persistence](https://tanstack.com/query/v5/docs/react/plugins/createAsyncStoragePersister) . Query Keys [​](#query-keys) ---------------------------- Query Keys are typically used to perform advanced operations on the query such as: invalidation, refetching, prefetching, etc. Wagmi exports Query Keys for every Hook, and they can be retrieved via the [Hook (React)](#hook-react) or via an [Import (Vanilla JS)](#import-vanilla-js) . Read more about **Query Keys** on the [TanStack Query docs.](https://tanstack.com/query/v5/docs/react/guides/query-keys) ### Hook (React) [​](#hook-react) Each Hook returns a `queryKey` value. You would use this approach when you want to utilize the query key in a React component as it handles reactivity for you, unlike the [Import](#import-vanilla-js) method below. ts import { useBlock } from 'wagmi' function App() { const { queryKey } = useBlock() } ### Import (Vanilla JS) [​](#import-vanilla-js) Each Hook has a corresponding `getQueryOptions` function that returns a query key. You would use this method when you want to utilize the query key outside of a React component in a Vanilla JS context, like in a utility function. ts import { getBlockQueryOptions } from 'wagmi/query' import { config } from './config' function perform() { const { queryKey } = getBlockQueryOptions(config, { chainId: config.state.chainId }) } WARNING The caveat of this method is that it does not handle reactivity for you (e.g. active account/chain changes, argument changes, etc). You would need to handle this yourself by explicitly passing through the arguments to `getQueryOptions`. Invalidating Queries [​](#invalidating-queries) ------------------------------------------------ Invalidating a query is the process of marking the query data as stale (e.g. inactive/unused), and refetching the queries that are already rendered. Read more about **Invalidating Queries** on the [TanStack Query docs.](https://tanstack.com/query/v5/docs/react/guides/query-invalidation) #### Example: Watching a Users' Balance [​](#example-watching-a-users-balance) You may want to "watch" a users' balance, and invalidate the balance after each incoming block. We can invoke `invalidateQueries` inside a `useEffect` with the block number as it's only dependency – this will refetch all rendered balance queries when the `blockNumber` changes. tsx import { useQueryClient } from '@tanstack/react-query' import { useEffect } from 'react' import { useBlockNumber, useBalance } from 'wagmi' function App() { const queryClient = useQueryClient() const { data: blockNumber } = useBlockNumber({ watch: true }) const { data: balance, queryKey } = useBalance() useEffect(() => { queryClient.invalidateQueries({ queryKey }) }, [blockNumber]) return
{balance}
} #### Example: After User Interaction [​](#example-after-user-interaction) Maybe you want to invalidate a users' balance after some interaction. This would mark the balance as stale, and consequently refetch all rendered balance queries. tsx import { useBalance } from 'wagmi' function App() { // 1. Extract `queryKey` from the useBalance Hook. const { queryKey } = useBalance() return ( ) } function Example() { // 3. Other `useBalance` Hooks in your rendered React tree will be refetched! const { data: balance } = useBalance() return
{balance}
} Fetching Queries [​](#fetching-queries) ---------------------------------------- Fetching a query is the process of invoking the query function to retrieve data. If the query exists and the data is not invalidated or older than a given `staleTime`, then the data from the cache will be returned. Otherwise, the query will fetch for the latest data. example.tsxapp.tsxconfig.ts tsx import { getBlockQueryOptions } from 'wagmi' import { queryClient } from './app' import { config } from './config' export async function fetchBlockData() { return queryClient.fetchQuery( getBlockQueryOptions(config, { chainId: config.state.chainId, } )) } tsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import * as React from 'react' import { WagmiProvider } from 'wagmi' import { config } from './config' export const queryClient = new QueryClient() export function App() { return ( {/** ... */} ) } ts import { http, createConfig } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Retrieving & Updating Query Data [​](#retrieving-updating-query-data) ---------------------------------------------------------------------- You can retrieve and update query data imperatively with `getQueryData` and `setQueryData`. This is useful for scenarios where you want to retrieve or update a query outside of a React component. Note that these functions do not invalidate or refetch queries. example.tsxapp.tsxconfig.ts tsx import { getBlockQueryOptions } from 'wagmi' import type { Block } from 'viem' import { queryClient } from './app' import { config } from './config' export function getPendingBlockData() { return queryClient.getQueryData( getBlockQueryOptions(config, { chainId: config.state.chainId, tag: 'pending' } )) } export function setPendingBlockData(data: Block) { return queryClient.setQueryData( getBlockQueryOptions(config, { chainId: config.state.chainId, tag: 'pending' }, data )) } tsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import * as React from 'react' import { WagmiProvider } from 'wagmi' import { config } from './config' export const queryClient = new QueryClient() export function App() { return ( {/** ... */} ) } ts import { http, createConfig } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Prefetching Queries [​](#prefetching-queries) ---------------------------------------------- Prefetching a query is the process of fetching the data ahead of time and seeding the cache with the returned data. This is useful for scenarios where you want to fetch data before the user navigates to a page, or fetching data on the server to be reused on client hydration. Read more about **Prefetching Queries** on the [TanStack Query docs.](https://tanstack.com/query/v5/docs/react/guides/prefetching) #### Example: Prefetching in Event Handler [​](#example-prefetching-in-event-handler) tsx import { Link } from 'next/link' import { getBlockQueryOptions } from 'wagmi' function App() { const config = useConfig() const chainId = useChainId() // 1. Set up a function to prefetch the block data. const prefetch = () => queryClient.prefetchQuery(getBlockQueryOptions(config, { chainId })) return ( Block details ) } SSR [​](#ssr) -------------- It is possible to utilize TanStack Query's SSR strategies with Wagmi Hooks & Query Keys. Check out the [Server Rendering & Hydration](https://tanstack.com/query/v5/docs/react/guides/ssr) & [Advanced Server Rendering](https://tanstack.com/query/v5/docs/react/guides/advanced-ssr) guides. Devtools [​](#devtools) ------------------------ TanStack Query includes dedicated [Devtools](https://tanstack.com/query/latest/docs/framework/react/devtools) that assist in visualizing and debugging your queries, their cache states, and much more. You will have to pass a custom `queryKeyFn` to your `QueryClient` for Devtools to correctly serialize BigInt values for display. Alternatively, You can use the `hashFn` from `@wagmi/core/query`, which already handles this serialization. #### Install [​](#install-2) pnpmnpmyarnbun bash pnpm i @tanstack/react-query-devtools bash npm i @tanstack/react-query-devtools bash yarn add @tanstack/react-query-devtools bash bun i @tanstack/react-query-devtools #### Usage [​](#usage-2) tsx import { QueryClient, QueryClientProvider, } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import { hashFn } from "@wagmi/core/query"; const queryClient = new QueryClient({ defaultOptions: { queries: { queryKeyHashFn: hashFn, }, }, }); --- # Viem | Wagmi Return to top Viem [​](#viem) ================ [Viem](https://viem.sh) is a low-level TypeScript Interface for Ethereum that enables developers to interact with the Ethereum blockchain, including: JSON-RPC API abstractions, Smart Contract interaction, wallet & signing implementations, coding/parsing utilities and more. **Wagmi Core** is essentially a wrapper over **Viem** that provides multi-chain functionality via [Wagmi Config](/react/api/createConfig) and automatic account management via [Connectors](/react/api/connectors) . Leveraging Viem Actions [​](#leveraging-viem-actions) ------------------------------------------------------ All of the core [Wagmi Hooks](/react/api/actions) are friendly wrappers around [Viem Actions](https://viem.sh/docs/actions/public/introduction.html) that inject a multi-chain and connector aware [Wagmi Config](/react/api/createConfig) . There may be cases where you might want to dig deeper and utilize Viem Actions directly (maybe a Hook doesn't exist in Wagmi yet). In these cases, you can create your own custom Wagmi Hook by importing Viem Actions directly via `viem/actions` and plugging in a Viem Client returned by the [`useClient` Hook](/react/api/hooks/useClient) . The example below demonstrates two different ways to utilize Viem Actions: 1. **Tree-shakable Actions (recommended):** Uses `useClient` (for public actions) and `useConnectorClient` (for wallet actions). 2. **Client Actions:** Uses `usePublicClient` (for public actions) and `useWalletClient` (for wallet actions). TIP It is highly recommended to use the **tree-shakable** method to ensure that you are only pulling modules you use, and keep your bundle size low. Tree-shakable ActionsClient Actions tsx // 1. Import modules. import { useMutation, useQuery } from '@tanstack/react-query' import { http, createConfig, useClient, useConnectorClient } from 'wagmi' import { base, mainnet, optimism, zora } from 'wagmi/chains' import { getLogs, watchAsset } from 'viem/actions' // 2. Set up a Wagmi Config export const config = createConfig({ chains: [base, mainnet, optimism, zora], transports: { [base.id]: http(), [mainnet.id]: http(), [optimism.id]: http(), [zora.id]: http(), }, }) function Example() { // 3. Extract a Viem Client for the current active chain. const publicClient = useClient({ config }) // 4. Create a "custom" Query Hook that utilizes the Client. const { data: logs } = useQuery({ queryKey: ['logs', publicClient.uid], queryFn: () => getLogs(publicClient, /* ... */) }) // 5. Extract a Viem Client for the current active chain & account. const { data: walletClient } = useConnectorClient({ config }) // 6. Create a "custom" Mutation Hook that utilizes the Client. const { mutate } = useMutation({ mutationFn: (asset) => watchAsset(walletClient, asset) }) return (
{/* ... */}
) } tsx // 1. Import modules. import { useMutation, useQuery } from '@tanstack/react-query' import { http, createConfig, useClient, useConnectorClient } from 'wagmi' import { base, mainnet, optimism, zora } from 'wagmi/chains' // 2. Set up a Wagmi Config export const config = createConfig({ chains: [base, mainnet, optimism, zora], transports: { [base.id]: http(), [mainnet.id]: http(), [optimism.id]: http(), [zora.id]: http(), }, }) function Example() { // 3. Extract a Viem Client for the current active chain. const publicClient = useClient({ config }) // 4. Create a "custom" Query Hook that utilizes the Client. const { data: logs } = useQuery({ queryKey: ['logs', publicClient.uid], queryFn: () => publicClient.getLogs(/* ... */) }) // 5. Extract a Viem Client for the current active chain & account. const { data: walletClient } = useConnectorClient({ config }) // 6. Create a "custom" Mutation Hook that utilizes the Client. const { mutate } = useMutation({ mutationFn: (asset) => walletClient.watchAsset(asset) }) return (
{/* ... */}
) } Private Key & Mnemonic Accounts [​](#private-key-mnemonic-accounts) -------------------------------------------------------------------- It is possible to utilize Viem's [Private Key & Mnemonic Accounts](https://viem.sh/docs/accounts/local.html) with Wagmi by explicitly passing through the account via the `account` argument on Wagmi Actions. tsx import { http, createConfig, useSendTransaction } from 'wagmi' import { base, mainnet, optimism, zora } from 'wagmi/chains' import { parseEther } from 'viem' import { privateKeyToAccount } from 'viem/accounts' export const config = createConfig({ chains: [base, mainnet, optimism, zora], transports: { [base.id]: http(), [mainnet.id]: http(), [optimism.id]: http(), [zora.id]: http(), }, }) const account = privateKeyToAccount('0x...') function Example() { const { data: hash } = useSendTransaction({ account, to: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC', value: parseEther('0.001') }) } INFO Wagmi currently does not support hoisting Private Key & Mnemonic Accounts to the top-level Wagmi Config – meaning you have to explicitly pass through the account to every Action. If you feel like this is a feature that should be added, please [open an discussion](https://github.com/wevm/wagmi/discussions/new?category=ideas) . --- # Error Handling | Wagmi Return to top Error Handling [​](#error-handling) ==================================== The `error` property in Wagmi Hooks is strongly typed with it's corresponding error type. This enables you to have granular precision with handling errors in your application. You can discriminate the error type by using the `name` property on the error object. index.tsxconfig.ts tsx import { } from 'wagmi' function () { const { , } = () ?. if (?. === 'HttpRequestError') { const { } = return <>A HTTP error occurred. Status: {} } if (?. === 'LimitExceededRpcError') { const { } = return <>Rate limit exceeded. Code: {} } // ... } ts import { http, createConfig } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) --- # Why Wagmi | Wagmi Return to top Why Wagmi [​](#why-wagmi) ========================== The Problems [​](#the-problems) -------------------------------- Building Ethereum applications is hard. Apps need to support connecting wallets, multiple chains, signing messages and data, sending transactions, listening for events and state changes, refreshing stale blockchain data, and much more. This is all on top of solving for app-specific use-cases and providing polished user experiences. The ecosystem is also continuously evolving, meaning you need to adapt to new improvements or get left behind. App developers should not need to worry about connecting tens of different wallets, the intricacies of multi-chain support, typos accidentally sending an order of magnitude more ETH or calling a misspelled contract function, or accidentally spamming their RPC provider, costing thousands in compute units. Wagmi solves all these problems and more — allowing app developers to focus on building high-quality and performant experiences for Ethereum — by focusing on **developer experience**, **performance**, **feature coverage**, and **stability.** Developer Experience [​](#developer-experience) ------------------------------------------------ Wagmi delivers a great developer experience through modular and composable APIs, automatic type safety and inference, and comprehensive documentation. It provides developers with intuitive building blocks to build their Ethereum apps. While Wagmi's APIs might seem more verbose at first, it makes Wagmi's modular building blocks extremely flexible. Easy to move around, change, and remove. It also allows developers to better understand Ethereum concepts as well as understand _what_ and _why_ certain properties are being passed through. Learning how to use Wagmi is a great way to learn how to interact with Ethereum in general. Wagmi also provides [strongly typed APIs](/vue/typescript) , allowing consumers to get the best possible experience through [autocomplete](https://twitter.com/awkweb/status/1555678944770367493) , [type inference](https://twitter.com/jakemoxey/status/1570244174502588417?s=20) , as well as static validation. You often just need to provide an ABI and Wagmi can help you autocomplete your way to success, identify type errors before your users do, drill into blockchain errors [at compile and runtimes](/vue/guides/error-handling) with surgical precision, and much more. The API documentation is comprehensive and contains usage info for _every_ module in Wagmi. The core team uses a [documentation](https://gist.github.com/zsup/9434452) and [test driven](https://en.wikipedia.org/wiki/Test-driven_development#:~:text=Test%2Ddriven%20development%20(TDD),software%20against%20all%20test%20cases.) development approach to building modules, which leads to predictable and stable APIs. Performance [​](#performance) ------------------------------ Performance is critical for applications on all sizes. Slow page load and interactions can cause users to stop using applications. Wagmi uses and is built by the same team behind [Viem](https://viem.sh) , the most performant production-ready Ethereum library. End users should not be required to download a module of over 100kB in order to interact with Ethereum. Wagmi is optimized for tree-shaking and dead-code elimination, allowing apps to minimize bundle size for fast page load times. Data layer performance is also critical. Slow, unnecessary, and manual data fetching can make apps unusable and cost thousands in RPC compute units. Wagmi supports caching, deduplication, persistence, and much more through [TanStack Query](/vue/guides/tanstack-query) . Feature Coverage [​](#feature-coverage) ---------------------------------------- Wagmi supports the most popular and commonly-used Ethereum features out of the box with 40+ Vue Composables for accounts, wallets, contracts, transactions, signing, ENS, and more. Wagmi also supports just about any wallet out there through it's official [connectors](/vue/api/connectors) , [EIP-6963 support](/vue/api/createConfig#multiinjectedproviderdiscovery) , and [extensible API](/dev/creating-connectors) . If you need lower-level control, you can always drop down to [Wagmi Core](/core/getting-started) or [Viem](https://viem.sh) , which Wagmi uses internally to perform blockchain operations. Wagmi also manages multi-chain support automatically so developers can focus on their applications instead of adding custom code. Finally, Wagmi has a [CLI](/cli/getting-started) to manage ABIs as well as a robust ecosystem of third-party libraries, like [ConnectKit](https://docs.family.co/connectkit) , [RainbowKit](https://www.rainbowkit.com) , [AppKit](https://walletconnect.com/appkit) , [Dynamic](https://www.dynamic.xyz) , [Privy](https://privy.io) , and many more, so you can get started quickly without needing to build everything from scratch. Stability [​](#stability) -------------------------- Stability is a fundamental principle for Wagmi. Many organizations, large and small, rely heavily on Wagmi and expect it to be entirely stable for their users and applications. Wagmi's test suite runs against forked Ethereum nodes to make sure functions work across chains. The test suite also runs type tests against many different versions of peer dependencies, like TypeScript, to ensure compatibility with the latest releases of other popular software. Wagmi follows semver so developers can upgrade between versions with confidence. Starting with Wagmi v2, new functionality will be opt-in with old functionality being deprecated alongside the new features. This means upgrading to the latest major versions will not require immediate changes. Lastly, the core team works full-time on Wagmi and [related projects](https://github.com/wevm) , and is constantly improving Wagmi and keeping it up-to-date with industry trends and changes. --- # Ethers.js Adapters | Wagmi Return to top Ethers.js Adapters [​](#ethers-js-adapters) ============================================ It is recommended for projects to migrate to [Viem](https://viem.sh) when using Wagmi, but there are some cases where you might still need to use [Ethers.js](https://ethers.org) in your project: * You may want to **incrementally migrate** Ethers.js usage to Viem * Some **third-party libraries & SDKs** may only support Ethers.js * Personal preference We have provided reference implementations for Viem → Ethers.js adapters that you can copy + paste in your project. Client → Provider [​](#client-→-provider) ------------------------------------------ ### Reference Implementation [​](#reference-implementation) Copy the following reference implementation into a file of your choice: Ethers v5Ethers v6 ts import { providers } from 'ethers' import { useMemo } from 'react' import type { Chain, Client, Transport } from 'viem' import { Config, useClient } from 'wagmi' export function clientToProvider(client: Client) { const { chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } if (transport.type === 'fallback') return new providers.FallbackProvider( (transport.transports as ReturnType[]).map( ({ value }) => new providers.JsonRpcProvider(value?.url, network), ), ) return new providers.JsonRpcProvider(transport.url, network) } /** Hook to convert a viem Client to an ethers.js Provider. */ export function useEthersProvider({ chainId, }: { chainId?: number | undefined } = {}) { const client = useClient({ chainId }) return useMemo(() => (client ? clientToProvider(client) : undefined), [client]) } ts import { FallbackProvider, JsonRpcProvider } from 'ethers' import { useMemo } from 'react' import type { Chain, Client, Transport } from 'viem' import { type Config, useClient } from 'wagmi' export function clientToProvider(client: Client) { const { chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } if (transport.type === 'fallback') { const providers = (transport.transports as ReturnType[]).map( ({ value }) => new JsonRpcProvider(value?.url, network), ) if (providers.length === 1) return providers[0] return new FallbackProvider(providers) } return new JsonRpcProvider(transport.url, network) } /** Action to convert a viem Client to an ethers.js Provider. */ export function useEthersProvider({ chainId }: { chainId?: number } = {}) { const client = useClient({ chainId }) return useMemo(() => (client ? clientToProvider(client) : undefined), [client]) } ### Usage [​](#usage) Now you can use the `useEthersProvider` function in your components: example.tsethers.ts (Ethers v5)ethers.ts (Ethers v6) ts import { useEthersProvider } from './ethers' function Example() { const provider = useEthersProvider() ... } ts import { providers } from 'ethers' import { useMemo } from 'react' import type { Chain, Client, Transport } from 'viem' import { Config, useClient } from 'wagmi' export function clientToProvider(client: Client) { const { chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } if (transport.type === 'fallback') return new providers.FallbackProvider( (transport.transports as ReturnType[]).map( ({ value }) => new providers.JsonRpcProvider(value?.url, network), ), ) return new providers.JsonRpcProvider(transport.url, network) } /** Hook to convert a viem Client to an ethers.js Provider. */ export function useEthersProvider({ chainId, }: { chainId?: number | undefined } = {}) { const client = useClient({ chainId }) return useMemo(() => (client ? clientToProvider(client) : undefined), [client]) } ts import { FallbackProvider, JsonRpcProvider } from 'ethers' import { useMemo } from 'react' import type { Chain, Client, Transport } from 'viem' import { type Config, useClient } from 'wagmi' export function clientToProvider(client: Client) { const { chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } if (transport.type === 'fallback') { const providers = (transport.transports as ReturnType[]).map( ({ value }) => new JsonRpcProvider(value?.url, network), ) if (providers.length === 1) return providers[0] return new FallbackProvider(providers) } return new JsonRpcProvider(transport.url, network) } /** Action to convert a viem Client to an ethers.js Provider. */ export function useEthersProvider({ chainId }: { chainId?: number } = {}) { const client = useClient({ chainId }) return useMemo(() => (client ? clientToProvider(client) : undefined), [client]) } Connector Client → Signer [​](#connector-client-→-signer) ---------------------------------------------------------- ### Reference Implementation [​](#reference-implementation-1) Copy the following reference implementation into a file of your choice: Ethers v5Ethers v6 ts import { providers } from 'ethers' import { useMemo } from 'react' import type { Account, Chain, Client, Transport } from 'viem' import { Config, useConnectorClient } from 'wagmi' export function clientToSigner(client: Client) { const { account, chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } const provider = new providers.Web3Provider(transport, network) const signer = provider.getSigner(account.address) return signer } /** Hook to convert a Viem Client to an ethers.js Signer. */ export function useEthersSigner({ chainId }: { chainId?: number } = {}) { const { data: client } = useConnectorClient({ chainId }) return useMemo(() => (client ? clientToSigner(client) : undefined), [client]) } ts import { BrowserProvider, JsonRpcSigner } from 'ethers' import { useMemo } from 'react' import type { Account, Chain, Client, Transport } from 'viem' import { type Config, useConnectorClient } from 'wagmi' export function clientToSigner(client: Client) { const { account, chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } const provider = new BrowserProvider(transport, network) const signer = new JsonRpcSigner(provider, account.address) return signer } /** Hook to convert a viem Wallet Client to an ethers.js Signer. */ export function useEthersSigner({ chainId }: { chainId?: number } = {}) { const { data: client } = useConnectorClient({ chainId }) return useMemo(() => (client ? clientToSigner(client) : undefined), [client]) } ### Usage [​](#usage-1) Now you can use the `useEthersSigner` function in your components: example.tsethers.ts (Ethers v5)ethers.ts (Ethers v6) ts import { useEthersSigner } from './ethers' function example() { const signer = useEthersSigner() ... } ts import { providers } from 'ethers' import { useMemo } from 'react' import type { Account, Chain, Client, Transport } from 'viem' import { Config, useConnectorClient } from 'wagmi' export function clientToSigner(client: Client) { const { account, chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } const provider = new providers.Web3Provider(transport, network) const signer = provider.getSigner(account.address) return signer } /** Action to convert a Viem Client to an ethers.js Signer. */ export function useEthersSigner({ chainId }: { chainId?: number } = {}) { const { data: client } = useConnectorClient({ chainId }) return useMemo(() => (client ? clientToSigner(client) : undefined), [client]) } ts import { BrowserProvider, JsonRpcSigner } from 'ethers' import { useMemo } from 'react' import type { Account, Chain, Client, Transport } from 'viem' import { type Config, useConnectorClient } from 'wagmi' export function clientToSigner(client: Client) { const { account, chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } const provider = new BrowserProvider(transport, network) const signer = new JsonRpcSigner(provider, account.address) return signer } /** Hook to convert a viem Wallet Client to an ethers.js Signer. */ export function useEthersSigner({ chainId }: { chainId?: number } = {}) { const { data: client } = useConnectorClient({ chainId }) return useMemo(() => (client ? clientToSigner(client) : undefined), [client]) } --- # Chain Properties | Wagmi Return to top Chain Properties [​](#chain-properties) ======================================== Some chains support additional properties related to blocks and transactions. This is powered by Viem's [formatters](https://viem.sh/docs/clients/chains.html#formatters) and [serializers](https://viem.sh/docs/clients/chains.html#serializers) . For example, Celo, ZkSync, OP Stack chains all support additional properties. In order to use these properties in a type-safe way, there are a few things you should be aware of. TIP Make sure you follow the TypeScript guide's [Config Types](/react/typescript#config-types) section before moving on. The easiest way to do this is to use [Declaration Merging](/react/typescript#declaration-merging) to "register" your `config` globally with TypeScript. ts import { http, createConfig } from 'wagmi' import { base, celo, mainnet } from 'wagmi/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) declare module 'wagmi' { interface Register { config: typeof config } } Narrowing Parameters [​](#narrowing-parameters) ------------------------------------------------ Once your Config is registered with TypeScript, you are ready to access chain-specific properties! For example, Celo's `feeCurrency` is available. index.tsxconfig.ts ts import { parseEther } from 'viem' import { useSimulateContract } from 'wagmi' const result = useSimulateContract({ to: '0xd2135CfB216b74109775236E36d4b433F1DF507B', value: parseEther('0.01'), feeCurrency: '0x…', }) ts import { http, createConfig } from 'wagmi' import { base, celo, mainnet } from 'wagmi/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) declare module 'wagmi' { interface Register { config: typeof config } } This is great, but if you have multiple chains that support additional properties, your autocomplete could be overwhelmed with all of them. By setting the `chainId` property to a specific value (e.g. `celo.id`), you can narrow parameters to a single chain. index.tsxconfig.ts ts import { parseEther } from 'viem' import { useSimulateContract } from 'wagmi' import { celo } from 'wagmi/chains' const result = useSimulateContract({ to: '0xd2135CfB216b74109775236E36d4b433F1DF507B', value: parseEther('0.01'), chainId: celo.id, feeCurrency: '0x…', // ^? (property) feeCurrency?: `0x${string}` | undefined }) ts import { http, createConfig } from 'wagmi' import { base, celo, mainnet } from 'wagmi/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) declare module 'wagmi' { interface Register { config: typeof config } } Narrowing Return Types [​](#narrowing-return-types) ---------------------------------------------------- Return types can also have chain-specific properties attached to them. There are a couple approaches for extracting these properties. ### `chainId` Parameter [​](#chainid-parameter) Not only can you use the `chainId` parameter to [narrow parameters](#narrowing-parameters) , you can also use it to narrow the return type. index.tsxconfig.ts ts import { useWaitForTransactionReceipt } from 'wagmi' import { zkSync } from 'wagmi/chains' const { data } = useWaitForTransactionReceipt({ chainId: zkSync.id, hash: '0x16854fcdd0219cacf5aec5e4eb2154dac9e406578a1510a6fc48bd0b67e69ea9', }) data?.logs // ^? (property) logs: ZkSyncLog[] | undefined ts import { http, createConfig } from 'wagmi' import { base, celo, mainnet } from 'wagmi/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) declare module 'wagmi' { interface Register { config: typeof config } } ### `chainId` Data Property [​](#chainid-data-property) Wagmi internally will set a `chainId` property on return types that you can use to narrow results. The `chainId` is determined from the `chainId` parameter or global state (e.g. connector). You can use this property to help TypeScript narrow the type. index.tsxconfig.ts ts import { useWaitForTransactionReceipt } from 'wagmi' import { zkSync } from 'wagmi/chains' const { data } = useWaitForTransactionReceipt({ hash: '0x16854fcdd0219cacf5aec5e4eb2154dac9e406578a1510a6fc48bd0b67e69ea9', }) if (data?.chainId === zkSync.id) { data?.logs // ^? (property) logs: ZkSyncLog[] | undefined } ts import { http, createConfig } from 'wagmi' import { base, celo, mainnet } from 'wagmi/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) declare module 'wagmi' { interface Register { config: typeof config } } Troubleshooting [​](#troubleshooting) -------------------------------------- If chain properties aren't working, make sure [TypeScript](/react/guides/faq#type-inference-doesn-t-work) is configured correctly. Not all chains have additional properties, to check which ones do, see the [Viem repo](https://github.com/wevm/viem/tree/main/src/chains) (chains that have a top-level directory under [`src/chains`](https://github.com/wevm/viem/tree/main/src/chains) support additional properties). --- # Installation | Wagmi Return to top Installation [​](#installation) ================================ Install Wagmi via your package manager, a ` Requirements [​](#requirements) -------------------------------- Wagmi is optimized for modern browsers. It is compatible with the latest versions of the following browsers. ![chrome](/browsers/chrome.png)![edge](/browsers/edge.png)![firefox](/browsers/firefox.png)![opera](/browsers/opera.png)![safari](/browsers/safari.png) TIP Depending on your environment, you might need to add polyfills. See [Viem Platform Compatibility](https://viem.sh/docs/compatibility.html) for more info. Using Unreleased Commits [​](#using-unreleased-commits) -------------------------------------------------------- If you can't wait for a new release to test the latest features, you can either install from the `canary` tag (tracks the [`main`](https://github.com/wevm/wagmi/tree/main) branch). pnpmnpmyarnbun bash pnpm add @wagmi/core@canary bash npm install @wagmi/core@canary bash yarn add @wagmi/core@canary bash bun add @wagmi/core@canary Or clone the [Wagmi repo](https://github.com/wevm/wagmi) to your local machine, build, and link it yourself. bash gh repo clone wevm/wagmi cd wagmi pnpm install pnpm build cd packages/core pnpm link --global Then go to the project where you are using Wagmi and run `pnpm link --global @wagmi/core` (or the package manager that you used to link Wagmi globally). Make sure you installed any [required peer dependencies](#package-manager) and their versions are correct. Security [​](#security) ------------------------ Ethereum-related projects are often targeted in attacks to steal users' assets. Make sure you follow security best-practices for your project. Some quick things to get started. * Pin package versions, upgrade mindfully, and inspect lockfile changes to minimize the risk of [supply-chain attacks](https://nodejs.org/en/guides/security/#supply-chain-attacks) . * Install the [Socket Security](https://socket.dev) [GitHub App](https://github.com/apps/socket-security) to help detect and block supply-chain attacks. * Add a [Content Security Policy](https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html) to defend against external scripts running in your app. --- # TypeScript | Wagmi Return to top TypeScript [​](#typescript) ============================ Requirements [​](#requirements) -------------------------------- Wagmi is designed to be as type-safe as possible! Things to keep in mind: * Types currently require using TypeScript >=5.0.4. * [TypeScript doesn't follow semver](https://www.learningtypescript.com/articles/why-typescript-doesnt-follow-strict-semantic-versioning) and often introduces breaking changes in minor releases. * Changes to types in this repository are considered non-breaking and are usually released as patch changes (otherwise every type enhancement would be a major version!). * It is highly recommended that you lock your `wagmi` and `typescript` versions to specific patch releases and upgrade with the expectation that types may be fixed or upgraded between any release. * The non-type-related public API of Wagmi still follows semver very strictly. To ensure everything works correctly, make sure your `tsconfig.json` has [`strict`](https://www.typescriptlang.org/tsconfig#strict) mode set to `true`. tsconfig.json json { "compilerOptions": { "strict": true } } Config Types [​](#config-types) -------------------------------- By default Vue Plugins does not work well with type inference. To support strong type-safety across the Vue Plugins boundary, there are two options available: * Declaration merging to "register" your `config` globally with TypeScript. * `config` property to pass your `config` directly to composables. ### Declaration Merging [​](#declaration-merging) [Declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) allows you to "register" your `config` globally with TypeScript. The `Register` type enables Wagmi to infer types in places that wouldn't normally have access to type info via a Vue Plugin alone. To set this up, add the following declaration to your project. Below, we co-locate the declaration merging and the `config` set up. ts import { createConfig, http } from '@wagmi/vue' import { mainnet, sepolia } from 'wagmi/chains' declare module '@wagmi/vue' { interface Register { config: typeof config } } export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Since the `Register` type is global, you only need to add it once in your project. Once set up, you will get strong type-safety across your entire project. For example, query composables will type `chainId` based on your `config`'s `chains`. ts import { } from '@wagmi/vue' ({ chainId: 123 })Type '123' is not assignable to type 'DeepMaybeRef<1 | 11155111 | undefined>'. You just saved yourself a runtime error and you didn't even need to pass your `config`. 🎉 ### Hook `config` Property [​](#hook-config-property) For cases where you have more than one Wagmi `config` or don't want to use the declaration merging approach, you can pass a specific `config` directly to composables via the `config` property. ts import { createConfig, http } from '@wagmi/vue' import { mainnet, optimism } from '@wagmi/vue/chains' export const configA = createConfig({ chains: [mainnet], transports: { [mainnet.id]: http(), }, }) export const configB = createConfig({ chains: [optimism], transports: { [optimism.id]: http(), }, }) As you expect, `chainId` is inferred correctly for each `config`. ts import { } from '@wagmi/vue' ({ chainId: 123, : })Type '123' is not assignable to type 'DeepMaybeRef<1 | undefined>'.({ chainId: 123, : })Type '123' is not assignable to type 'DeepMaybeRef<10 | undefined>'. This approach is more explicit, but works well for advanced use-cases, if you don't want to use a Vue Plugin or declaration merging, etc. Const-Assert ABIs & Typed Data [​](#const-assert-abis-typed-data) ------------------------------------------------------------------ Wagmi can infer types based on [ABIs](https://docs.soliditylang.org/en/latest/abi-spec.html#json) and [EIP-712](https://eips.ethereum.org/EIPS/eip-712) Typed Data definitions, powered by [Viem](https://viem.sh) and [ABIType](https://github.com/wevm/abitype) . This achieves full end-to-end type-safety from your contracts to your frontend and enlightened developer experience by autocompleting ABI item names, catching misspellings, inferring argument and return types (including overloads), and more. For this to work, you must either [const-assert](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) ABIs and Typed Data (more info below) or define them inline. For example, `useReadContract`'s `abi` configuration parameter: ts const { data } = useReadContract({ abi: […], // <--- defined inline }) ts const abi = […] as const // <--- const assertion const { data } = useReadContract({ abi }) If type inference isn't working, it's likely you forgot to add a `const` assertion or define the configuration parameter inline. Also, make sure your ABIs, Typed Data definitions, and [TypeScript configuration](#requirements) are valid and set up correctly. TIP Unfortunately [TypeScript doesn't support importing JSON `as const` yet](https://github.com/microsoft/TypeScript/issues/32063) . Check out the [Wagmi CLI](/cli/getting-started) to help with this! It can automatically fetch ABIs from Etherscan and other block explorers, resolve ABIs from your Foundry/Hardhat projects, generate Vue Composables, and more. Anywhere you see the `abi` or `types` configuration property, you can likely use const-asserted or inline ABIs and Typed Data to get type-safety and inference. These properties are also called out in the docs. Here's what [`useReadContract`](/vue/api/composables/useReadContract) looks like with and without a const-asserted `abi` property. Const-AssertedNot Const-Asserted ts import { } from '@wagmi/vue' const { } = ({ : '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', : , : 'balanceOf', : ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], }) ts import { } from '@wagmi/vue' const { } = ({ : '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', : , : 'balanceOf', : ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], }) You can prevent runtime errors and be more productive by making sure your ABIs and Typed Data definitions are set up appropriately. 🎉 ts import { } from '@wagmi/vue' ({ : , functionName: 'balanecOf',Type '"balanecOf"' is not assignable to type 'DeepMaybeRef<"balanceOf" | "isApprovedForAll" | "getApproved" | "ownerOf" | "tokenURI" | undefined>'. Did you mean '"balanceOf"'?}) Configure Internal Types [​](#configure-internal-types) -------------------------------------------------------- For advanced use-cases, you may want to configure Wagmi's internal types. Most of Wagmi's types relating to ABIs and EIP-712 Typed Data are powered by [ABIType](https://github.com/wevm/abitype) . See the [ABIType docs](https://abitype.dev) for more info on how to configure types. --- # Connect Wallet | Wagmi Return to top Connect Wallet [​](#connect-wallet) ==================================== The ability for a user to connect their wallet is a core function for any Dapp. It allows users to perform tasks such as: writing to contracts, signing messages, or sending transactions. Wagmi contains everything you need to get started with building a Connect Wallet module. To get started, you can either use a [third-party library](#third-party-libraries) or [build your own](#build-your-own) . Third-party Libraries [​](#third-party-libraries) -------------------------------------------------- You can use a pre-built Connect Wallet module from a third-party library such as: * [ConnectKit](https://docs.family.co/connectkit) - [Guide](https://docs.family.co/connectkit/getting-started) * [AppKit](https://walletconnect.com/appkit) - [Guide](https://docs.walletconnect.com/appkit/next/core/installation) * [RainbowKit](https://www.rainbowkit.com/) - [Guide](https://www.rainbowkit.com/docs/installation) * [Dynamic](https://www.dynamic.xyz/) - [Guide](https://docs.dynamic.xyz/quickstart) * [Privy](https://privy.io) - [Guide](https://docs.privy.io/guide/react/wallets/usage/wagmi) The above libraries are all built on top of Wagmi, handle all the edge cases around wallet connection, and provide a seamless Connect Wallet UX that you can use in your Dapp. Build Your Own [​](#build-your-own) ------------------------------------ Wagmi provides you with the Hooks to get started building your own Connect Wallet module. It takes less than five minutes to get up and running with Browser Wallets, WalletConnect, and Coinbase Wallet. ### 1\. Configure Wagmi [​](#_1-configure-wagmi) Before we get started with building the functionality of the Connect Wallet module, we will need to set up the Wagmi configuration. Let's create a `config.ts` file and export a `config` object. config.ts tsx import { http, createConfig } from 'wagmi' import { base, mainnet, optimism } from 'wagmi/chains' import { injected, metaMask, safe, walletConnect } from 'wagmi/connectors' const projectId = '' export const config = createConfig({ chains: [mainnet, base], connectors: [\ injected(),\ walletConnect({ projectId }),\ metaMask(),\ safe(),\ ], transports: { [mainnet.id]: http(), [base.id]: http(), }, }) In the above configuration, we want to set up connectors for Injected (browser), WalletConnect (browser + mobile), MetaMask, and Safe wallets. This configuration uses the **Mainnet** and **Base** chains, but you can use whatever you want. WARNING Make sure to replace the `projectId` with your own WalletConnect Project ID, if you wish to use WalletConnect! [Get your Project ID](https://cloud.walletconnect.com/) ### 2\. Wrap App in Context Provider [​](#_2-wrap-app-in-context-provider) Next, we will need to wrap our React App with Context so that our application is aware of Wagmi & React Query's reactive state and in-memory caching. app.tsxconfig.ts tsx // 1. Import modules import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { WagmiProvider } from 'wagmi' import { config } from './config' // 2. Set up a React Query client. const queryClient = new QueryClient() function App() { // 3. Wrap app with Wagmi and React Query context. return ( {/** ... */} ) } tsx import { http, createConfig } from 'wagmi' import { base, mainnet, optimism } from 'wagmi/chains' import { injected, metaMask, safe, walletConnect } from 'wagmi/connectors' const projectId = '' export const config = createConfig({ chains: [mainnet, base], connectors: [\ injected(),\ walletConnect({ projectId }),\ metaMask(),\ safe(),\ ], transports: { [mainnet.id]: http(), [base.id]: http(), }, }) ### 3\. Display Wallet Options [​](#_3-display-wallet-options) After that, we will create a `WalletOptions` component that will display our connectors. This will allow users to select a wallet and connect. Below, we are rendering a list of `connectors` retrieved from `useConnect`. When the user clicks on a connector, the `connect` function will connect the users' wallet. wallet-options.tsxapp.tsxconfig.ts tsx import * as React from 'react' import { Connector, useConnect } from 'wagmi' export function WalletOptions() { const { connectors, connect } = useConnect() return connectors.map((connector) => ( )) } tsx // 1. Import modules import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { WagmiProvider } from 'wagmi' import { config } from './config' // 2. Set up a React Query client. const queryClient = new QueryClient() function App() { // 3. Wrap app with Wagmi and React Query context. return ( {/* ... */} ) } tsx import { http, createConfig } from 'wagmi' import { base, mainnet, optimism } from 'wagmi/chains' import { injected, metaMask, safe, walletConnect } from 'wagmi/connectors' const projectId = '' export const config = createConfig({ chains: [mainnet, base], connectors: [\ injected(),\ walletConnect({ projectId }),\ metaMask(),\ safe(),\ ], transports: { [mainnet.id]: http(), [base.id]: http(), }, }) ### 4\. Display Connected Account [​](#_4-display-connected-account) Lastly, if an account is connected, we want to show some basic information, like the connected address and ENS name and avatar. Below, we are using hooks like `useAccount`, `useEnsAvatar` and `useEnsName` to extract this information. We are also utilizing `useDisconnect` to show a "Disconnect" button so a user can disconnect their wallet. account.tsxwallet-options.tsxapp.tsxconfig.ts tsx import { useAccount, useDisconnect, useEnsAvatar, useEnsName } from 'wagmi' export function Account() { const { address } = useAccount() const { disconnect } = useDisconnect() const { data: ensName } = useEnsName({ address }) const { data: ensAvatar } = useEnsAvatar({ name: ensName! }) return (
{ensAvatar && ENS Avatar} {address &&
{ensName ? `${ensName} (${address})` : address}
}
) } tsx import * as React from 'react' import { Connector, useConnect } from 'wagmi' export function WalletOptions() { const { connectors, connect } = useConnect() return connectors.map((connector) => ( connect({ connector })} /> )) } function WalletOption({ connector, onClick, }: { connector: Connector onClick: () => void }) { const [ready, setReady] = React.useState(false) React.useEffect(() => { ;(async () => { const provider = await connector.getProvider() setReady(!!provider) })() }, [connector]) return ( ) } tsx // 1. Import modules import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { WagmiProvider } from 'wagmi' import { config } from './config' // 2. Set up a React Query client. const queryClient = new QueryClient() function App() { // 3. Wrap app with Wagmi and React Query context. return ( {/* ... */} ) } tsx import { http, createConfig } from 'wagmi' import { base, mainnet, optimism } from 'wagmi/chains' import { injected, metaMask, safe, walletConnect } from 'wagmi/connectors' const projectId = '' export const config = createConfig({ chains: [mainnet, base], connectors: [\ injected(),\ walletConnect({ projectId }),\ metaMask(),\ safe(),\ ], transports: { [mainnet.id]: http(), [base.id]: http(), }, }) ### 5\. Wire it up! [​](#_5-wire-it-up) Finally, we can wire up our Wallet Options and Account components to our application's entrypoint. app.tsxaccount.tsxwallet-options.tsxconfig.ts tsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { WagmiProvider, useAccount } from 'wagmi' import { config } from './config' import { Account } from './account' import { WalletOptions } from './wallet-options' const queryClient = new QueryClient() function ConnectWallet() { const { isConnected } = useAccount() if (isConnected) return return } function App() { return ( ) } tsx import { useAccount, useDisconnect, useEnsAvatar, useEnsName } from 'wagmi' export function Account() { const { address } = useAccount() const { disconnect } = useDisconnect() const { data: ensName } = useEnsName({ address }) const { data: ensAvatar } = useEnsAvatar({ name: ensName! }) return (
{ensAvatar && ENS Avatar} {address &&
{ensName ? `${ensName} (${address})` : address}
}
) } tsx import * as React from 'react' import { Connector, useConnect } from 'wagmi' export function WalletOptions() { const { connectors, connect } = useConnect() return connectors.map((connector) => ( connect({ connector })} /> )) } function WalletOption({ connector, onClick, }: { connector: Connector onClick: () => void }) { const [ready, setReady] = React.useState(false) React.useEffect(() => { ;(async () => { const provider = await connector.getProvider() setReady(!!provider) })() }, [connector]) return ( ) } tsx import { http, createConfig } from 'wagmi' import { base, mainnet, optimism } from 'wagmi/chains' import { injected, metaMask, safe, walletConnect } from 'wagmi/connectors' const projectId = '' export const config = createConfig({ chains: [mainnet, base], connectors: [\ injected(),\ walletConnect({ projectId }),\ metaMask(),\ safe(),\ ], transports: { [mainnet.id]: http(), [base.id]: http(), }, }) ### Playground [​](#playground) Want to see the above steps all wired up together in an end-to-end example? Check out the below StackBlitz playground. --- # Installation | Wagmi Return to top Installation [​](#installation) ================================ Install Wagmi CLI via your package manager. Package Manager [​](#package-manager) -------------------------------------- Install the required package. pnpmnpmyarnbun bash pnpm add @wagmi/cli bash npm install @wagmi/cli bash yarn add @wagmi/cli bash bun add @wagmi/cli Using Unreleased Commits [​](#using-unreleased-commits) -------------------------------------------------------- If you can't wait for a new release to test the latest features, you can either install from the `canary` tag (tracks the [`main`](https://github.com/wevm/wagmi/tree/main) branch). pnpmnpmyarnbun bash pnpm add @wagmi/cli@canary bash npm install @wagmi/cli@canary bash yarn add @wagmi/cli@canary bash bun add @wagmi/cli@canary Or clone the [Wagmi repo](https://github.com/wevm/wagmi) to your local machine, build, and link it yourself. bash git clone https://github.com/wevm/wagmi.git cd wagmi pnpm install pnpm build cd packages/cli pnpm link --global Then go to the project where you are using the Wagmi CLI and run `pnpm link --global @wagmi/cli` (or the package manager that you used to link Wagmi CLI globally). --- # TanStack Query | Wagmi Return to top TanStack Query [​](#tanstack-query) ==================================== Wagmi Composables are not only a wrapper around the core [Wagmi Actions](/core/api/actions) , but they also utilize [TanStack Query](https://tanstack.com/query/v5) to enable trivial and intuitive fetching, caching, synchronizing, and updating of asynchronous data in your Vue applications. Without an asynchronous data fetching abstraction, you would need to handle all the negative side-effects that comes as a result, such as: representing finite states (loading, error, success), handling race conditions, caching against a deterministic identifier, etc. Queries & Mutations [​](#queries-mutations) -------------------------------------------- Wagmi Composables represent either a **Query** or a **Mutation**. **Queries** are used for fetching data (e.g. fetching a block number, reading from a contract, etc), and are typically invoked on mount by default. All queries are coupled to a unique [Query Key](#query-keys) , and can be used for further operations such as refetching, prefetching, or modifying the cached data. **Mutations** are used for mutating data (e.g. connecting/disconnecting accounts, writing to a contract, switching chains, etc), and are typically invoked in response to a user interaction. Unlike **Queries**, they are not coupled with a query key. Terms [​](#terms) ------------------ * **Query**: An asynchronous data fetching (e.g. read data) operation that is tied against a unique Query Key. * **Mutation**: An asynchronous mutating (e.g. create/update/delete data or side-effect) operation. * **Query Key**: A unique identifier that is used to deterministically identify a query. It is typically a tuple of the query name and the query arguments. * **Stale Data**: Data that is unused or inactive after a certain period of time. * **Query Fetching**: The process of invoking an async query function. * **Query Refetching**: The process of refetching **rendered** queries. * **[Query Invalidation](https://tanstack.com/query/v5/docs/vue/guides/query-invalidation) **: The process of marking query data as stale (e.g. inactive/unused), and refetching **rendered** queries. * **[Query Prefetching](https://tanstack.com/query/v5/docs/vue/guides/prefetching) **: The process of prefetching queries and seeding the cache. Query Keys [​](#query-keys) ---------------------------- Query Keys are typically used to perform advanced operations on the query such as: invalidation, refetching, prefetching, etc. Wagmi exports Query Keys for every Composable, and they can be retrieved via the [Composable (Vue)](#composable-vue) or via an [Import (Vanilla JS)](#import-vanilla-js) . Read more about **Query Keys** on the [TanStack Query docs.](https://tanstack.com/query/v5/docs/vue/guides/query-keys) ### Composable (Vue) [​](#composable-vue) Each Composable returns a `queryKey` value. You would use this approach when you want to utilize the query key in a Vue component as it handles reactivity for you, unlike the [Import](#import-vanilla-js) method below. vue ### Import (Vanilla JS) [​](#import-vanilla-js) Each Hook has a corresponding `getQueryOptions` function that returns a query key. You would use this method when you want to utilize the query key outside of a Vue component in a Vanilla JS context, like in a utility function. ts import { getBalanceQueryOptions } from '@wagmi/vue/query' import { config } from './config' function perform() { const { queryKey } = getBalanceQueryOptions(config, { chainId: config.state.chainId }) } WARNING The caveat of this method is that it does not handle reactivity for you (e.g. active account/chain changes, argument changes, etc). You would need to handle this yourself by explicitly passing through the arguments to `getQueryOptions`. Invalidating Queries [​](#invalidating-queries) ------------------------------------------------ Invalidating a query is the process of marking the query data as stale (e.g. inactive/unused), and refetching the queries that are already rendered. Read more about **Invalidating Queries** on the [TanStack Query docs.](https://tanstack.com/query/v5/docs/vue/guides/query-invalidation) #### Example: Watching a Users' Balance [​](#example-watching-a-users-balance) You may want to "watch" a users' balance, and invalidate the balance after each incoming block. We can invoke `invalidateQueries` inside a `watchEffect` – this will refetch all rendered balance queries when the `blockNumber` changes. vue #### Example: After User Interaction [​](#example-after-user-interaction) Maybe you want to invalidate a users' balance after some interaction. This would mark the balance as stale, and consequently refetch all rendered balance queries. vue vue Fetching Queries [​](#fetching-queries) ---------------------------------------- Fetching a query is the process of invoking the query function to retrieve data. If the query exists and the data is not invalidated or older than a given `staleTime`, then the data from the cache will be returned. Otherwise, the query will fetch for the latest data. example.tsxmain.tsconfig.ts tsx import { getBlockQueryOptions } from '@wagmi/vue/query' import { queryClient } from './main' import { config } from './config' export async function fetchBlockData() { return queryClient.fetchQuery( getBlockQueryOptions(config, { chainId: config.state.chainId, } )) } ts import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query' import { WagmiPlugin } from '@wagmi/vue' import { createApp } from 'vue' import App from './App.vue' import { config } from './config' export const queryClient = new QueryClient() createApp(App) .use(WagmiPlugin, { config }) .use(VueQueryPlugin, { queryClient }) .mount('#app') ts import { http, createConfig } from '@wagmi/vue' import { mainnet, sepolia } from '@wagmi/vue/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Retrieving & Updating Query Data [​](#retrieving-updating-query-data) ---------------------------------------------------------------------- You can retrieve and update query data imperatively with `getQueryData` and `setQueryData`. This is useful for scenarios where you want to retrieve or update a query outside of a Vue component. Note that these functions do not invalidate or refetch queries. example.tsxmain.tsconfig.ts tsx import type { GetBalanceReturnType } from '@wagmi/vue/actions' import { getBalanceQueryOptions } from '@wagmi/vue/query' import { queryClient } from './app' import { config } from './config' export function getBalanceData() { return queryClient.getQueryData( getBalanceQueryOptions(config, { chainId: config.state.chainId, } )) } export function setBalanceData(parameters: Partial) { return queryClient.setQueryData( getBalanceQueryOptions(config, { chainId: config.state.chainId, }, data => ({ ...data, ...parameters }) )) } ts import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query' import { WagmiPlugin } from '@wagmi/vue' import { createApp } from 'vue' import App from './App.vue' import { config } from './config' export const queryClient = new QueryClient() createApp(App) .use(WagmiPlugin, { config }) .use(VueQueryPlugin, { queryClient }) .mount('#app') ts import { http, createConfig } from '@wagmi/vue' import { mainnet, sepolia } from '@wagmi/vue/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Prefetching Queries [​](#prefetching-queries) ---------------------------------------------- Prefetching a query is the process of fetching the data ahead of time and seeding the cache with the returned data. This is useful for scenarios where you want to fetch data before the user navigates to a page, or fetching data on the server to be reused on client hydration. Read more about **Prefetching Queries** on the [TanStack Query docs.](https://tanstack.com/query/v5/docs/vue/guides/prefetching) #### Example: Prefetching in Event Handler [​](#example-prefetching-in-event-handler) vue SSR [​](#ssr) -------------- It is possible to utilize TanStack Query's SSR strategies with Wagmi Composables & Query Keys. Check out the [SSR guide](https://tanstack.com/query/latest/docs/framework/vue/guides/ssr) . Devtools [​](#devtools) ------------------------ TanStack Query includes dedicated [Devtools](https://tanstack.com/query/latest/docs/framework/vue/devtools) that assist in visualizing and debugging your queries, their cache states, and much more. You will have to pass a custom `queryKeyFn` to your `QueryClient` for Devtools to correctly serialize BigInt values for display. Alternatively, You can use the `hashFn` from `@wagmi/core/query`, which already handles this serialization. #### Install [​](#install) pnpmnpmyarnbun bash pnpm i @tanstack/vue-query-devtools bash npm i @tanstack/vue-query-devtools bash yarn add @tanstack/vue-query-devtools bash bun i @tanstack/vue-query-devtools #### Usage [​](#usage) App.vuemain.vue vue vue --- # TypeScript | Wagmi Return to top TypeScript [​](#typescript) ============================ Requirements [​](#requirements) -------------------------------- Wagmi Core is designed to be as type-safe as possible! Things to keep in mind: * Types currently require using TypeScript >=5.0.4. * [TypeScript doesn't follow semver](https://www.learningtypescript.com/articles/why-typescript-doesnt-follow-strict-semantic-versioning) and often introduces breaking changes in minor releases. * Changes to types in this repository are considered non-breaking and are usually released as patch changes (otherwise every type enhancement would be a major version!). * It is highly recommended that you lock your `@wagmi/core` and `typescript` versions to specific patch releases and upgrade with the expectation that types may be fixed or upgraded between any release. * The non-type-related public API of Wagmi Core still follows semver very strictly. To ensure everything works correctly, make sure your `tsconfig.json` has [`strict`](https://www.typescriptlang.org/tsconfig#strict) mode set to `true`. tsconfig.json json { "compilerOptions": { "strict": true } } Const-Assert ABIs & Typed Data [​](#const-assert-abis-typed-data) ------------------------------------------------------------------ Wagmi Core can infer types based on [ABIs](https://docs.soliditylang.org/en/latest/abi-spec.html#json) and [EIP-712](https://eips.ethereum.org/EIPS/eip-712) Typed Data definitions, powered by [Viem](https://viem.sh) and [ABIType](https://github.com/wevm/abitype) . This achieves full end-to-end type-safety from your contracts to your frontend and enlightened developer experience by autocompleting ABI item names, catching misspellings, inferring argument and return types (including overloads), and more. For this to work, you must either [const-assert](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) ABIs and Typed Data (more info below) or define them inline. For example, `useReadContract`'s `abi` configuration parameter: ts const result = await readContract({ abi: […], // <--- defined inline }) ts const abi = […] as const // <--- const assertion const result = readContract({ abi }) If type inference isn't working, it's likely you forgot to add a `const` assertion or define the configuration parameter inline. Also, make sure your ABIs, Typed Data definitions, and [TypeScript configuration](#requirements) are valid and set up correctly. TIP Unfortunately [TypeScript doesn't support importing JSON `as const` yet](https://github.com/microsoft/TypeScript/issues/32063) . Check out the [Wagmi CLI](/cli/getting-started) to help with this! It can automatically fetch ABIs from Etherscan and other block explorers, resolve ABIs from your Foundry/Hardhat projects, and more. Anywhere you see the `abi` or `types` configuration property, you can likely use const-asserted or inline ABIs and Typed Data to get type-safety and inference. These properties are also called out in the docs. Here's what [`readContract`](/core/api/actions/readContract) looks like with and without a const-asserted `abi` property. Const-AssertedNot Const-Asserted ts import { } from '@wagmi/core' const = await (, { : '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', : , : 'balanceOf', : ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], }) ts import { } from '@wagmi/core' const = await (, { : '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', : , : 'balanceOf', : ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], }) You can prevent runtime errors and be more productive by making sure your ABIs and Typed Data definitions are set up appropriately. 🎉 ts import { } from '@wagmi/core' (, { : '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', : , functionName: 'balanecOf',Type '"balanecOf"' is not assignable to type '"balanceOf" | "isApprovedForAll" | "getApproved" | "ownerOf" | "tokenURI"'. Did you mean '"balanceOf"'? : ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], }) Configure Internal Types [​](#configure-internal-types) -------------------------------------------------------- For advanced use-cases, you may want to configure wagmi's internal types. Most of wagmi's types relating to ABIs and EIP-712 Typed Data are powered by [ABIType](https://github.com/wevm/abitype) . See the [ABIType docs](https://abitype.dev) for more info on how to configure types. --- # Send Transaction | Wagmi Return to top Send Transaction [​](#send-transaction) ======================================== The following guide teaches you how to send transactions in Wagmi. The example below builds on the [Connect Wallet guide](/react/guides/connect-wallet) and uses the [useSendTransaction](/react/api/hooks/useSendTransaction) & [useWaitForTransaction](/react/api/hooks/useWaitForTransactionReceipt) hooks. Example [​](#example) ---------------------- Feel free to check out the example before moving on: Steps [​](#steps) ------------------ ### 1\. Connect Wallet [​](#_1-connect-wallet) Follow the [Connect Wallet guide](/react/guides/connect-wallet) guide to get this set up. ### 2\. Create a new component [​](#_2-create-a-new-component) Create your `SendTransaction` component that will contain the send transaction logic. send-transaction.tsx tsx import * as React from 'react' export function SendTransaction() { return (
) } ### 3\. Add a form handler [​](#_3-add-a-form-handler) Next, we will need to add a handler to the form that will send the transaction when the user hits "Send". This will be a basic handler in this step. send-transaction.tsx tsx import * as React from 'react' export function SendTransaction() { async function submit(e: React.FormEvent) { e.preventDefault() const formData = new FormData(e.target as HTMLFormElement) const to = formData.get('address') as `0x${string}` const value = formData.get('value') as string } return (
) } ### 4\. Hook up the `useSendTransaction` Hook [​](#_4-hook-up-the-usesendtransaction-hook) Now that we have the form handler, we can hook up the [`useSendTransaction` Hook](/react/api/hooks/useSendTransaction) to send the transaction. send-transaction.tsx tsx import * as React from 'react' import { useSendTransaction } from 'wagmi' import { parseEther } from 'viem' export function SendTransaction() { const { data: hash, sendTransaction } = useSendTransaction() async function submit(e: React.FormEvent) { e.preventDefault() const formData = new FormData(e.target as HTMLFormElement) const to = formData.get('address') as `0x${string}` const value = formData.get('value') as string sendTransaction({ to, value: parseEther(value) }) } return (
{hash &&
Transaction Hash: {hash}
}
) } ### 5\. Add loading state (optional) [​](#_5-add-loading-state-optional) We can optionally add a loading state to the "Send" button while we are waiting confirmation from the user's wallet. send-transaction.tsx tsx import * as React from 'react' import { useSendTransaction } from 'wagmi' import { parseEther } from 'viem' export function SendTransaction() { const { data: hash, isPending, sendTransaction } = useSendTransaction() async function submit(e: React.FormEvent) { e.preventDefault() const formData = new FormData(e.target as HTMLFormElement) const to = formData.get('address') as `0x${string}` const value = formData.get('value') as string sendTransaction({ to, value: parseEther(value) }) } return (
{hash &&
Transaction Hash: {hash}
}
) } ### 6\. Wait for transaction receipt (optional) [​](#_6-wait-for-transaction-receipt-optional) We can also display the transaction confirmation status to the user by using the [`useWaitForTransactionReceipt` Hook](/react/api/hooks/useWaitForTransactionReceipt) . send-transaction.tsx tsx import * as React from 'react' import { useSendTransaction, useWaitForTransactionReceipt } from 'wagmi' import { parseEther } from 'viem' export function SendTransaction() { const { data: hash, isPending, sendTransaction } = useSendTransaction() async function submit(e: React.FormEvent) { e.preventDefault() const formData = new FormData(e.target as HTMLFormElement) const to = formData.get('address') as `0x${string}` const value = formData.get('value') as string sendTransaction({ to, value: parseEther(value) }) } const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ hash, }) return (
{hash &&
Transaction Hash: {hash}
} {isConfirming &&
Waiting for confirmation...
} {isConfirmed &&
Transaction confirmed.
}
) } ### 7\. Handle errors (optional) [​](#_7-handle-errors-optional) If the user rejects the transaction, or the user does not have enough funds to cover the transaction, we can display an error message to the user. send-transaction.tsx tsx import * as React from 'react' import { type BaseError, useSendTransaction, useWaitForTransactionReceipt } from 'wagmi' import { parseEther } from 'viem' export function SendTransaction() { const { data: hash, error, isPending, sendTransaction } = useSendTransaction() async function submit(e: React.FormEvent) { e.preventDefault() const formData = new FormData(e.target as HTMLFormElement) const to = formData.get('address') as `0x${string}` const value = formData.get('value') as string sendTransaction({ to, value: parseEther(value) }) } const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ hash, }) return (
{hash &&
Transaction Hash: {hash}
} {isConfirming &&
Waiting for confirmation...
} {isConfirmed &&
Transaction confirmed.
} {error && (
Error: {(error as BaseError).shortMessage || error.message}
)}
) } ### 8\. Wire it up! [​](#_8-wire-it-up) Finally, we can wire up our Send Transaction component to our application's entrypoint. app.tsxsend-transaction.tsxconfig.ts tsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { WagmiProvider, useAccount } from 'wagmi' import { config } from './config' import { SendTransaction } from './send-transaction' const queryClient = new QueryClient() function App() { return ( ) } tsx import * as React from 'react' import { type BaseError, useSendTransaction, useWaitForTransactionReceipt } from 'wagmi' import { parseEther } from 'viem' export function SendTransaction() { const { data: hash, error, isPending, sendTransaction } = useSendTransaction() async function submit(e: React.FormEvent) { e.preventDefault() const formData = new FormData(e.target as HTMLFormElement) const to = formData.get('address') as `0x${string}` const value = formData.get('value') as string sendTransaction({ to, value: parseEther(value) }) } const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ hash, }) return (
{hash &&
Transaction Hash: {hash}
} {isConfirming &&
Waiting for confirmation...
} {isConfirmed &&
Transaction confirmed.
} {error && (
Error: {(error as BaseError).shortMessage || error.message}
)}
) } tsx import { http, createConfig } from 'wagmi' import { base, mainnet, optimism } from 'wagmi/chains' import { injected, metaMask, safe, walletConnect } from 'wagmi/connectors' const projectId = '' export const config = createConfig({ chains: [mainnet, base], connectors: [\ injected(),\ walletConnect({ projectId }),\ metaMask(),\ safe(),\ ], transports: { [mainnet.id]: http(), [base.id]: http(), }, }) [See the Example.](#example) --- # Creating Connectors | Wagmi Return to top Creating Connectors [​](#creating-connectors) ============================================== Thanks for your interest in adding a new connector to Wagmi! Please take a moment to review this document **before starting work on a new connector.** Overview [​](#overview) ------------------------ This guide details how to create new connectors and upstream them back into Wagmi. By following these steps, you will understand the development process, workflow, and requirements for new connectors. **Not all connectors will be accepted into Wagmi** for a variety of reasons outlined in this document. In addition, for connector requests to be accepted, the team creating the connector must [sponsor Wagmi](https://github.com/sponsors/wevm) . It takes time and effort to maintain third-party connectors. Wagmi is an OSS project that depends on sponsors and grants to continue our work. Please get in touch via [dev@wevm.dev](mailto:dev@wevm.dev) if you have questions about sponsoring. **Please ask first before starting work on a new connector.** To avoid having your pull request declined after investing time and effort into a new connector, we ask that contributors create a [Connector Request](https://github.com/wevm/wagmi/discussions/new?category=connector-request) before starting work. This ensures the connector solves for an important or general use-case of interest to Wagmi users and is well supported by the Wagmi and connector teams. 1\. Follow the contributing guide [​](#_1-follow-the-contributing-guide) ------------------------------------------------------------------------- Check out the [Contributing Guide](/dev/contributing) to get your local development environment set up and learn more about the contributing workflow. 2\. Create a new file for the connector [​](#_2-create-a-new-file-for-the-connector) ------------------------------------------------------------------------------------- Create a new file in `packages/connector/src` named after the connector you want to add. For example, if you want to add Foo, you would create a file named `foo.ts`. File names should be camel-cased and as short as possible. 3\. Create the connector object. [​](#_3-create-the-connector-object) ---------------------------------------------------------------------- Import `createConnector` from `@wagmi/core` and export a new function that accepts a parameters object and returns the `createConnector` result. This is the base of all connectors. The name of the connector name should be the same as the file name. ts import { createConnector } from '@wagmi/core' export type FooBarBazParameters = {} export function fooBarBaz(parameters: FooBarBazParameters = {}) { return createConnector((config) => ({})) } 4\. Add the missing properties to the object [​](#_4-add-the-missing-properties-to-the-object) ----------------------------------------------------------------------------------------------- Now that the base of the connector is set up, you should see a type error that looks something like this: ts (() => ({}))Type '{}' is missing the following properties from type '{ [x: string]: unknown; readonly icon?: string | undefined; readonly id: string; readonly name: string; readonly rdns?: string | readonly string[] | undefined; readonly supportsSimulation?: boolean | undefined; ... 14 more ...; onMessage?: ((message: ProviderMessage) => void) | undefined; }': id, name, type, connect, and 8 more. The type error tells you what properties are missing from `createConnector`'s return type. Add them all in! #### Properties [​](#properties) * `icon`: Optional icon URL for the connector. * `id`: The ID for the connector. This should be camel-cased and as short as possible. Example: `fooBarBaz`. * `name`: Human-readable name for the connector. Example: `'Foo Bar Baz'`. * `rdns`: Optional reverse DNS for the connector. This is used to filter out duplicate [EIP-6963](https://eips.ethereum.org/EIPS/eip-6963) injected providers when `createConfig#multiInjectedProviderDiscovery` is enabled. #### Methods [​](#methods) * `connect`: Function for connecting the connector. * `disconnect`: Function for disconnecting the connector. * `getAccounts`: Function that returns the connected accounts for the connector. * `getChainId`: Function that returns the connected chain ID for the connector. * `getProvider`: Function that returns the underlying provider interface for internal use throughout the connector. * `isAuthorized`: Function that returns whether the connector has connected previously and is still authorized. * `setup`: Optional function for running when the connector is first created. * `switchChain`: Optional function for switching the connector's active chain. #### Events [​](#events) * `onAccountsChanged`: Function for subscribing to account changes internally in the connector. * `onChainChanged`: Function for subscribing to chain changes internally in the connector. * `onConnect`: Function for subscribing to connection events internally in the connector. * `onDisconnect`: Function for subscribing to disconnection events internally in the connector. * `onMessage`: Optional function for subscribing to messages internally in the connector. #### Parameters [​](#parameters) `createConnector` also has the following config properties you can use within the connector: * `chains`: List of chains configured by the user. * `emitter`: Emitter for emitting events. Used to sync connector state with Wagmi `Config`. The following events are available: * `change`: Emitted when the connected accounts or chain changes. * `connect`: Emitted when the connector connects. * `disconnect`: Emitted when the connector disconnects. * `error`: Emitted when the connector receives an error. * `message`: Emitted when the connector receives a message. * `storage`: Optional storage configured by the user. Defaults to wrapper around localStorage. TIP If you plan to use a third-party SDK, it should have minimal dependencies (limit bundle size, supply chain attacks, etc.) and use the most permissive license possible (ideally MIT). Any third-party packages, should also have [`"sideEffects": false`](https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free) in their `package.json` file for maximum tree-shakability support. TIP All address values returned and emitted by the connector should be checksummed using Viem's [`getAddress`](https://viem.sh/docs/utilities/getAddress) . 5\. Export the connector [​](#_5-export-the-connector) ------------------------------------------------------- Export the connector from `packages/connector/src/exports/index.ts` in alphabetic order. ts export { fooBarBaz } from './fooBarBaz.js' 6\. Try out the connector and add tests [​](#_6-try-out-the-connector-and-add-tests) ------------------------------------------------------------------------------------- While building a connector, it can be useful to try it out with Wagmi. You can use the [development playgrounds](/dev/contributing#_5-running-the-dev-playgrounds) for testing your changes. Ideally, you should also be able to add tests for the connector in a `connectorName.test.ts` file. This isn't always easy so at a minimum please create a test file with instructions for how to test the connector manually. The test file should include actual tests or "instruction tests" for the following: * How to connect the connector. * How to disconnect the connector. * How to switch the connector's active chain (if applicable). Remember to include all info required to test the connector, like software to install (browser extension, mobile app, etc.), smart contracts to interact with/deploy, etc. Finally, you should also update the test file in `packages/connectors/src/exports/index.test.ts` to include the new connector. You can do this manually or by running: bash pnpm test:update packages/connectors/src/exports/index.test.ts 7\. Add your team to CODEOWNERS [​](#_7-add-your-team-to-codeowners) --------------------------------------------------------------------- It is critical that connectors are updated in a timely manner and actively maintained so that users of Wagmi can rely on them in production settings. The Wagmi core team will provide as much assistance as possible to keep connectors up-to-date with breaking changes from Wagmi, but it is your responsibility to ensure that any dependencies and issues/discussions related to the connector are handled in a timely manner. If issues are not resolved in a timely manner, the connector may be removed from Wagmi. In support of this goal, add at least one member of your team to the [CODEOWNERS](https://github.com/wevm/wagmi/blob/main/.github/CODEOWNERS) file so that you get notified of pull requests, issues, etc. related to the connector. You can add your team like this: /packages/connectors/src/fooBarBaz @tmm @jxom For more info about GitHub code owners, check out the [GitHub Documentation](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) . 8\. Document the connector [​](#_8-document-the-connector) ----------------------------------------------------------- The connector should be documented. Follow the step on [writing documentation](/dev/contributing#_7-writing-documentation) to get set up with running the docs site locally and add the required pages. 9\. Create a changeset [​](#_9-create-a-changeset) --------------------------------------------------- Now that the connector works and has tests, it's time to create a changeset to prepare for release. Run the following to create a changeset: bash pnpm changeset The changeset should be a `patch` applied to the `@wagmi/connectors` repository with the description `Added [ConnectorName]`, For example, `Added Foo Bar Baz`. 10\. Create a pull request [​](#_10-create-a-pull-request) ----------------------------------------------------------- The connector is ready to go! Create a [pull request](/dev/contributing#_8-submitting-a-pull-request) and the connector should make it into a future release of Wagmi after some review. --- # Migrate from v1 to v2 | Wagmi CLI Return to top Migrate from v1 to v2 [​](#migrate-from-v1-to-v2) ================================================== To get started, install the latest version of the Wagmi CLI. pnpmnpmyarnbun bash pnpm add @wagmi/cli bash npm install @wagmi/cli bash yarn add @wagmi/cli bash bun add @wagmi/cli Not ready to migrate yet? The Wagmi CLI v1 docs are still available at [1.x.wagmi.sh/cli](https://1.x.wagmi.sh/cli) . Changed generated action and hook names [​](#changed-generated-action-and-hook-names) -------------------------------------------------------------------------------------- Generated action and hook names now align with [Wagmi v2 naming conventions](/react/guides/migrate-from-v1-to-v2#renamed-hooks) . If you want hooks to still follow Wagmi v1 naming conventions, set [`getActionName`](/cli/api/plugins/actions#getactionname) and [`getHookName`](/cli/api/plugins/react#gethookname) to `'legacy'`. ts import { defineConfig } from '@wagmi/cli' import { actions, react } from '@wagmi/cli/plugins' export default defineConfig({ plugins: [\ actions({\ getActionName: 'legacy', \ }),\ react({\ getHookName: 'legacy', \ }),\ ], }) --- # Viem | Wagmi Return to top Viem [​](#viem) ================ [Viem](https://viem.sh) is a low-level TypeScript Interface for Ethereum that enables developers to interact with the Ethereum blockchain, including: JSON-RPC API abstractions, Smart Contract interaction, wallet & signing implementations, coding/parsing utilities and more. **Wagmi Core** is essentially a wrapper over **Viem** that provides multi-chain functionality via [Wagmi Config](/react/api/createConfig) and automatic account management via [Connectors](/react/api/connectors) . Leveraging Viem Actions [​](#leveraging-viem-actions) ------------------------------------------------------ All of the core [Wagmi Composables](/vue/api/composables) are friendly wrappers around [Viem Actions](https://viem.sh/docs/actions/public/introduction.html) that inject a multi-chain and connector aware [Wagmi Config](/vue/api/createConfig) . There may be cases where you might want to dig deeper and utilize Viem Actions directly (maybe a Composable doesn't exist in Wagmi yet). In these cases, you can create your own custom Wagmi Composable by importing Viem Actions directly via `viem/actions` and plugging in a Viem Client returned by the [`useClient` Composable](/vue/api/composables/useClient) . There are two categories of Viem Actions: * **[Public Actions](https://viem.sh/docs/actions/public/introduction) :** Actions that are "read-only" and do not require a wallet connection. * **[Wallet Actions](https://viem.sh/docs/actions/wallet/introduction) :** Actions that interface with a Wallet and require a wallet connection. While it is not mandatory, it is also recommended to pair Actions with either `useQuery` or `useMutation` to effectively leverage the reactivity and caching capabilities of [Tanstack Query](/vue/guides/tanstack-query) . ### Public Actions [​](#public-actions) The example below demonstrates how to utilize Viem's `getLogs` Action with a `useQuery` Composable to create your own abstraction akin to a `useLogs` Composable. vue ### Wallet Actions [​](#wallet-actions) The example below demonstrates how to utilize Viem's `watchAsset` Action with a `useMutation` Composable to create your own abstraction akin to a `useWatchAsset` Composable. vue Private Key & Mnemonic Accounts [​](#private-key-mnemonic-accounts) -------------------------------------------------------------------- It is possible to utilize Viem's [Private Key & Mnemonic Accounts](https://viem.sh/docs/accounts/local.html) with Wagmi by explicitly passing through the account via the `account` argument on Wagmi Actions. vue INFO Wagmi currently does not support hoisting Private Key & Mnemonic Accounts to the top-level Wagmi Config – meaning you have to explicitly pass through the account to every Action. If you feel like this is a feature that should be added, please [open an discussion](https://github.com/wevm/wagmi/discussions/new?category=ideas) . --- # Viem | Wagmi Return to top Viem [​](#viem) ================ [Viem](https://viem.sh) is a low-level TypeScript Interface for Ethereum that enables developers to interact with the Ethereum blockchain, including: JSON-RPC API abstractions, Smart Contract interaction, wallet & signing implementations, coding/parsing utilities and more. **Wagmi Core** is essentially a wrapper over **Viem** that provides multi-chain functionality via [Wagmi Config](/core/api/createConfig) and automatic account management via [Connectors](/core/api/connectors) . Leveraging Viem Actions [​](#leveraging-viem-actions) ------------------------------------------------------ All of the core [Wagmi Actions](/core/api/actions) are friendly wrappers around [Viem Actions](https://viem.sh/docs/actions/public/introduction.html) that inject a multi-chain and connector aware [Wagmi Config](/core/api/createConfig) . There may be cases where you might want to dig deeper and utilize Viem Actions directly (maybe an Action doesn't exist in Wagmi yet). In these cases, you can import Viem Actions directly via `viem/actions` and plug in a Viem Client returned by the [`getClient` Action](/core/api/actions/getClient) . The example below demonstrates two different ways to utilize Viem Actions: 1. **Tree-shakable Actions (recommended):** Uses `getClient` (for public actions) and `getConnectorClient` (for wallet actions). 2. **Client Actions:** Uses `getPublicClient` (for public actions) and `getWalletClient` (for wallet actions). TIP It is highly recommended to use the **tree-shakable** method to ensure that you are only pulling modules you use, and keep your bundle size low. Tree-shakable ActionsClient Actions tsx // 1. Import modules. import { http, createConfig, getClient, getConnectorClient } from '@wagmi/core' import { base, mainnet, optimism, zora } from '@wagmi/core/chains' import { getLogs, watchAsset } from 'viem/actions' // 2. Set up a Wagmi Config export const config = createConfig({ chains: [base, mainnet, optimism, zora], transports: { [base.id]: http(), [mainnet.id]: http(), [optimism.id]: http(), [zora.id]: http(), }, }) // 3. Extract a Viem Client for the current active chain. const publicClient = getClient(config) const logs = await getLogs(publicClient, /* ... */) // 4. Extract a Viem Client for the current active chain & account. const walletClient = getConnectorClient(config) const success = await watchAsset(walletClient, /* ... */) tsx // 1. Import modules. import { http, createConfig, getPublicClient, getWalletClient } from '@wagmi/core' import { base, mainnet, optimism, zora } from '@wagmi/core/chains' // 2. Set up a Wagmi Config export const config = createConfig({ chains: [base, mainnet, optimism, zora], transports: { [base.id]: http(), [mainnet.id]: http(), [optimism.id]: http(), [zora.id]: http(), }, }) // 3. Extract a Viem Public Client for the current active chain. const publicClient = getPublicClient(config) const logs = await publicClient.getLogs(publicClient, /* ... */) // 4. Extract a Viem Wallet Client for the current active chain & account. const walletClient = getWalletClient(config) const success = await walletClient.watchAsset(walletClient, /* ... */) Multi-chain Viem Client [​](#multi-chain-viem-client) ------------------------------------------------------ The [Viem Client](https://viem.sh/docs/client) provides an interface to interact with an JSON-RPC Provider. By nature, JSON-RPC Providers are single-chain, so the Viem Client is designed to be instantiated with a single `chain`. As a result, setting up Viem to be multi-chain aware can get a bit verbose. The good news is that you can create a **"multi-chain Viem Client"** with **Wagmi** by utilizing [`createConfig`](/core/api/createConfig) and [`getClient`](/core/api/actions/getClient) . Wagmi UsageViem Usage tsx // 1. Import modules. import { http, createConfig, getClient, getConnectorClient } from '@wagmi/core' import { base, mainnet, optimism, zora } from '@wagmi/core/chains' import { getBlockNumber, sendTransaction } from 'viem/actions' // 2. Set up a Wagmi Config export const config = createConfig({ chains: [base, mainnet, optimism, zora], transports: { [base.id]: http(), [mainnet.id]: http(), [optimism.id]: http(), [zora.id]: http(), }, }) // 3. Extract a Viem Client for the current active chain. const publicClient = getClient(config) const blockNumber = await getBlockNumber(publicClient) // 4. Extract a Viem Client for the current active chain & account. const walletClient = getConnectorClient(config) const hash = await sendTransaction(walletClient, /* ... */) tsx // Manually set up Viem Clients without wagmi. Don't do this, it's only here // to demonstrate the amount of boilerplate required. import { createPublicClient, createWalletClient, http } from 'viem' import { base, mainnet, optimism, zora } from 'viem/chains' const publicClient = { base: createPublicClient({ chain: base, transport: http() }), mainnet: createPublicClient({ chain: mainnet, transport: http() }), optimism: createPublicClient({ chain: optimism, transport: http() }), zora: createPublicClient({ chain: zora, transport: http() }) } as const const walletClient = { base: createWalletClient({ chain: base, transport: custom(window.ethereum) }), mainnet: createWalletClient({ chain: mainnet, transport: custom(window.ethereum) }), optimism: createWalletClient({ chain: optimism, transport: custom(window.ethereum) }), zora: createWalletClient({ chain: zora, transport: custom(window.ethereum) }) } as const const blockNumber = await publicClient.mainnet.getBlockNumber() const hash = await walletClient.mainnet.sendTransaction(/* ... */) Private Key & Mnemonic Accounts [​](#private-key-mnemonic-accounts) -------------------------------------------------------------------- It is possible to utilize Viem's [Private Key & Mnemonic Accounts](https://viem.sh/docs/accounts/local.html) with Wagmi by explicitly passing through the account via the `account` argument on Wagmi Actions. tsx import { http, createConfig, sendTransaction } from '@wagmi/core' import { base, mainnet, optimism, zora } from '@wagmi/core/chains' import { parseEther } from 'viem' import { privateKeyToAccount } from 'viem/accounts' export const config = createConfig({ chains: [base, mainnet, optimism, zora], transports: { [base.id]: http(), [mainnet.id]: http(), [optimism.id]: http(), [zora.id]: http(), }, }) const account = privateKeyToAccount('0x...') const hash = await sendTransaction({ account, to: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC', value: parseEther('0.001') }) INFO Wagmi currently does not support hoisting Private Key & Mnemonic Accounts to the top-level Wagmi Config – meaning you have to explicitly pass through the account to every Action. If you feel like this is a feature that should be added, please [open a discussion](https://github.com/wevm/wagmi/discussions/new?category=ideas) . --- # Read from Contract | Wagmi Return to top Read from Contract [​](#read-from-contract) ============================================ The [`useReadContract` Hook](/react/api/hooks/useReadContract) allows you to read data on a smart contract, from a `view` or `pure` (read-only) function. They can only read the state of the contract, and cannot make any changes to it. Since read-only methods do not change the state of the contract, they do not require any gas to be executed, and can be called by any user without the need to pay for gas. The component below shows how to retrieve the token balance of an address from the [Wagmi Example](https://etherscan.io/token/0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2) contract read-contract.tsxcontracts.ts tsx import { useReadContract } from 'wagmi' import { wagmiContractConfig } from './contracts' function ReadContract() { const { data: balance } = useReadContract({ ...wagmiContractConfig, functionName: 'balanceOf', args: ['0x03A71968491d55603FFe1b11A9e23eF013f75bCF'], }) return (
Balance: {balance?.toString()}
) } ts export const wagmiContractConfig = { address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', abi: [\ {\ type: 'function',\ name: 'balanceOf',\ stateMutability: 'view',\ inputs: [{ name: 'account', type: 'address' }],\ outputs: [{ type: 'uint256' }],\ },\ {\ type: 'function',\ name: 'totalSupply',\ stateMutability: 'view',\ inputs: [],\ outputs: [{ name: 'supply', type: 'uint256' }],\ },\ ], } as const If `useReadContract` depends on another value (`address` in the example below), you can use the [`query.enabled`](/react/api/hooks/useReadContract#enabled) option to prevent the query from running until the dependency is ready. tsx const { data: balance } = useReadContract({ ...wagmiContractConfig, functionName: 'balanceOf', args: [address], query: { enabled: !!address, }, }) Loading & Error States [​](#loading-error-states) -------------------------------------------------- The [`useReadContract` Hook](/react/api/hooks/useReadContract) also returns loading & error states, which can be used to display a loading indicator while the data is being fetched, or an error message if contract execution reverts. read-contract.tsxread-contract.tsx (refetch)read-contract.tsx (invalidate) tsx import { type BaseError, useReadContract } from 'wagmi' function ReadContract() { const { data: balance, error, isPending } = useReadContract({ ...wagmiContractConfig, functionName: 'balanceOf', args: ['0x03A71968491d55603FFe1b11A9e23eF013f75bCF'], }) if (isPending) return
Loading...
if (error) return (
Error: {(error as BaseError).shortMessage || error.message}
) return (
Balance: {balance?.toString()}
) } Refetching On Blocks [​](#refetching-on-blocks) ------------------------------------------------ The [`useBlockNumber` Hook](/react/api/hooks/useBlockNumber) can be utilized to refetch or [invalidate](https://tanstack.com/query/latest/docs/framework/react/guides/query-invalidation) the contract data on a specific block interval. read-contract.tsx (refetch)read-contract.tsx (invalidate) tsx import { useEffect } from 'react' import { useBlockNumber, useReadContract } from 'wagmi' function ReadContract() { const { data: balance, refetch } = useReadContract({ ...wagmiContractConfig, functionName: 'balanceOf', args: ['0x03A71968491d55603FFe1b11A9e23eF013f75bCF'], }) const { data: blockNumber } = useBlockNumber({ watch: true }) useEffect(() => { // want to refetch every `n` block instead? use the modulo operator! // if (blockNumber % 5 === 0) refetch() // refetch every 5 blocks refetch() }, [blockNumber]) return (
Balance: {balance?.toString()}
) } tsx import { useQueryClient } from '@tanstack/react-query' import { useEffect } from 'react' import { useBlockNumber, useReadContract } from 'wagmi' function ReadContract() { const queryClient = useQueryClient() const { data: balance, refetch } = useReadContract({ ...wagmiContractConfig, functionName: 'balanceOf', args: ['0x03A71968491d55603FFe1b11A9e23eF013f75bCF'], }) const { data: blockNumber } = useBlockNumber({ watch: true }) useEffect(() => { // if `useReadContract` is in a different hook/component, // you can import `readContractQueryKey` from `'wagmi/query'` and // construct a one-off query key to use for invalidation queryClient.invalidateQueries({ queryKey }) }, [blockNumber, queryClient]) return (
Balance: {balance?.toString()}
) } Calling Multiple Functions [​](#calling-multiple-functions) ------------------------------------------------------------ We can use the [`useReadContract` Hook](/react/api/hooks/useReadContract) multiple times in a single component to call multiple functions on the same contract, but this ends up being hard to manage as the number of functions increases, especially when we also want to deal with loading & error states. Luckily, to make this easier, we can use the [`useReadContracts` Hook](/react/api/hooks/useReadContracts) to call multiple functions in a single call. read-contract.tsx tsx import { type BaseError, useReadContracts } from 'wagmi' function ReadContract() { const { data, error, isPending } = useReadContracts({ contracts: [{ \ ...wagmiContractConfig,\ functionName: 'balanceOf',\ args: ['0x03A71968491d55603FFe1b11A9e23eF013f75bCF'],\ }, { \ ...wagmiContractConfig, \ functionName: 'ownerOf', \ args: [69n], \ }, { \ ...wagmiContractConfig, \ functionName: 'totalSupply', \ }] }) const [balance, ownerOf, totalSupply] = data || [] if (isPending) return
Loading...
if (error) return (
Error: {(error as BaseError).shortMessage || error.message}
) return ( <>
Balance: {balance?.toString()}
Owner of Token 69: {ownerOf?.toString()}
Total Supply: {totalSupply?.toString()}
) } --- # Configuring CLI | Wagmi Return to top Configuring CLI [​](#configuring-cli) ====================================== When running `wagmi` from the command line, `@wagmi/cli` will automatically try to resolve a config file named `wagmi.config.js` or `wagmi.config.ts` inside the project root. The most basic config file looks like this: wagmi.config.js js export default { // config options } Note `@wagmi/cli` supports using ES modules syntax in the config file even if the project is not using native Node ESM, e.g. `"type": "module"` in package.json. In this case, the config file is auto pre-processed before load. You can also explicitly specify a config file to use with the `--config`/`-c` CLI option (resolved relative to the current directory): bash wagmi --config my-config.js To scaffold a config file quickly, check out the [`init`](/cli/api/commands/init) command. Config Intellisense [​](#config-intellisense) ---------------------------------------------- Since Wagmi CLI ships with TypeScript typings, you can use your editor's intellisense with [JSDoc](https://jsdoc.app) type hints: wagmi.config.js js /** @type {import('@wagmi/cli').Config} */ export default { // ... } Alternatively, you can use the `defineConfig` utility which should provide intellisense without the need for JSDoc annotations: wagmi.config.js js import { defineConfig } from '@wagmi/cli' export default defineConfig({ // ... }) Wagmi CLI also directly supports TypeScript config files. You can use `wagmi.config.ts` with the `defineConfig` helper as well. Conditional Config [​](#conditional-config) -------------------------------------------- If the config needs to conditionally determine options based on the environment, it can export a function instead: wagmi.config.js js export default defineConfig(() => { if (process.env.NODE_ENV === 'dev') { return { // dev specific config } } else { return { // production specific config } } }) Async Config [​](#async-config) -------------------------------- If the config needs to call async function, it can export a async function instead: wagmi.config.js js export default defineConfig(async () => { const data = await asyncFunction() return { // ... } }) This can be useful for resolving external resources from the network or filesystem that are required for configuration ahead of running a command. Array Config [​](#array-config) -------------------------------- The config can also be represented either as a pre-defined array or returned as an array from a function: wagmi.config.js js export default defineConfig([\ {\ // config 1\ },\ {\ // config 2\ },\ ]) Environment Variables [​](#environment-variables) -------------------------------------------------- Environmental Variables can be obtained from `process.env` as usual. Note that Wagmi CLI doesn't load `.env` files by default as the files to load can only be determined after evaluating the config. However, you can use the exported `loadEnv` utility to load the specific `.env` files if needed. wagmi.config.js js import { defineConfig, loadEnv } from '@wagmi/cli' export default defineConfig(() => { const env = loadEnv({ mode: process.env.NODE_ENV, envDir: process.cwd(), }) return { // ... } }) --- # Error Handling | Wagmi Return to top Error Handling [​](#error-handling) ==================================== The `error` property in Wagmi Composables is strongly typed with it's corresponding error type. This enables you to have granular precision with handling errors in your application. You can discriminate the error type by using the `name` property on the error object. index.vueconfig.ts vue ts import { http, createConfig } from '@wagmi/vue' import { mainnet, sepolia } from '@wagmi/vue/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) --- # Framework Adapters | Wagmi Return to top Framework Adapters [​](#framework-adapters) ============================================ Folks often ask if they can use Wagmi with other frameworks, like Svelte, Solid.js, and more. The short answer is — you already can! Wagmi Core is pure VanillaJS that you can use with any framework. For some, this answer is (understandably) unsatisfying as they want a tight integration between Wagmi Core and their favorite framework's reactivity system, e.g. what Wagmi is for React and Vue. Someday, we would love to support additional frameworks, but unfortunately the core team doesn't have time to build and support them in a high-quality way at the moment. This could change in the future with additional [sponsors](https://github.com/sponsors/wevm) , reshuffling of the roadmap, or if someone from the community wants to lead the effort. In the meantime, here are some tips on how to create tighter bonds between Wagmi Core and other frameworks. Dependency Injection [​](#dependency-injection) ------------------------------------------------ Once you create a Wagmi Config, you'll need to make sure your framework has access to it inside your higher-level functions (e.g. hooks for React, composables for Vue). For example, Wagmi uses [React Context](https://react.dev/learn/passing-data-deeply-with-context) to inject the Config into React Hooks and update it if it changes. This makes it so your users don't need to pass a Config object every time they use a hook. Reactivity Layer [​](#reactivity-layer) ---------------------------------------- All frameworks approach reactivity in a different way. To hook into your favorite frameworks, reactivity system, it's often helpful to see what other popular libraries for your framework are doing. The most important thing to hook up Wagmi Core with your framework is to make sure changes to the Wagmi Config are tracked. This enables behavior, like switching chains or connecting accounts, to propagate throughout your app and update state. Check out [`useAccount`](https://github.com/wevm/wagmi/blob/main/packages/react/src/hooks/useAccount.ts) , [`useChainId`](https://github.com/wevm/wagmi/blob/main/packages/react/src/hooks/useChainId.ts) , [`useClient`](https://github.com/wevm/wagmi/blob/main/packages/react/src/hooks/useClient.ts) , and [`useConnectorClient`](https://github.com/wevm/wagmi/blob/main/packages/react/src/hooks/useConnectorClient.ts) — versions of these for your framework are important to get right as they power a lot of internals. TanStack Query [​](#tanstack-query) ------------------------------------ Wagmi uses [TanStack Query](https://tanstack.com/query) to enable caching, deduplication, persistence, and more in React and Vue applications. Normally, you would need to find a similar library for your framework, but the good news is TanStack Query supports other frameworks! (Svelte, Solid, and Angular at the time of writing.) To get started with your framework, install and set up the related TanStack Query adapter. Next, import query keys/functions and mutation functions from the `'@wagmi/core/query'` entrypoint. You can plug these directly into your framework's TanStack Query adapter functions. If you are building a library, you'll also want to make sure that you wire up generics correctly so type-inference and safety work correctly. The best way to make sure you are doing this correctly, is to see how we do this for React with Wagmi by checking out the [source code](https://github.com/wevm/wagmi/tree/main/packages/react/src/hooks) . Testing [​](#testing) ---------------------- If you are building a library, you'll want to write tests. Wagmi uses [React Testing Library](https://testing-library.com/docs/react-testing-library/intro) to test hooks. [Testing Library](https://testing-library.com) also supports other frameworks, like Svelte, Solid, and more. You can take a look at how the React tests work and do something similar for your code. Proxy Exports [​](#proxy-exports) ---------------------------------- Wagmi proxies exports directly from Wagmi Core and [Viem](https://viem.sh) to make importing easier. You'll likely want to imitate this behavior for your framework. --- # Write to Contract | Wagmi Return to top Write to Contract [​](#write-to-contract) ========================================== The [`useWriteContract` Hook](/react/api/hooks/useWriteContract) allows you to mutate data on a smart contract, from a `payable` or `nonpayable` (write) function. These types of functions require gas to be executed, hence a transaction is broadcasted in order to change the state. In the guide below, we will teach you how to implement a "Mint NFT" form that takes in a dynamic argument (token ID) using Wagmi. The example below builds on the [Connect Wallet guide](/react/guides/connect-wallet) and uses the [useWriteContract](/react/api/hooks/useWriteContract) & [useWaitForTransaction](/react/api/hooks/useWaitForTransactionReceipt) hooks. If you have already completed the [Sending Transactions guide](/react/guides/send-transaction) , this guide will look very similar! That's because writing to a contract internally broadcasts & sends a transaction. Example [​](#example) ---------------------- Feel free to check out the example before moving on: Steps [​](#steps) ------------------ ### 1\. Connect Wallet [​](#_1-connect-wallet) Follow the [Connect Wallet guide](/react/guides/connect-wallet) guide to get this set up. ### 2\. Create a new component [​](#_2-create-a-new-component) Create your `MintNFT` component that will contain the Mint NFT logic. mint-nft.tsx tsx import * as React from 'react' export function MintNFT() { return (
) } ### 3\. Add a form handler [​](#_3-add-a-form-handler) Next, we will need to add a handler to the form that will send the transaction when the user hits "Mint". This will be a basic handler in this step. mint-nft.tsx tsx import * as React from 'react' export function MintNFT() { async function submit(e: React.FormEvent) { e.preventDefault() const formData = new FormData(e.target as HTMLFormElement) const tokenId = formData.get('tokenId') as string } return (
) } ### 4\. Hook up the `useWriteContract` Hook [​](#_4-hook-up-the-usewritecontract-hook) Now that we have the form handler, we can hook up the [`useWriteContract` Hook](/react/api/hooks/useWriteContract) to send the transaction. mint-nft.tsxabi.ts tsx import * as React from 'react' import { useWriteContract } from 'wagmi' import { abi } from './abi' export function MintNFT() { const { data: hash, writeContract } = useWriteContract() async function submit(e: React.FormEvent) { e.preventDefault() const formData = new FormData(e.target as HTMLFormElement) const tokenId = formData.get('tokenId') as string writeContract({ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', abi, functionName: 'mint', args: [BigInt(tokenId)], }) } return (
{hash &&
Transaction Hash: {hash}
}
) } ts export const abi = [\ {\ name: 'mint',\ type: 'function',\ stateMutability: 'nonpayable',\ inputs: [{ internalType: 'uint32', name: 'tokenId', type: 'uint32' }],\ outputs: [],\ },\ ] as const ### 5\. Add loading state (optional) [​](#_5-add-loading-state-optional) We can optionally add a loading state to the "Mint" button while we are waiting confirmation from the user's wallet. mint-nft.tsxabi.ts tsx import * as React from 'react' import { useWriteContract } from 'wagmi' import { abi } from './abi' export function MintNFT() { const { data: hash, isPending, writeContract } = useWriteContract() async function submit(e: React.FormEvent) { e.preventDefault() const formData = new FormData(e.target as HTMLFormElement) const tokenId = formData.get('tokenId') as string writeContract({ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', abi, functionName: 'mint', args: [BigInt(tokenId)], }) } return (
{hash &&
Transaction Hash: {hash}
}
) } ts export const abi = [\ {\ name: 'mint',\ type: 'function',\ stateMutability: 'nonpayable',\ inputs: [{ internalType: 'uint32', name: 'tokenId', type: 'uint32' }],\ outputs: [],\ },\ ] as const ### 6\. Wait for transaction receipt (optional) [​](#_6-wait-for-transaction-receipt-optional) We can also display the transaction confirmation status to the user by using the [`useWaitForTransactionReceipt` Hook](/react/api/hooks/useWaitForTransactionReceipt) . mint-nft.tsxabi.ts tsx import * as React from 'react' import { useWaitForTransactionReceipt, useWriteContract } from 'wagmi' import { abi } from './abi' export function MintNFT() { const { data: hash, isPending, writeContract } = useWriteContract() async function submit(e: React.FormEvent) { e.preventDefault() const formData = new FormData(e.target as HTMLFormElement) const tokenId = formData.get('tokenId') as string writeContract({ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', abi, functionName: 'mint', args: [BigInt(tokenId)], }) } const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ hash, }) return (
{hash &&
Transaction Hash: {hash}
} {isConfirming &&
Waiting for confirmation...
} {isConfirmed &&
Transaction confirmed.
}
) } ts export const abi = [\ {\ name: 'mint',\ type: 'function',\ stateMutability: 'nonpayable',\ inputs: [{ internalType: 'uint32', name: 'tokenId', type: 'uint32' }],\ outputs: [],\ },\ ] as const ### 7\. Handle errors (optional) [​](#_7-handle-errors-optional) If the user rejects the transaction, or the contract reverts, we can display an error message to the user. mint-nft.tsxabi.ts tsx import * as React from 'react' import { type BaseError, useWaitForTransactionReceipt, useWriteContract } from 'wagmi' import { abi } from './abi' export function MintNFT() { const { data: hash, error, isPending, writeContract } = useWriteContract() async function submit(e: React.FormEvent) { e.preventDefault() const formData = new FormData(e.target as HTMLFormElement) const tokenId = formData.get('tokenId') as string writeContract({ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', abi, functionName: 'mint', args: [BigInt(tokenId)], }) } const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ hash, }) return (
{hash &&
Transaction Hash: {hash}
} {isConfirming &&
Waiting for confirmation...
} {isConfirmed &&
Transaction confirmed.
} {error && (
Error: {(error as BaseError).shortMessage || error.message}
)}
) } ts export const abi = [\ {\ name: 'mint',\ type: 'function',\ stateMutability: 'nonpayable',\ inputs: [{ internalType: 'uint32', name: 'tokenId', type: 'uint32' }],\ outputs: [],\ },\ ] as const ### 8\. Wire it up! [​](#_8-wire-it-up) Finally, we can wire up our Mint NFT component to our application's entrypoint. app.tsxmint-nft.tsxabi.tsconfig.ts tsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { WagmiProvider, useAccount } from 'wagmi' import { config } from './config' import { MintNft } from './mint-nft' const queryClient = new QueryClient() function App() { return ( ) } tsx import * as React from 'react' import { type BaseError, useWaitForTransactionReceipt, useWriteContract } from 'wagmi' import { abi } from './abi' export function MintNFT() { const { data: hash, error, isPending, writeContract } = useWriteContract() async function submit(e: React.FormEvent) { e.preventDefault() const formData = new FormData(e.target as HTMLFormElement) const tokenId = formData.get('tokenId') as string writeContract({ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', abi, functionName: 'mint', args: [BigInt(tokenId)], }) } const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ hash, }) return (
{hash &&
Transaction Hash: {hash}
} {isConfirming &&
Waiting for confirmation...
} {isConfirmed &&
Transaction confirmed.
} {error && (
Error: {(error as BaseError).shortMessage || error.message}
)}
) } ts export const abi = [\ {\ name: 'mint',\ type: 'function',\ stateMutability: 'nonpayable',\ inputs: [{ internalType: 'uint32', name: 'tokenId', type: 'uint32' }],\ outputs: [],\ },\ ] as const tsx import { http, createConfig } from 'wagmi' import { base, mainnet, optimism } from 'wagmi/chains' import { injected, metaMask, safe, walletConnect } from 'wagmi/connectors' const projectId = '' export const config = createConfig({ chains: [mainnet, base], connectors: [\ injected(),\ walletConnect({ projectId }),\ metaMask(),\ safe(),\ ], transports: { [mainnet.id]: http(), [base.id]: http(), }, }) [See the Example.](#example) --- # Config Options | Wagmi Return to top Config Options [​](#config-options) ==================================== Configuration options for Wagmi CLI. contracts [​](#contracts) -------------------------- `ContractConfig[] | undefined` Array of contracts to use when running [commands](/cli/api/commands) . `abi` and `name` are required, all other properties are optional. ### address [​](#address) `Address | Record | undefined` Contract address or addresses. Accepts an object `{ [chainId]: address }` for targeting specific chains. wagmi.config.ts ts export default { out: 'src/generated.ts', contracts: [\ {\ abi: […],\ address: '0x…',\ name: 'MyCoolContract',\ },\ {\ abi: […],\ address: {\ 1: '0xfoo…',\ 5: '0xbar…',\ },\ name: 'MyCoolMultichainContract'\ }\ ], } ### abi [​](#abi) `Abi` ABI for contract. Used by [plugins](/cli/api/plugins) to generate code base on properties. wagmi.config.ts ts export default { out: 'src/generated.ts', contracts: [\ {\ abi: […],\ name: 'MyCoolContract'\ },\ ], } ### name [​](#name) `string` Name of contract. Must be unique. Used by [plugins](/cli/api/plugins) to name generated code. wagmi.config.ts ts export default { out: 'src/generated.ts', contracts: [\ {\ abi: […],\ name: 'MyCoolContract'\ },\ ], } out [​](#out) -------------- `string` Path to output generated code. Must be unique per config. Use an [Array Config](/cli/config/configuring-cli#array-config) for multiple outputs. wagmi.config.ts ts export default { out: 'src/generated.ts', contracts: [\ {\ abi: […],\ name: 'MyCoolContract'\ },\ ], } plugins [​](#plugins) ---------------------- `Plugin[] | undefined` Plugins to use and their configuration. Wagmi CLI has multiple [built-in plugins](/cli/api/plugins) that are used to manage ABIs, generate code, etc. wagmi.config.ts ts import { etherscan, react } from '@wagmi/cli/plugins' export default { out: 'src/generated.js', plugins: [\ etherscan({\ apiKey: process.env.ETHERSCAN_API_KEY,\ chainId: 5,\ contracts: [\ {\ name: 'EnsRegistry',\ address: {\ 1: '0x314159265dd8dbb310642f98f50c066173c1259b',\ 5: '0x112234455c3a32fd11230c42e7bccd4a84e02010',\ },\ },\ ],\ }),\ react(),\ ], } --- # Error Handling | Wagmi Return to top Error Handling [​](#error-handling) ==================================== Every module in Wagmi Core exports an accompanying error type which you can use to strongly type your `catch` statements. These types come in the form of `ErrorType`. For example, the `getBlockNumber` action exports a `GetBlockNumberErrorType` type. Unfortunately, [TypeScript doesn't have an abstraction for typed exceptions](https://github.com/microsoft/TypeScript/issues/13219) , so the most pragmatic & vanilla approach would be to explicitly cast error types in the `catch` statement. index.tsxconfig.ts tsx import { type GetBlockNumberErrorType, getBlockNumber } from '@wagmi/core' import { config } from './config' try { const blockNumber = await getBlockNumber(config) } catch (e) { const error = e as GetBlockNumberErrorType error.name // ^? (property) name: "Error" | "ChainDisconnectedError" | "HttpRequestError" | "InternalRpcError" | "InvalidInputRpcError" | "InvalidParamsRpcError" | "InvalidRequestRpcError" | "JsonRpcVersionUnsupportedError" | ... 16 more ... | "WebSocketRequestError" if (error.name === 'InternalRpcError') error.code // ^? (property) code: -32603 if (error.name === 'HttpRequestError') error.headers // ^? (property) headers: Headers error.status // ^? (property) status: number } ts import { http, createConfig } from '@wagmi/core' import { mainnet, sepolia } from '@wagmi/core/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) TIP If you are using [Wagmi Hooks](/react/api/hooks) , errors are [already strongly typed](/react/guides/error-handling) via the `error` property. --- # Chain Properties | Wagmi Return to top Chain Properties [​](#chain-properties) ======================================== Some chains support additional properties related to blocks and transactions. This is powered by Viem's [formatters](https://viem.sh/docs/clients/chains.html#formatters) and [serializers](https://viem.sh/docs/clients/chains.html#serializers) . For example, Celo, ZkSync, OP Stack chains support all support additional properties. In order to use these properties in a type-safe way, there are a few things you should be aware of. TIP Make sure you follow the TypeScript guide's [Config Types](/vue/typescript#config-types) section before moving on. The easiest way to do this is to use [Declaration Merging](/vue/typescript#declaration-merging) to "register" your `config` globally with TypeScript. ts import { http, createConfig } from '@wagmi/vue' import { base, celo, mainnet } from '@wagmi/vue/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) declare module '@wagmi/vue' { interface Register { config: typeof config } } Narrowing Parameters [​](#narrowing-parameters) ------------------------------------------------ Once your Config is registered with TypeScript, you are ready to access chain-specific properties! For example, Celo's `feeCurrency` is available. index.tsxconfig.ts ts import { parseEther } from 'viem' import { useSimulateContract } from '@wagmi/vue' const result = useSimulateContract({ to: '0xd2135CfB216b74109775236E36d4b433F1DF507B', value: parseEther('0.01'), feeCurrency: '0x…', }) ts import { http, createConfig } from '@wagmi/vue' import { base, celo, mainnet } from '@wagmi/vue/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) declare module '@wagmi/vue' { interface Register { config: typeof config } } This is great, but if you have multiple chains that support additional properties, your autocomplete could be overwhelmed with all of them. By setting the `chainId` property to a specific value (e.g. `celo.id`), you can narrow parameters to a single chain. index.tsxconfig.ts ts import { parseEther } from 'viem' import { useSimulateContract } from '@wagmi/vue' import { celo } from '@wagmi/vue/chains' const result = useSimulateContract({ to: '0xd2135CfB216b74109775236E36d4b433F1DF507B', value: parseEther('0.01'), chainId: celo.id, feeCurrency: '0x…', // ^? (property) feeCurrency?: `0x${string}` | undefined }) ts import { http, createConfig } from '@wagmi/vue' import { base, celo, mainnet } from '@wagmi/vue/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) declare module '@wagmi/vue' { interface Register { config: typeof config } } Narrowing Return Types [​](#narrowing-return-types) ---------------------------------------------------- Return types can also have chain-specific properties attached to them. There are a couple approaches for extracting these properties. ### `chainId` Parameter [​](#chainid-parameter) Not only can you use the `chainId` parameter to [narrow parameters](#narrowing-parameters) , you can also use it to narrow the return type. index.tsxconfig.ts ts import { useWaitForTransactionReceipt } from '@wagmi/vue' import { zkSync } from '@wagmi/vue/chains' const { data } = useWaitForTransactionReceipt({ chainId: zkSync.id, hash: '0x16854fcdd0219cacf5aec5e4eb2154dac9e406578a1510a6fc48bd0b67e69ea9', }) data?.logs // ^? (property) logs: ZkSyncLog[] | undefined ts import { http, createConfig } from '@wagmi/vue' import { base, celo, mainnet } from '@wagmi/vue/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) declare module '@wagmi/vue' { interface Register { config: typeof config } } ### `chainId` Data Property [​](#chainid-data-property) Wagmi internally will set a `chainId` property on return types that you can use to narrow results. The `chainId` is determined from the `chainId` parameter or global state (e.g. connector). You can use this property to help TypeScript narrow the type. index.tsxconfig.ts ts import { useWaitForTransactionReceipt } from '@wagmi/vue' import { zkSync } from '@wagmi/vue/chains' const { data } = useWaitForTransactionReceipt({ hash: '0x16854fcdd0219cacf5aec5e4eb2154dac9e406578a1510a6fc48bd0b67e69ea9', }) if (data?.chainId === zkSync.id) { data?.logs // ^? (property) logs: ZkSyncLog[] | undefined } ts import { http, createConfig } from '@wagmi/vue' import { base, celo, mainnet } from '@wagmi/vue/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) declare module '@wagmi/vue' { interface Register { config: typeof config } } Troubleshooting [​](#troubleshooting) -------------------------------------- If chain properties aren't working, make sure [TypeScript](/vue/guides/faq#type-inference-doesn-t-work) is configured correctly. Not all chains have additional properties, to check which ones do, see the [Viem repo](https://github.com/wevm/viem/tree/main/src/chains) (chains that have a top-level directory under [`src/chains`](https://github.com/wevm/viem/tree/main/src/chains) support additional properties). --- # FAQ / Troubleshooting | Wagmi Return to top FAQ / Troubleshooting [​](#faq-troubleshooting) ================================================ Collection of frequently asked questions with ideas on how to troubleshoot and resolve them. Type inference doesn't work [​](#type-inference-doesn-t-work) -------------------------------------------------------------- * Check that you set up TypeScript correctly with `"strict": true` in your `tsconfig.json` ([TypeScript docs](/react/typescript#requirements) ) * Check that you [const-asserted any ABIs or Typed Data](/react/typescript#const-assert-abis-typed-data) you are using. * Restart your language server or IDE, and check for type errors in your code. My wallet doesn't work [​](#my-wallet-doesn-t-work) ---------------------------------------------------- If you run into issues with a specific wallet, try another before opening up an issue. There are many different wallets and it's likely that the issue is with the wallet itself, not Wagmi. For example, if you are using Wallet X and sending a transaction doesn't work, try Wallet Y and see if it works. `BigInt` Serialization [​](#bigint-serialization) -------------------------------------------------- Using native `BigInt` with `JSON.stringify` will raise a `TypeError` as [`BigInt` values are not serializable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#use_within_json) . There are two techniques to mitigate this: #### Lossless serialization [​](#lossless-serialization) Lossless serialization means that `BigInt` will be converted to a format that can be deserialized later (e.g. `69420n` → `"#bigint.69420"`). The trade-off is that these values are not human-readable and are not intended to be displayed to the user. Lossless serialization can be achieved with wagmi's [`serialize`](/react/api/utilities/serialize) and [`deserialize`](/react/api/utilities/deserialize) utilities. tsx import { serialize, deserialize } from 'wagmi' const serialized = serialize({ value: 69420n }) // '{"value":"#bigint.69420"}' const deserialized = deserialize(serialized) // { value: 69420n } #### Lossy serialization [​](#lossy-serialization) Lossy serialization means that the `BigInt` will be converted to a normal display string (e.g. `69420n` → `'69420'`). The trade-off is that you will not be able to deserialize the `BigInt` with `JSON.parse` as it can not distinguish between a normal string and a `BigInt`. This method can be achieved by modifying `JSON.stringify` to include a BigInt `replacer`: tsx const replacer = (key, value) => typeof value === 'bigint' ? value.toString() : value JSON.stringify({ value: 69420n }, replacer) // '{"value":"69420"}' How do I support the project? [​](#how-do-i-support-the-project) ----------------------------------------------------------------- Wagmi is an open source software project and free to use. If you enjoy using Wagmi or would like to support Wagmi development, you can: * [Become a sponsor on GitHub](https://github.com/sponsors/wevm) * Send us crypto * Mainnet: 0x4557B18E779944BFE9d78A672452331C186a9f48 * Multichain: 0xd2135CfB216b74109775236E36d4b433F1DF507B * [Become a supporter on Drips](https://www.drips.network/app/projects/github/wevm/wagmi) If you use Wagmi at work, consider asking your company to sponsor Wagmi. This may not be easy, but **business sponsorships typically make a much larger impact on the sustainability of OSS projects** than individual donations, so you will help us much more if you succeed. Is Wagmi production ready? [​](#is-wagmi-production-ready) ----------------------------------------------------------- Yes. Wagmi is very stable and is used in production by thousands of organizations, like [Stripe](https://stripe.com) , [Shopify](https://shopify.com) , [Coinbase](https://coinbase.com) , [Uniswap](https://uniswap.org) , [ENS](https://ens.domains) , [Optimism](https://optimism.com) . Is Wagmi strict with semver? [​](#is-wagmi-strict-with-semver) --------------------------------------------------------------- Yes, Wagmi is very strict with [semantic versioning](https://semver.org) and we will never introduce breaking changes to the runtime API in a minor version bump. For exported types, we try our best to not introduce breaking changes in non-major versions, however, [TypeScript doesn't follow semver](https://www.learningtypescript.com/articles/why-typescript-doesnt-follow-strict-semantic-versioning) and often introduces breaking changes in minor releases that can cause Wagmi type issues. See the [TypeScript docs](/react/typescript#requirements) for more information. How can I contribute to Wagmi? [​](#how-can-i-contribute-to-wagmi) ------------------------------------------------------------------- The Wagmi team accepts all sorts of contributions. Check out the [Contributing](/dev/contributing) guide to get started. If you are interested in adding a new connector to Wagmi, check out the [Creating Connectors](/dev/creating-connectors) guide. Anything else you want to know? [​](#anything-else-you-want-to-know) --------------------------------------------------------------------- Please create a new [GitHub Discussion thread](https://github.com/wevm/wagmi) . You're also free to suggest changes to this or any other page on the site using the "Suggest changes to this page" button at the bottom of the page. How does Wagmi work? [​](#how-does-wagmi-work) ----------------------------------------------- Until there's a more in-depth write-up about Wagmi internals, here is the gist: * Wagmi is essentially a wrapper around [Viem](https://viem.sh) and TanStack Query that adds connector and multichain support. * [Connectors](/react/api/connectors) allow Wagmi and Ethereum accounts to communicate with each other. * The Wagmi [`Config`](/react/api/createConfig#config) manages connections established between Wagmi and Connectors, as well as some global state. [Connections](/react/api/createConfig#connection) come with one or more addresses and a chain ID. * If there are connections, the Wagmi `Config` listens for connection changes and updates the [`chainId`](/react/api/createConfig#chainid) based on the ["current" connection](/react/api/createConfig#current) . (The Wagmi `Config` can have [many connections established](/react/api/createConfig#connections) at once, but only one connection can be the "current" connection. Usually this is the connection from the last connector that is connected, but can change based on event emitted from other connectors or through the [`useSwitchAccount`](/react/api/hooks/useSwitchAccount) hook and [`switchAccount`](/core/api/actions/switchAccount) action.) * If there are no connections, the Wagmi `Config` defaults the global state `chainId` to the first chain it was created with or last established connection. * The global `chainId` can be changed directly using the [`useSwitchChain`](/react/api/hooks/useSwitchChain) hook and [`switchChain`](/core/api/actions/switchChain) action. This works when there are no connections as well as for most connectors (not all connectors support chain switching). * Wagmi uses the global `chainId` (from the "current" connection or global state) to internally create Viem Client's, which are used by hooks and actions. * Hooks are constructed by TanStack Query options helpers, exported by the `'@wagmi/core/query'` entrypoint, and some additional code to wire up type parameters, hook into React Context, etc. * There are three types of hooks: query hooks, mutation hooks, and config hooks. Query hooks, like [`useCall`](/react/api/hooks/useCall) , generally read blockchain state and mutation hooks, like [`useSendTransaction`](/react/api/hooks/useSendTransaction) , usually change state through sending transactions via the "current" connection. Config hooks are for getting data from and managing the Wagmi `Config` instance, e.g. [`useChainId`](/react/api/hooks/useChainId) and `useSwitchAccount`. Query and mutation hooks usually have corresponding [Viem actions.](https://viem.sh) --- # Commands | Wagmi Return to top Commands [​](#commands) ======================== Available Commands [​](#available-commands) -------------------------------------------- * [`init`](/cli/api/commands/init) Creates configuration file. * [`generate`](/cli/api/commands/generate) Generates code based on configuration, using `contracts` and `plugins`. Display Info [​](#display-info) -------------------------------- ### `-h`, `--help` [​](#h-help) Show help message when `-h`, `--help` flags appear. pnpmnpmyarnbun bash pnpm wagmi --help bash npx wagmi --help bash yarn wagmi --help bash bun wagmi --help ### `-v`, `--version` [​](#v-version) Show version number when `-v`, `--version` flags appear. pnpmnpmyarnbun bash pnpm wagmi --version bash npx wagmi --version bash yarn wagmi --version bash bun wagmi --version --- # SSR | Wagmi Return to top SSR [​](#ssr) ============== Wagmi uses client-only external stores (such as `localStorage` and `mipd`) to show the user the most relevant data as quickly as possible on first render. However, the caveat of using these external client stores is that frameworks which incorporate SSR (such as Next.js) will throw hydration warnings on the client when it identifies mismatches between the server-rendered HTML and the client-rendered HTML. To stop this from happening, you can toggle on the [`ssr`](/vue/api/createConfig#ssr) property in the Wagmi Config. tsx import { createConfig, http } from '@wagmi/vue' import { mainnet, sepolia } from '@wagmi/vue/chains' const config = createConfig({ chains: [mainnet, sepolia], ssr: true, transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) Turning on the `ssr` property means that content from the external stores will be hydrated on the client after the initial mount. Persistence using Cookies [​](#persistence-using-cookies) ---------------------------------------------------------- As a result of turning on the `ssr` property, external persistent stores like `localStorage` will be hydrated on the client **after the initial mount**. This means that you will still see a flash of "empty" data on the client (e.g. a `"disconnected"` account instead of a `"reconnecting"` account, or an empty address instead of the last connected address) until after the first mount, when the store hydrates. In order to persist data between the server and the client, you can use cookies. ### 1\. Set up cookie storage [​](#_1-set-up-cookie-storage) First, we will set up cookie storage in the Wagmi Config. tsx import { createConfig, http, cookieStorage, createStorage } from '@wagmi/vue' import { mainnet, sepolia } from '@wagmi/vue/chains' export const config = createConfig({ chains: [mainnet, sepolia], ssr: true, storage: createStorage({ storage: cookieStorage, }), transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) ### 2\. Hydrate the cookie [​](#_2-hydrate-the-cookie) Next, we will need to add some mechanisms to hydrate the stored cookie in Wagmi. #### Nuxt.js [​](#nuxt-js) Would you like to contribute this content? Feel free to [open a Pull Request](https://github.com/wevm/wagmi/pulls) ! #### Vanilla SSR [​](#vanilla-ssr) Would you like to contribute this content? Feel free to [open a Pull Request](https://github.com/wevm/wagmi/pulls) ! --- # Ethers.js Adapters | Wagmi Return to top Ethers.js Adapters [​](#ethers-js-adapters) ============================================ It is recommended for projects to migrate to [Viem](https://viem.sh) when using Wagmi, but there are some cases where you might still need to use [Ethers.js](https://ethers.org) in your project: * You may want to **incrementally migrate** Ethers.js usage to Viem * Some **third-party libraries & SDKs** may only support Ethers.js * Personal preference We have provided reference implementations for Viem → Ethers.js adapters that you can copy + paste in your project. Client → Provider [​](#client-→-provider) ------------------------------------------ ### Reference Implementation [​](#reference-implementation) Copy the following reference implementation into a file of your choice: Ethers v5Ethers v6 ts import { type Config, getClient } from '@wagmi/core' import { providers } from 'ethers' import type { Client, Chain, Transport } from 'viem' export function clientToProvider(client: Client) { const { chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } if (transport.type === 'fallback') return new providers.FallbackProvider( (transport.transports as ReturnType[]).map( ({ value }) => new providers.JsonRpcProvider(value?.url, network), ), ) return new providers.JsonRpcProvider(transport.url, network) } /** Action to convert a viem Public Client to an ethers.js Provider. */ export function getEthersProvider( config: Config, { chainId }: { chainId?: number } = {}, ) { const client = getClient(config, { chainId }) if (!client) return return clientToProvider(client) } ts import { type Config, getClient } from '@wagmi/core' import { FallbackProvider, JsonRpcProvider } from 'ethers' import type { Client, Chain, Transport } from 'viem' export function clientToProvider(client: Client) { const { chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } if (transport.type === 'fallback') { const providers = (transport.transports as ReturnType[]).map( ({ value }) => new JsonRpcProvider(value?.url, network), ) if (providers.length === 1) return providers[0] return new FallbackProvider(providers) } return new JsonRpcProvider(transport.url, network) } /** Action to convert a viem Client to an ethers.js Provider. */ export function getEthersProvider( config: Config, { chainId }: { chainId?: number } = {}, ) { const client = getClient(config, { chainId }) if (!client) return return clientToProvider(client) } ### Usage [​](#usage) Now you can use the `getEthersProvider` function in your components: example.tsethers.ts (Ethers v5)ethers.ts (Ethers v6) ts import { getEthersProvider } from './ethers' import { config } from './config' function example() { const provider = getEthersProvider(config) ... } ts import { type Config, getClient } from '@wagmi/core' import { providers } from 'ethers' import type { Client, Chain, Transport } from 'viem' export function clientToProvider(client: Client) { const { chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } if (transport.type === 'fallback') return new providers.FallbackProvider( (transport.transports as ReturnType[]).map( ({ value }) => new providers.JsonRpcProvider(value?.url, network), ), ) return new providers.JsonRpcProvider(transport.url, network) } /** Action to convert a viem Public Client to an ethers.js Provider. */ export function getEthersProvider( config: Config, { chainId }: { chainId?: number } = {}, ) { const client = getClient(config, { chainId }) if (!client) return return clientToProvider(client) } ts import { type Config, getClient } from '@wagmi/core' import { FallbackProvider, JsonRpcProvider } from 'ethers' import type { Client, Chain, Transport } from 'viem' export function clientToProvider(client: Client) { const { chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } if (transport.type === 'fallback') { const providers = (transport.transports as ReturnType[]).map( ({ value }) => new JsonRpcProvider(value?.url, network), ) if (providers.length === 1) return providers[0] return new FallbackProvider(providers) } return new JsonRpcProvider(transport.url, network) } /** Action to convert a viem Client to an ethers.js Provider. */ export function getEthersProvider( config: Config, { chainId }: { chainId?: number } = {}, ) { const client = getClient(config, { chainId }) if (!client) return return clientToProvider(client) } Connector Client → Signer [​](#connector-client-→-signer) ---------------------------------------------------------- ### Reference Implementation [​](#reference-implementation-1) Copy the following reference implementation into a file of your choice: Ethers v5Ethers v6 ts import { Config, getConnectorClient } from '@wagmi/core' import { providers } from 'ethers' import type { Account, Chain, Client, Transport } from 'viem' export function clientToSigner(client: Client) { const { account, chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } const provider = new providers.Web3Provider(transport, network) const signer = provider.getSigner(account.address) return signer } /** Action to convert a Viem Client to an ethers.js Signer. */ export async function getEthersSigner( config: Config, { chainId }: { chainId?: number } = {}, ) { const client = await getConnectorClient(config, { chainId }) return clientToSigner(client) } ts import { Config, getConnectorClient } from '@wagmi/core' import { BrowserProvider, JsonRpcSigner } from 'ethers' import type { Account, Chain, Client, Transport } from 'viem' export function clientToSigner(client: Client) { const { account, chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } const provider = new BrowserProvider(transport, network) const signer = new JsonRpcSigner(provider, account.address) return signer } /** Action to convert a viem Wallet Client to an ethers.js Signer. */ export async function getEthersSigner( config: Config, { chainId }: { chainId?: number } = {}, ) { const client = await getConnectorClient(config, { chainId }) return clientToSigner(client) } ### Usage [​](#usage-1) Now you can use the `getEthersSigner` function in your components: example.tsethers.ts (Ethers v5)ethers.ts (Ethers v6) ts import { getEthersSigner } from './ethers' import { config } from './config' function example() { const provider = getEthersSigner(config) ... } ts import { Config, getConnectorClient } from '@wagmi/core' import { providers } from 'ethers' import type { Account, Chain, Client, Transport } from 'viem' export function clientToSigner(client: Client) { const { account, chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } const provider = new providers.Web3Provider(transport, network) const signer = provider.getSigner(account.address) return signer } /** Action to convert a Viem Client to an ethers.js Signer. */ export async function getEthersSigner( config: Config, { chainId }: { chainId?: number } = {}, ) { const client = await getConnectorClient(config, { chainId }) return clientToSigner(client) } ts import { Config, getConnectorClient } from '@wagmi/core' import { BrowserProvider, JsonRpcSigner } from 'ethers' import type { Account, Chain, Client, Transport } from 'viem' export function clientToSigner(client: Client) { const { account, chain, transport } = client const network = { chainId: chain.id, name: chain.name, ensAddress: chain.contracts?.ensRegistry?.address, } const provider = new BrowserProvider(transport, network) const signer = new JsonRpcSigner(provider, account.address) return signer } /** Action to convert a viem Wallet Client to an ethers.js Signer. */ export async function getEthersSigner( config: Config, { chainId }: { chainId?: number } = {}, ) { const client = await getConnectorClient(config, { chainId }) return clientToSigner(client) } --- # generate | Wagmi Return to top generate [​](#generate) ======================== Generates code based on configuration, using `contracts` and `plugins`. Usage [​](#usage) ------------------ bash wagmi generate Options [​](#options) ---------------------- ### \-c, --config [​](#c-config-path) `string` Path to config file. bash wagmi generate --config wagmi.config.ts ### \-r, --root [​](#r-root-path) `string` Root path to resolve config from. bash wagmi generate --root path/to/root ### \-w, --watch [​](#w-watch) `boolean` Watch for changes (for plugins that support watch mode). bash wagmi generate --watch ### \-h, --help [​](#h-help) Displays help message. bash wagmi generate --help --- # Migrate from v1 to v2 | Wagmi Return to top Migrate from v1 to v2 [​](#migrate-from-v1-to-v2) ================================================== Overview [​](#overview) ------------------------ Wagmi v2 redesigns the core APIs to mesh better with [Viem](https://viem.sh) and [TanStack Query](https://tanstack.com/query/v5/docs/react) . This major version transforms Wagmi into a light wrapper around these libraries, sprinkling in multichain support and account management. As such, there are some breaking changes and deprecations to be aware of outlined in this guide. To get started, install the latest version of Wagmi and it's required peer dependencies. pnpmnpmyarnbun bash pnpm add wagmi viem@2.x @tanstack/react-query bash npm install wagmi viem@2.x @tanstack/react-query bash yarn add wagmi viem@2.x @tanstack/react-query bash bun add wagmi viem@2.x @tanstack/react-query Wagmi v2 should be the last major version that will have this many actionable breaking changes. Moving forward after Wagmi v2, new functionality will be opt-in with old functionality being deprecated alongside the new features. This means upgrading to the latest major versions will not require immediate changes. Not ready to migrate yet? The Wagmi v1 docs are still available at [1.x.wagmi.sh/react](https://1.x.wagmi.sh/react) . Dependencies [​](#dependencies) -------------------------------- ### Moved TanStack Query to peer dependencies [​](#moved-tanstack-query-to-peer-dependencies) Wagmi uses [TanStack Query](https://tanstack.com/query/v5/docs/react) to manage async state, handling requests, caching, and more. With Wagmi v1, TanStack Query was an internal implementation detail. With Wagmi v2, TanStack Query is a peer dependency. A lot of Wagmi users also use TanStack Query in their apps so making it a peer dependency gives them more control and removes some custom Wagmi code internally. If you don't normally use TanStack Query, all you need to do is set it up and mostly forget about it (we'll provide guidance around version updates). app.tsxconfig.ts tsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { WagmiProvider } from 'wagmi' import { config } from './config' const queryClient = new QueryClient() function App() { return ( {/** ... */} ) } ts import { http, createConfig } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) For more information on setting up TanStack Query for Wagmi, follow the [Getting Started docs](/react/getting-started#setup-tanstack-query) . If you want to set up persistence for your query cache (default behavior before Wagmi v2), check out the [TanStack Query docs](https://tanstack.com/query/v5/docs/react/plugins/persistQueryClient#usage-with-react) . ### Dropped CommonJS support [​](#dropped-commonjs-support) Wagmi v2 no longer publishes a separate `cjs` tag since very few people use this tag and ESM is the future. See [Sindre Sorhus' guide](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) for more info about switching to ESM. Hooks [​](#hooks) ------------------ ### Removed mutation setup arguments [​](#removed-mutation-setup-arguments) Mutation hooks are hooks that change network or application state, sign data, or perform write operations through mutation functions. With Wagmi v1, you could pass arguments directly to these hooks instead of using them with their mutation functions. For example: ts // Wagmi v1 const { signMessage } = useSignMessage({ message: 'foo bar baz', }) With Wagmi v2, you must pass arguments to the mutation function instead. This follows the same behavior as [TanStack Query](https://tanstack.com/query/v5/docs/react/guides/mutations) mutations and improves type-safety. tsx import { useSignMessage } from 'wagmi' const { signMessage } = useSignMessage({ message: 'foo bar baz' }) const { signMessage } = useSignMessage() ### Moved TanStack Query parameters to `query` property [​](#moved-tanstack-query-parameters-to-query-property) Previously, you could pass TanStack Query parameters, like `enabled` and `staleTime`, directly to hooks. In Wagmi v2, TanStack Query parameters are now moved to the `query` property. This allows Wagmi to better support TanStack Query type inference, control for future breaking changes since [TanStack Query is now a peer dependency](#moved-tanstack-query-to-peer-dependencies) , and expose Wagmi-related hook property at the top-level of editor features, like autocomplete. tsx useReadContract({ enabled: false, staleTime: 1_000, query: { enabled: false, staleTime: 1_000, }, }) ### Removed watch property [​](#removed-watch-property) The `watch` property was removed from all hooks besides [`useBlock`](/react/api/hooks/useBlock) and [`useBlockNumber`](/react/api/hooks/useBlockNumber) . This property allowed hooks to internally listen for block changes and automatically refresh their data. In Wagmi v2, you can compose `useBlock` or `useBlockNumber` along with [`React.useEffect`](https://react.dev/reference/react/useEffect) to achieve the same behavior. Two different approaches are outlined for `useBalance` below. invalidateQueriesrefetch ts import { useQueryClient } from '@tanstack/react-query' import { useEffect } from 'react' import { useBlockNumber, useBalance } from 'wagmi' const queryClient = useQueryClient() const { data: blockNumber } = useBlockNumber({ watch: true }) const { data: balance, queryKey } = useBalance({ address: '0x4557B18E779944BFE9d78A672452331C186a9f48', watch: true, }) useEffect(() => { queryClient.invalidateQueries({ queryKey }) }, [blockNumber, queryClient]) ts import { useEffect } from 'react' import { useBlockNumber, useBalance } from 'wagmi' const { data: blockNumber } = useBlockNumber({ watch: true }) const { data: balance, refetch } = useBalance({ address: '0x4557B18E779944BFE9d78A672452331C186a9f48', watch: true, }) useEffect(() => { refetch() }, [blockNumber]) This is a bit more code, but removes a lot of internal code from hooks that can slow down your app when not used and gives you more control. For example, you can easily refresh data every five blocks instead of every block. ts const { data: blockNumber } = useBlockNumber({ watch: true }) const { data: balance, queryKey } = useBalance({ address: '0x4557B18E779944BFE9d78A672452331C186a9f48', }) useEffect(() => { if (blockNumber % 5 === 0) queryClient.invalidateQueries({ queryKey }) }, [blockNumber, queryClient]) ### Removed suspense property [​](#removed-suspense-property) Wagmi used to support an experimental `suspense` property via TanStack Query. Since TanStack Query [removed `suspense`](https://tanstack.com/query/v5/docs/react/guides/migrating-to-v5#new-hooks-for-suspense) from its `useQuery` hook, it is no longer supported by Wagmi Hooks. Instead, you can use `useSuspenseQuery` along with TanStack Query-related exports from the `'wagmi/query'` entrypoint. ts import { useSuspenseQuery } from '@tanstack/react-query' import { useConfig } from 'wagmi' import { getBalanceQueryOptions } from 'wagmi/query' import { useBalance } from 'wagmi' const config = useConfig() const options = getBalanceQueryOptions(config, { address: '0x…' }) const result = useSuspenseQuery(options) const result = useBalance({ address: '0x…', suspense: true, }) ### Removed prepare hooks [​](#removed-prepare-hooks) `usePrepareContractWrite` and `usePrepareSendTransaction` were removed and replaced with idiomatic Viem alternatives. For `usePrepareContractWrite`, use [`useSimulateContract`](/react/api/hooks/useSimulateContract) . Similar to `usePrepareContractWrite`, `useSimulateContract` composes well with `useWriteContract` tsx import { usePrepareContractWrite, useWriteContract } from 'wagmi' import { useSimulateContract, useWriteContract } from 'wagmi' const { config } = usePrepareContractWrite({ const { data } = useSimulateContract({ address: '0x', abi: [{\ type: 'function',\ name: 'transferFrom',\ stateMutability: 'nonpayable',\ inputs: [\ { name: 'sender', type: 'address' },\ { name: 'recipient', type: 'address' },\ { name: 'amount', type: 'uint256' },\ ],\ outputs: [{ type: 'bool' }],\ }], functionName: 'transferFrom', args: ['0x', '0x', 123n], }) const { write } = useWriteContract(config) const { writeContract } = useWriteContract() Instead of `usePrepareSendTransaction`, use [`useEstimateGas`](/react/api/hooks/useEstimateGas) . You can pass `useEstimateGas` `data` to `useSendTransaction` to compose the two hooks. tsx import { usePrepareSendTransaction, useSendTransaction } from 'wagmi' import { useEstimateGas, useSendTransaction } from 'wagmi' import { parseEther } from 'viem' const { config } = usePrepareSendTransaction({ const { data } = useEstimateGas({ to: '0xd2135CfB216b74109775236E36d4b433F1DF507B', value: parseEther('0.01'), }) const { sendTransaction } = useSendTransaction(config) const { sendTransaction } = useSendTransaction() This might seem like more work, but it gives you more control and is more accurate representation of what is happening under the hood. ### Removed `useNetwork` hook [​](#removed-usenetwork-hook) The `useNetwork` hook was removed since the connected chain is typically based on the connected account. Use [`useAccount`](/react/api/hooks/useAccount) to get the connected `chain`. ts import { useNetwork } from 'wagmi' import { useAccount } from 'wagmi' const { chain } = useNetwork() const { chain } = useAccount() Use `useConfig` for the list of `chains` set up with the Wagmi [`Config`](/react/api/createConfig#chains) . ts import { useNetwork } from 'wagmi' import { useConfig } from 'wagmi' const { chains } = useNetwork() const { chains } = useConfig() ### Removed `onConnect` and `onDisconnect` callbacks from `useAccount` [​](#removed-onconnect-and-ondisconnect-callbacks-from-useaccount) The `onConnect` and `onDisconnect` callbacks were removed from the `useAccount` hook since it is frequently used without these callbacks so it made sense to extract these into a new API, [`useAccountEffect`](/react/api/hooks/useAccountEffect) , rather than clutter the `useAccount` hook. ts import { useAccount } from 'wagmi' import { useAccountEffect } from 'wagmi' useAccount({ useAccountEffect({ onConnect(data) { console.log('connected', data) }, onDisconnect() { console.log('disconnected') }, }) ### Removed `useWebSocketPublicClient` [​](#removed-usewebsocketpublicclient) The Wagmi [`Config`](/react/api/createConfig) does not separate transport types anymore. Simply use Viem's [`webSocket`](https://viem.sh/docs/clients/transports/websocket.html) transport instead when setting up your Wagmi `Config`. You can get Viem `Client` instance with this transport attached by using [`useClient`](/react/api/hooks/useClient) or [`usePublicClient`](/react/api/hooks/usePublicClient) . ### Removed `useInfiniteReadContracts` `paginatedIndexesConfig` [​](#removed-useinfinitereadcontracts-paginatedindexesconfig) In the spirit of removing unnecessary abstractions, `paginatedIndexesConfig` was removed. Use `useInfiniteReadContracts`'s `initialPageParam` and `getNextPageParam` parameters along with `fetchNextPage`/`fetchPreviousPage` from the result instead or copy `paginatedIndexesConfig`'s implementation to your codebase. See the [TanStack Query docs](https://tanstack.com/query/v5/docs/react/guides/infinite-queries) for more information on infinite queries. ### Updated `useSendTransaction` and `useWriteContract` return type [​](#updated-usesendtransaction-and-usewritecontract-return-type) Updated [`useSendTransaction`](/react/api/hooks/useSendTransaction) and [`useWriteContract`](/react/api/hooks/useWriteContract) return type from ``{ hash: `0x${string}` }`` to `` `0x${string}` ``. ts const result = useSendTransaction() result.data?.hash result.data ### Updated `useConnect` return type [​](#updated-useconnect-return-type) Updated [`useConnect`](/react/api/hooks/useConnect) return type from `{ account: Address; chain: { id: number; unsupported?: boolean }; connector: Connector }` to `{ accounts: readonly Address[]; chainId: number }`. This better reflects the ability to have multiple accounts per connector. ### Renamed parameters and return types [​](#renamed-parameters-and-return-types) All hook parameters and return types follow the naming pattern of `[PascalCaseHookName]Parameters` and `[PascalCaseHookName]ReturnType`. For example, `UseAccountParameters` and `UseAccountReturnType`. ts import { UseAccountConfig, UseAccountResult } from 'wagmi' import { UseAccountParameters, UseAccountReturnType } from 'wagmi' Connectors [​](#connectors) ---------------------------- ### Updated connector API [​](#updated-connector-api) In order to maximize type-safety and ease of creating connectors, the connector API changed. Follow the [Creating Connectors guide](/dev/creating-connectors) for more info on creating new connectors and converting Wagmi v1 connectors. ### Removed individual entrypoints [​](#removed-individual-entrypoints) Previously, each connector had it's own entrypoint to optimize tree-shaking. Since all connectors now have [`package.json#sideEffects`](https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free) enabled, this is no longer necessary and the entrypoint is unified. Use the `'wagmi/connectors'` entrypoint instead. ts import { InjectedConnector } from 'wagmi/connectors/injected' import { CoinbaseWalletConnector } from 'wagmi/connectors/coinbaseWallet' import { coinbaseWallet, injected } from 'wagmi/connectors' ### Removed `MetaMaskConnector` [​](#removed-metamaskconnector) The `MetaMaskConnector` was removed since it was nearly the same thing as the `InjectedConnector`. Use the [`injected`](/react/api/connectors/injected) connector instead, along with the [`target`](/react/api/connectors/injected#target) parameter set to `'metaMask'`, for the same behavior. ts import { MetaMaskConnector } from 'wagmi/connectors/metaMask' import { injected } from 'wagmi/connectors' const connector = new MetaMaskConnector() const connector = injected({ target: 'metaMask' }) ### Renamed connectors [​](#renamed-connectors) In Wagmi v1, connectors were classes you needed to instantiate. In Wagmi v2, connectors are functions. As a result, the API has changed. Connectors have the following new names: * `CoinbaseWalletConnector` is now [`coinbaseWallet`](/react/api/connectors/coinbaseWallet) . * `InjectedConnector` is now [`injected`](/react/api/connectors/injected) . * `SafeConnector` is now [`safe`](/react/api/connectors/safe) . * `WalletConnectConnector` is now [`walletConnect`](/react/api/connectors/walletConnect) . To create a connector, you now call the connector function with parameters. ts import { WalletConnectConnector } from 'wagmi/connectors/walletConnect' import { walletConnect } from 'wagmi/connectors' const connector = new WalletConnectConnector({ const connector = walletConnect({ projectId: '3fcc6bba6f1de962d911bb5b5c3dba68', }) ### Removed `WalletConnectLegacyConnector` [​](#removed-walletconnectlegacyconnector) WalletConnect v1 was sunset June 28, 2023. Use the [`walletConnect`](/react/api/connectors/walletConnect) connector instead. ts import { WalletConnectLegacyConnector } from 'wagmi/connectors/walletConnectLegacy' import { walletConnect } from 'wagmi/connectors' const connector = new WalletConnectLegacyConnector({ const connector = walletConnect({ projectId: '3fcc6bba6f1de962d911bb5b5c3dba68', }) Chains [​](#chains) -------------------- ### Updated `'wagmi/chains'` entrypoint [​](#updated-wagmi-chains-entrypoint) Chains now live in the [Viem repository](https://github.com/wevm/viem) . As a result, the `'wagmi/chains'` entrypoint now proxies all chains from `'viem/chains'` directly. ### Removed `mainnet` and `sepolia` from main entrypoint [​](#removed-mainnet-and-sepolia-from-main-entrypoint) Since the `'wagmi/chains'` entrypoint now proxies `'viem/chains'`, `mainnet` and `sepolia` were removed from the main entrypoint. Use the `'wagmi/chains'` entrypoint instead. ts import { mainnet, sepolia } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' Errors [​](#errors) -------------------- A number of errors were renamed to better reflect their functionality or replaced by Viem errors. Miscellaneous [​](#miscellaneous) ---------------------------------- ### Removed internal ENS name normalization [​](#removed-internal-ens-name-normalization) Before v2, Wagmi handled ENS name normalization internally for `useEnsAddress`, `useEnsAvatar`, and `useEnsResolver`, using Viem's [`normalize`](https://viem.sh/docs/ens/utilities/normalize.html) function. This added extra bundle size as full normalization is quite heavy. For v2, you must normalize ENS names yourself before passing them to these hooks. You can use Viem's `normalize` function or any other function that performs [UTS-46 normalization](https://unicode.org/reports/tr46) . ts import { useEnsAddress } from 'wagmi' import { normalize } from 'viem/ens' const result = useEnsAddress({ name: 'wevm.eth', name: normalize('wevm.eth'), }) By inverting control, Wagmi let's you choose how much normalization to do. For example, maybe your project only allows ENS names that are numeric so no normalization is not needed. Check out the [ENS documentation](https://docs.ens.domains/contract-api-reference/name-processing#normalising-names) for more information on normalizing names. ### Removed `configureChains` [​](#removed-configurechains) The Wagmi v2 `Config` now has native multichain support using the [`chains`](/react/api/createConfig) parameter so the `configureChains` function is no longer required. ts import { configureChains, createConfig } from 'wagmi' import { http, createConfig } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' const { chains, publicClient } = configureChains( [mainnet, sepolia], [publicProvider(), publicProvider()], ) export const config = createConfig({ publicClient, chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) ### Removed ABI exports [​](#removed-abi-exports) Import from Viem instead. ts import { erc20ABI } from 'wagmi' import { erc20Abi } from 'viem' ### Removed `'wagmi/providers/*` entrypoints [​](#removed-wagmi-providers-entrypoints) It never made sense that we would have provider URLs hardcoded in the Wagmi codebase. Use [Viem transports](https://viem.sh/docs/clients/intro.html#transports) along with RPC provider URLs instead. ts import { alchemyProvider } from 'wagmi/providers/alchemy' import { http } from 'viem' const transport = http('https://mainnet.example.com') ### Updated `createConfig` parameters [​](#updated-createconfig-parameters) * Removed `autoConnect`. The reconnecting behavior is now managed by React and not related to the Wagmi `Config`. Use `WagmiProvider` [`reconnectOnMount`](/react/api/WagmiProvider#reconnectonmount) or [`useReconnect`](/react/api/hooks/useReconnect) hook instead. * Removed `publicClient` and `webSocketPublicClient`. Use [`transports`](/react/api/createConfig#transports) or [`client`](/react/api/createConfig#client) instead. * Removed `logger`. Wagmi no longer logs debug information to console. ### Updated `Config` object [​](#updated-config-object) * Removed `config.connector`. Use `config.state.connections.get(config.state.current)?.connector` instead. * Removed `config.data`. Use `config.state.connections.get(config.state.current)` instead. * Removed `config.error`. Was unused and not needed. * Removed `config.lastUsedChainId`. Use `config.state.connections.get(config.state.current)?.chainId` instead. * Removed `config.publicClient`. Use [`config.getClient()`](/react/api/createConfig#getclient) or [`getPublicClient`](/core/api/actions/getPublicClient) instead. * Removed `config.status`. Use [`config.state.status`](/react/api/createConfig#status) instead. * Removed `config.webSocketClient`. Use [`config.getClient()`](/react/api/createConfig#getclient) or [`getPublicClient`](/core/api/actions/getPublicClient) instead. * Removed `config.clearState`. Was unused and not needed. * Removed `config.autoConnect()`. Use [`reconnect`](/core/api/actions/reconnect) action instead. * Renamed `config.setConnectors`. Use `config._internal.setConnectors` instead. * Removed `config.setLastUsedConnector`. Use `config.storage?.setItem('recentConnectorId', connectorId)` instead. * Removed `getConfig`. `config` should be passed explicitly to actions instead of using global `config`. Deprecations [​](#deprecations) -------------------------------- ### Renamed `WagmiConfig` [​](#renamed-wagmiconfig) `WagmiConfig` was renamed to [`WagmiProvider`](/react/api/WagmiProvider) to reduce confusion with the Wagmi [`Config`](/react/api/createConfig) type. React Context Providers usually follow the naming schema `*Provider` so this is a more idiomatic name. Now that Wagmi no longer uses Ethers.js (since Wagmi v1), the term "Provider" is less overloaded. app.tsxconfig.ts tsx import { WagmiConfig } from 'wagmi' import { WagmiProvider } from 'wagmi' import { config } from './config' function App() { return ( {/** ... */} ) } ts import { http, createConfig } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, }) ### Deprecated `useBalance` `token` parameter [​](#deprecated-usebalance-token-parameter) Moving forward, `useBalance` will only work for native currencies, thus the `token` parameter is no longer supported. Use [`useReadContracts`](/react/api/hooks/useReadContracts) instead. ts import { useBalance } from 'wagmi' import { useReadContracts } from 'wagmi' import { erc20Abi } from 'viem' const result = useBalance({ address: '0x4557B18E779944BFE9d78A672452331C186a9f48', token: '0x6B175474E89094C44Da98b954EedeAC495271d0F', }) const result = useReadContracts({ allowFailure: false, contracts: [ \ { \ address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', \ abi: erc20Abi, \ functionName: 'balanceOf', \ args: ['0x4557B18E779944BFE9d78A672452331C186a9f48'], \ }, \ { \ address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', \ abi: erc20Abi, \ functionName: 'decimals', \ }, \ { \ address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', \ abi: erc20Abi, \ functionName: 'symbol', \ }, \ ] }) ### Deprecated `useBalance` `unit` parameter and `formatted` return value [​](#deprecated-usebalance-unit-parameter-and-formatted-return-value) Moving forward, `useBalance` will not accept the `unit` parameter or return a `formatted` value. Instead you can call `formatUnits` from Viem directly or use another number formatting library, like [dnum](https://github.com/bpierre/dnum) instead. ts import { formatUnits } from 'viem' import { useBalance } from 'wagmi' const result = useBalance({ address: '0x4557B18E779944BFE9d78A672452331C186a9f48', unit: 'ether', }) result.data!.formatted formatUnits(result.data!.value, result.data!.decimals) ### Deprecated `useToken` [​](#deprecated-usetoken) Moving forward, `useToken` is no longer supported. Use [`useReadContracts`](/react/api/hooks/useReadContracts) instead. ts import { useToken } from 'wagmi' import { useReadContracts } from 'wagmi' import { erc20Abi } from 'viem' const result = useToken({ address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', }) const result = useReadContracts({ allowFailure: false, contracts: [ \ { \ address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', \ abi: erc20Abi, \ functionName: 'decimals', \ }, \ { \ address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', \ abi: erc20Abi, \ functionName: 'name', \ }, \ { \ address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', \ abi: erc20Abi, \ functionName: 'symbol', \ }, \ { \ address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', \ abi: erc20Abi, \ functionName: 'totalSupply', \ }, \ ] }) ### Deprecated `formatUnits` parameters and return values [​](#deprecated-formatunits-parameters-and-return-values) The `formatUnits` parameter and related return values (e.g. `result.formatted`) are deprecated for the following hooks: * [`useEstimateFeesPerGas`](/react/api/hooks/useEstimateFeesPerGas) * [`useToken`](/react/api/hooks/useToken) Instead you can call `formatUnits` from Viem directly or use another number formatting library, like [dnum](https://github.com/bpierre/dnum) instead. ts import { formatUnits } from 'viem' const result = useToken({ address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', formatUnits: 'ether', }) result.data!.totalSupply.formatted formatUnits(result.data!.totalSupply.value, 18) This allows us to invert control to users so they can handle number formatting however they want, taking into account precision, localization, and more. ### Renamed hooks [​](#renamed-hooks) The following hooks were renamed to better reflect their functionality and underlying [Viem](https://viem.sh) actions: * `useContractRead` is now [`useReadContract`](/react/api/hooks/useReadContract) * `useContractReads` is now [`useReadContracts`](/react/api/hooks/useReadContracts) * `useContractWrite` is now [`useWriteContract`](/react/api/hooks/useWriteContract) * `useContractEvent` is now [`useWatchContractEvent`](/react/api/hooks/useWatchContractEvent) * `useContractInfiniteReads` is now [`useInfiniteReadContracts`](/react/api/hooks/useInfiniteReadContracts) * `useFeeData` is now [`useEstimateFeesPerGas`](/react/api/hooks/useEstimateFeesPerGas) * `useSwitchNetwork` is now [`useSwitchChain`](/react/api/hooks/useSwitchChain) * `useWaitForTransaction` is now [`useWaitForTransactionReceipt`](/react/api/hooks/useWaitForTransactionReceipt) ### Miscellaneous [​](#miscellaneous-1) * `WagmiConfigProps` renamed to [`WagmiProviderProps`](/react/api/WagmiProvider#parameters) . * `Context` renamed to [`WagmiContext`](/react/api/WagmiProvider#context) . --- # Connect Wallet | Wagmi Return to top Connect Wallet [​](#connect-wallet) ==================================== The ability for a user to connect their wallet is a core function for any Dapp. It allows users to perform tasks such as: writing to contracts, signing messages, or sending transactions. Wagmi contains everything you need to get started with building a Connect Wallet module. To get started, you can either use a [third-party library](#third-party-libraries) or [build your own](#build-your-own) . Third-party Libraries [​](#third-party-libraries) -------------------------------------------------- You can use a pre-built Connect Wallet module from a third-party library such as: * [AppKit](https://walletconnect.com/appkit) - [Guide](https://docs.walletconnect.com/appkit/vue/core/installation) The above libraries are all built on top of Wagmi, handle all the edge cases around wallet connection, and provide a seamless Connect Wallet UX that you can use in your Dapp. Build Your Own [​](#build-your-own) ------------------------------------ Wagmi provides you with the Composables to get started building your own Connect Wallet module. It takes less than five minutes to get up and running with Browser Wallets, WalletConnect, and Coinbase Wallet. ### 1\. Configure Wagmi [​](#_1-configure-wagmi) Before we get started with building the functionality of the Connect Wallet module, we will need to set up the Wagmi configuration. Let's create a `config.ts` file and export a `config` object. config.ts tsx import { http, createConfig } from '@wagmi/vue' import { base, mainnet, optimism } from '@wagmi/vue/chains' import { injected, metaMask, safe, walletConnect } from '@wagmi/vue/connectors' const projectId = '' export const config = createConfig({ chains: [mainnet, base], connectors: [\ injected(),\ walletConnect({ projectId }),\ metaMask(),\ safe(),\ ], transports: { [mainnet.id]: http(), [base.id]: http(), }, }) In the above configuration, we want to set up connectors for Injected (browser), WalletConnect (browser + mobile), MetaMask, and Safe wallets. This configuration uses the **Mainnet** and **Base** chains, but you can use whatever you want. WARNING Make sure to replace the `projectId` with your own WalletConnect Project ID, if you wish to use WalletConnect! [Get your Project ID](https://cloud.walletconnect.com/) ### 2\. Inject the WagmiPlugin onto your App [​](#_2-inject-the-wagmiplugin-onto-your-app) Next, we will need to inject our App with plugins so that our application is aware of Wagmi & Vue Query's reactive state and in-memory caching. main.tsApp.vueconfig.ts ts // 1. Import modules. import { VueQueryPlugin } from '@tanstack/vue-query'; import { WagmiPlugin } from '@wagmi/vue'; import { createApp } from 'vue'; import App from './App.vue'; import { config } from './wagmi'; createApp(App) // 2. Inject the Wagmi plugin. .use(WagmiPlugin, { config }) // 3. Inject the Vue Query plugin. .use(VueQueryPlugin, {}) .mount('#app'); vue ts import { http, createConfig } from '@wagmi/vue' import { base, mainnet, optimism } from '@wagmi/vue/chains' import { injected, metaMask, safe, walletConnect } from '@wagmi/vue/connectors' const projectId = '' export const config = createConfig({ chains: [mainnet, base], connectors: [\ injected(),\ walletConnect({ projectId }),\ metaMask(),\ safe(),\ ], transports: { [mainnet.id]: http(), [base.id]: http(), }, }) ### 3\. Display Wallet Options [​](#_3-display-wallet-options) After that, we will create a `Connect` component that will display our connectors. This will allow users to select a wallet and connect. Below, we are rendering a list of `connectors` retrieved from `useConnect`. When the user clicks on a connector, the `connect` function will connect the users' wallet. Connect.vueApp.vuemain.tsconfig.ts vue vue ts // 1. Import modules. import { VueQueryPlugin } from '@tanstack/vue-query'; import { WagmiPlugin } from '@wagmi/vue'; import { createApp } from 'vue'; import App from './App.vue'; import { config } from './wagmi'; createApp(App) // 2. Inject the Wagmi plugin. .use(WagmiPlugin, { config }) // 3. Inject the Vue Query plugin. .use(VueQueryPlugin, {}) .mount('#app'); ts import { http, createConfig } from '@wagmi/vue' import { base, mainnet, optimism } from '@wagmi/vue/chains' import { injected, metaMask, safe, walletConnect } from '@wagmi/vue/connectors' const projectId = '' export const config = createConfig({ chains: [mainnet, base], connectors: [\ injected(),\ walletConnect({ projectId }),\ metaMask(),\ safe(),\ ], transports: { [mainnet.id]: http(), [base.id]: http(), }, }) ### 4\. Display Connected Account [​](#_4-display-connected-account) Lastly, if an account is connected, we want to show some basic information, like the connected address and ENS name and avatar. Below, we are using hooks like `useAccount`, `useEnsAvatar` and `useEnsName` to extract this information. We are also utilizing `useDisconnect` to show a "Disconnect" button so a user can disconnect their wallet. Account.vueConnect.vueApp.vuemain.tsconfig.ts vue vue vue ts // 1. Import modules. import { VueQueryPlugin } from '@tanstack/vue-query'; import { WagmiPlugin } from '@wagmi/vue'; import { createApp } from 'vue'; import App from './App.vue'; import { config } from './wagmi'; createApp(App) // 2. Inject the Wagmi plugin. .use(WagmiPlugin, { config }) // 3. Inject the Vue Query plugin. .use(VueQueryPlugin, {}) .mount('#app'); ts import { http, createConfig } from '@wagmi/vue' import { base, mainnet, optimism } from '@wagmi/vue/chains' import { injected, metaMask, safe, walletConnect } from '@wagmi/vue/connectors' const projectId = '' export const config = createConfig({ chains: [mainnet, base], connectors: [\ injected(),\ walletConnect({ projectId }),\ metaMask(),\ safe(),\ ], transports: { [mainnet.id]: http(), [base.id]: http(), }, }) ### 5\. Wire it up! [​](#_5-wire-it-up) Finally, we can wire up our Connect and Account components to our application's entrypoint. App.vueAccount.vueConnect.vuemain.tsconfig.ts vue vue vue ts // 1. Import modules. import { VueQueryPlugin } from '@tanstack/vue-query'; import { WagmiPlugin } from '@wagmi/vue'; import { createApp } from 'vue'; import App from './App.vue'; import { config } from './wagmi'; createApp(App) // 2. Inject the Wagmi plugin. .use(WagmiPlugin, { config }) // 3. Inject the Vue Query plugin. .use(VueQueryPlugin, {}) .mount('#app'); ts import { http, createConfig } from '@wagmi/vue' import { base, mainnet, optimism } from '@wagmi/vue/chains' import { injected, metaMask, safe, walletConnect } from '@wagmi/vue/connectors' const projectId = '' export const config = createConfig({ chains: [mainnet, base], connectors: [\ injected(),\ walletConnect({ projectId }),\ metaMask(),\ safe(),\ ], transports: { [mainnet.id]: http(), [base.id]: http(), }, }) ### Playground [​](#playground) Want to see the above steps all wired up together in an end-to-end example? Check out the below StackBlitz playground. --- # Chain Properties | Wagmi Return to top Chain Properties [​](#chain-properties) ======================================== Some chains support additional properties related to blocks and transactions. This is powered by Viem's [formatters](https://viem.sh/docs/clients/chains.html#formatters) and [serializers](https://viem.sh/docs/clients/chains.html#serializers) . For example, Celo, ZkSync, OP Stack chains support all additional properties. In order to use these properties in a type-safe way, there are a few things you should be aware of. Narrowing Parameters [​](#narrowing-parameters) ------------------------------------------------ When you pass your `config` to an action, you are ready to access chain-specific properties! For example, Celo's `feeCurrency` is available. index.tsconfig.ts ts import { parseEther } from 'viem' import { simulateContract } from '@wagmi/core' import { config } from './config' const result = await simulateContract(config, { to: '0xd2135CfB216b74109775236E36d4b433F1DF507B', value: parseEther('0.01'), feeCurrency: '0x…', }) ts import { http, createConfig } from '@wagmi/core' import { base, celo, mainnet } from '@wagmi/core/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) This is great, but if you have multiple chains that support additional properties, your autocomplete could be overwhelmed with all of them. By setting the `chainId` property to a specific value (e.g. `celo.id`), you can narrow parameters to a single chain. index.tsconfig.ts ts import { parseEther } from 'viem' import { simulateContract } from '@wagmi/core' import { celo } from 'wagmi/chains' const result = await simulateContract({ to: '0xd2135CfB216b74109775236E36d4b433F1DF507B', value: parseEther('0.01'), chainId: celo.id, feeCurrency: '0x…', // ^? (property) feeCurrency?: `0x${string}` | undefined }) ts import { http, createConfig } from '@wagmi/core' import { base, celo, mainnet } from '@wagmi/core/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) Narrowing Return Types [​](#narrowing-return-types) ---------------------------------------------------- Return types can also have chain-specific properties attached to them. There are a couple approaches for extracting these properties. ### `chainId` Parameter [​](#chainid-parameter) Not only can you use the `chainId` parameter to [narrow parameters](#narrowing-parameters) , you can also use it to narrow the return type. index.tsxconfig.ts ts import { waitForTransactionReceipt } from '@wagmi/core' import { zkSync } from '@wagmi/core/chains' const result = await waitForTransactionReceipt({ chainId: zkSync.id, hash: '0x16854fcdd0219cacf5aec5e4eb2154dac9e406578a1510a6fc48bd0b67e69ea9', }) result.logs // ^? (property) logs: ZkSyncLog[] | undefined ts import { http, createConfig } from '@wagmi/core' import { base, celo, mainnet } from '@wagmi/core/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) ### `chainId` Data Property [​](#chainid-data-property) Wagmi internally will set a `chainId` property on return types that you can use to narrow results. The `chainId` is determined from the `chainId` parameter or global state (e.g. connector). You can use this property to help TypeScript narrow the type. index.tsxconfig.ts ts import { waitForTransactionReceipt } from '@wagmi/core' import { zkSync } from '@wagmi/core/chains' const result = await waitForTransactionReceipt({ hash: '0x16854fcdd0219cacf5aec5e4eb2154dac9e406578a1510a6fc48bd0b67e69ea9', }) if (result.chainId === zkSync.id) { result.logs // ^? (property) logs: ZkSyncLog[] | undefined } ts import { http, createConfig } from '@wagmi/core' import { base, celo, mainnet } from '@wagmi/core/chains' export const config = createConfig({ chains: [base, celo, mainnet], transports: { [base.id]: http(), [celo.id]: http(), [mainnet.id]: http(), }, }) Troubleshooting [​](#troubleshooting) -------------------------------------- If chain properties aren't working, make sure [TypeScript](/core/guides/faq#type-inference-doesn-t-work) is configured correctly. Not all chains have additional properties, to check which ones do, see the [Viem repo](https://github.com/wevm/viem/tree/main/src/chains) (chains that have a top-level directory under [`src/chains`](https://github.com/wevm/viem/tree/main/src/chains) support additional properties). --- # init | Wagmi Return to top init [​](#init) ================ Creates configuration file. If TypeScript is detected, the config file will use TypeScript and be named `wagmi.config.ts`. Otherwise, the config file will use JavaScript and be named `wagmi.config.js`. Usage [​](#usage) ------------------ bash wagmi init Options [​](#options) ---------------------- ### \-c, --config [​](#c-config-path) `string` Path to config file. bash wagmi init --config wagmi.config.ts ### \-r, --root [​](#r-root-path) `string` Root path to resolve config from. bash wagmi init --root path/to/root ### \-h, --help [​](#h-help) Displays help message. bash wagmi init --help --- # createConfig | Wagmi Return to top createConfig [​](#createconfig) ================================ Creates new [`Config`](#config) object. Import [​](#import) -------------------- ts import { createConfig } from 'wagmi' Usage [​](#usage) ------------------ ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http('https://mainnet.example.com'), [sepolia.id]: http('https://sepolia.example.com'), }, }) Integrating a Viem Client Instead of using [`transports`](#transports) , it's possible to provide a function that returns a Viem [`Client`](https://viem.sh/docs/clients/custom.html) via the [`client`](#client) property for more fine-grained control over Wagmi's internal `Client` creation. ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' import { createClient } from 'viem' const config = createConfig({ chains: [mainnet, sepolia], client({ chain }) { return createClient({ chain, transport: http() }) }, }) Parameters [​](#parameters) ---------------------------- ts import { type CreateConfigParameters } from 'wagmi' ### chains [​](#chains) `readonly [Chain, ...Chain[]]` * Chains used by the `Config`. * See [Chains](/react/api/chains) for more details about built-in chains and the `Chain` type. ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http('https://mainnet.example.com'), [sepolia.id]: http('https://sepolia.example.com'), }, }) ### connectors [​](#connectors) `CreateConnectorFn[] | undefined` [Connectors](/react/api/connectors) used by the `Config`. ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' import { injected } from 'wagmi/connectors' const config = createConfig({ chains: [mainnet, sepolia], connectors: [injected()], transports: { [mainnet.id]: http('https://mainnet.example.com'), [sepolia.id]: http('https://sepolia.example.com'), }, }) ### multiInjectedProviderDiscovery [​](#multiinjectedproviderdiscovery) `boolean | undefined` * Enables discovery of injected providers via [EIP-6963](https://eips.ethereum.org/EIPS/eip-6963) using the [`mipd`](https://github.com/wevm/mipd) library and converting to [injected](/react/api/connectors/injected) connectors. * Defaults to `true`. ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' const config = createConfig({ chains: [mainnet, sepolia], multiInjectedProviderDiscovery: false, transports: { [mainnet.id]: http('https://mainnet.example.com'), [sepolia.id]: http('https://sepolia.example.com'), }, }) ### ssr [​](#ssr) `boolean | undefined` Flag to indicate if the config is being used in a server-side rendering environment. Defaults to `false`. ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' const config = createConfig({ chains: [mainnet, sepolia], ssr: true, transports: { [mainnet.id]: http('https://mainnet.example.com'), [sepolia.id]: http('https://sepolia.example.com'), }, }) ### storage [​](#storage) `Storage | null | undefined` * [`Storage`](/react/api/createStorage#storage) used by the config. Persists `Config`'s [`State`](#state-1) between sessions. * Defaults to `createStorage({ storage: typeof window !== 'undefined' && window.localStorage ? window.localStorage : noopStorage })`. ts import { createConfig, createStorage, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' const config = createConfig({ chains: [mainnet, sepolia], storage: createStorage({ storage: window.localStorage }), transports: { [mainnet.id]: http('https://mainnet.example.com'), [sepolia.id]: http('https://sepolia.example.com'), }, }) ### syncConnectedChain [​](#syncconnectedchain) `boolean | undefined` * Keep the [`State['chainId']`](#chainid) in sync with the current connection. * Defaults to `true`. ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' const config = createConfig({ chains: [mainnet, sepolia], syncConnectedChain: false, transports: { [mainnet.id]: http('https://mainnet.example.com'), [sepolia.id]: http('https://sepolia.example.com'), }, }) * * * ### batch [​](#batch) `{ multicall?: boolean | { batchSize?: number | undefined; wait?: number | undefined } | undefined } | { [_ in chains[number]["id"]]?: { multicall?: boolean | { batchSize?: number | undefined; wait?: number | undefined } | undefined } | undefined } | undefined` * Batch settings. See [Viem docs](https://viem.sh/docs/clients/custom.html#batch-optional) for more info. * Defaults to `{ multicall: true }`. ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' const config = createConfig({ chains: [mainnet, sepolia], batch: { multicall: true }, transports: { [mainnet.id]: http('https://mainnet.example.com'), [sepolia.id]: http('https://sepolia.example.com'), }, }) ### cacheTime [​](#cachetime) `number | { [_ in chains[number]['id']]?: number | undefined } | undefined` * Frequency in milliseconds for polling enabled features. See [Viem docs](https://viem.sh/docs/clients/public.html#cachetime-optional) for more info. * Defaults to [`pollingInterval`](#pollinginterval) or `4_000`. ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' const config = createConfig({ chains: [mainnet, sepolia], cacheTime: 4_000, transports: { [mainnet.id]: http('https://mainnet.example.com'), [sepolia.id]: http('https://sepolia.example.com'), }, }) ### pollingInterval [​](#pollinginterval) `number | { [_ in chains[number]['id']]?: number | undefined } | undefined` * Frequency in milliseconds for polling enabled features. See [Viem docs](https://viem.sh/docs/clients/custom.html#pollinginterval-optional) for more info. * Defaults to `4_000`. ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' const config = createConfig({ chains: [mainnet, sepolia], pollingInterval: 4_000, transports: { [mainnet.id]: http('https://mainnet.example.com'), [sepolia.id]: http('https://sepolia.example.com'), }, }) ### transports [​](#transports) `Record` Mapping of [chain IDs](#chains) to [`Transport`](/react/api/transports) s. This mapping is used internally when creating chain-aware Viem [`Client`](https://viem.sh/docs/clients/custom.html) objects. See the [Transport docs](/react/api/transports) for more info. ts import { createConfig, fallback, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: fallback([ \ http('https://...'), \ http('https://...'), \ ]), [sepolia.id]: http('https://...'), }, }) * * * ### client [​](#client) `(parameters: { chain: chains[number] }) => Client` Function for creating new Viem [`Client`](https://viem.sh/docs/clients/custom.html) to be used internally. Exposes more control over the internal `Client` creation logic versus using the [`transports`](#transports) property. ts import { createClient, http } from 'viem' import { createConfig } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' const config = createConfig({ chains: [mainnet, sepolia], client({ chain }) { return createClient({ chain, transport: http('https://...') }) }, }) WARNING When using this option, you likely want to pass `parameters.chain` straight through to [`createClient`](https://viem.sh/docs/clients/custom.html#createclient) to ensure the Viem `Client` is in sync with any active connections. Return Type [​](#return-type) ------------------------------ ts import { type Config } from 'wagmi' Config [​](#config) -------------------- Object responsible for managing Wagmi state and internals. ts import { type Config } from 'wagmi' ### chains [​](#chains-1) `readonly [Chain, ...Chain[]]` [`chains`](#chains) passed to `createConfig`. ### connectors [​](#connectors-1) `readonly Connector[]` Connectors set up from passing [`connectors`](#connectors) and [`multiInjectedProviderDiscovery`](#multiinjectedproviderdiscovery) to `createConfig`. ### state [​](#state) `State` The `Config` object's internal state. See [`State`](#state-1) for more info. ### storage [​](#storage-1) `Storage | null` [`storage`](#storage) passed to `createConfig`. ### getClient [​](#getclient) `(parameters?: { chainId?: chainId | chains[number]['id'] | undefined }): Client>` Creates new Viem [`Client`](https://viem.sh/docs/clients/custom.html) object. index.tsconfig.ts ts import { config } from './config' const client = config.getClient({ chainId: 1 }) ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http('https://mainnet.example.com'), [sepolia.id]: http('https://sepolia.example.com'), }, }) ### setState [​](#setstate) `(value: State | ((state: State) => State)) => void` Updates the `Config` object's internal state. See [`State`](#state-1) for more info. index.tsconfig.ts ts import { mainnet } from 'wagmi/chains' import { config } from './config' config.setState((x) => ({ ...x, chainId: x.current ? x.chainId : mainnet.id, })) ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http('https://mainnet.example.com'), [sepolia.id]: http('https://sepolia.example.com'), }, }) WARNING Exercise caution when using this method. It is intended for internal and advanced use-cases only. Manually setting state can cause unexpected behavior. ### subscribe [​](#subscribe) `(selector: (state: State) => state, listener: (selectedState: state, previousSelectedState: state) => void, options?: { emitImmediately?: boolean | undefined; equalityFn?: ((a: state, b: state) => boolean) | undefined } | undefined) => (() => void)` Listens for state changes matching the `selector` function. Returns a function that can be called to unsubscribe the listener. index.tsconfig.ts ts import { config } from './config' const unsubscribe = config.subscribe( (state) => state.chainId, (chainId) => console.log(`Chain ID changed to ${chainId}`), ) unsubscribe() ts import { createConfig, http } from 'wagmi' import { mainnet, sepolia } from 'wagmi/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http('https://mainnet.example.com'), [sepolia.id]: http('https://sepolia.example.com'), }, }) State [​](#state-1) -------------------- ts import { type State } from 'wagmi' ### chainId [​](#chainid) `chains[number]['id']` Current chain ID. When `syncConnectedChain` is `true`, `chainId` is kept in sync with the current connection. Defaults to first chain in [`chains`](#chains) . ### connections [​](#connections) `Map` Mapping of unique connector identifier to [`Connection`](#connection) object. ### current [​](#current) `string | undefined` Unique identifier of the current connection. ### status [​](#status) `'connected' | 'connecting' | 'disconnected' | 'reconnecting'` Current connection status. * `'connecting'` attempting to establish connection. * `'reconnecting'` attempting to re-establish connection to one or more connectors. * `'connected'` at least one connector is connected. * `'disconnected'` no connection to any connector. Connection [​](#connection) ---------------------------- ts import { type Connection } from 'wagmi' ### accounts [​](#accounts) `readonly [Address, ...Address[]]` Array of addresses associated with the connection. ### chainId [​](#chainid-1) `number` Chain ID associated with the connection. ### connector [​](#connector) `Connector` Connector associated with the connection. --- # Send Transaction | Wagmi Return to top Send Transaction [​](#send-transaction) ======================================== The following guide teaches you how to send transactions in Wagmi. The example below builds on the [Connect Wallet guide](/vue/guides/connect-wallet) and uses the [useSendTransaction](/vue/api/composables/useSendTransaction) & [useWaitForTransaction](/vue/api/composables/useWaitForTransactionReceipt) composables. Example [​](#example) ---------------------- Feel free to check out the example before moving on: Steps [​](#steps) ------------------ ### 1\. Connect Wallet [​](#_1-connect-wallet) Follow the [Connect Wallet guide](/vue/guides/connect-wallet) guide to get this set up. ### 2\. Create a new component [​](#_2-create-a-new-component) Create your `SendTransaction` component that will contain the send transaction logic. SendTransaction.vue tsx ### 3\. Add a form handler [​](#_3-add-a-form-handler) Next, we will need to add a handler to the form that will send the transaction when the user hits "Send". This will be a basic handler in this step. SendTransaction.vue vue ### 4\. Hook up the `useSendTransaction` Composable [​](#_4-hook-up-the-usesendtransaction-composable) Now that we have the form handler, we can hook up the [`useSendTransaction` Composable](/vue/api/composables/useSendTransaction) to send the transaction. SendTransaction.vue vue ### 5\. Add loading state (optional) [​](#_5-add-loading-state-optional) We can optionally add a loading state to the "Send" button while we are waiting confirmation from the user's wallet. SendTransaction.vue vue ### 6\. Wait for transaction receipt (optional) [​](#_6-wait-for-transaction-receipt-optional) We can also display the transaction confirmation status to the user by using the [`useWaitForTransactionReceipt` Composable](/vue/api/composables/useWaitForTransactionReceipt) . SendTransaction.vue vue ### 7\. Handle errors (optional) [​](#_7-handle-errors-optional) If the user rejects the transaction, or the user does not have enough funds to cover the transaction, we can display an error message to the user. SendTransaction.vue vue ### 8\. Wire it up! [​](#_8-wire-it-up) Finally, we can wire up our Send Transaction component to our application's entrypoint. App.vueSendTransaction.vue vue vue [See the Example.](#example) --- # FAQ / Troubleshooting | Wagmi Return to top FAQ / Troubleshooting [​](#faq-troubleshooting) ================================================ Collection of frequently asked questions with ideas on how to troubleshoot and resolve them. Type inference doesn't work [​](#type-inference-doesn-t-work) -------------------------------------------------------------- * Check that you set up TypeScript correctly with `"strict": true` in your `tsconfig.json` ([TypeScript docs](/core/typescript#requirements) ) * Check that you [const-asserted any ABIs or Typed Data](/core/typescript#const-assert-abis-typed-data) you are using. * Restart your language server or IDE, and check for type errors in your code. My wallet doesn't work [​](#my-wallet-doesn-t-work) ---------------------------------------------------- If you run into issues with a specific wallet, try another before opening up an issue. There are many different wallets and it's likely that the issue is with the wallet itself, not Wagmi. For example, if you are using Wallet X and sending a transaction doesn't work, try Wallet Y and see if it works. `BigInt` Serialization [​](#bigint-serialization) -------------------------------------------------- Using native `BigInt` with `JSON.stringify` will raise a `TypeError` as [`BigInt` values are not serializable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#use_within_json) . There are two techniques to mitigate this: #### Lossless serialization [​](#lossless-serialization) Lossless serialization means that `BigInt` will be converted to a format that can be deserialized later (e.g. `69420n` → `"#bigint.69420"`). The trade-off is that these values are not human-readable and are not intended to be displayed to the user. Lossless serialization can be achieved with wagmi's [`serialize`](/core/api/utilities/serialize) and [`deserialize`](/core/api/utilities/deserialize) utilities. tsx import { serialize, deserialize } from 'wagmi' const serialized = serialize({ value: 69420n }) // '{"value":"#bigint.69420"}' const deserialized = deserialize(serialized) // { value: 69420n } #### Lossy serialization [​](#lossy-serialization) Lossy serialization means that the `BigInt` will be converted to a normal display string (e.g. `69420n` → `'69420'`). The trade-off is that you will not be able to deserialize the `BigInt` with `JSON.parse` as it can not distinguish between a normal string and a `BigInt`. This method can be achieved by modifying `JSON.stringify` to include a BigInt `replacer`: tsx const replacer = (key, value) => typeof value === 'bigint' ? value.toString() : value JSON.stringify({ value: 69420n }, replacer) // '{"value":"69420"}' How do I support the project? [​](#how-do-i-support-the-project) ----------------------------------------------------------------- Wagmi is an open source software project and free to use. If you enjoy using Wagmi or would like to support Wagmi development, you can: * [Become a sponsor on GitHub](https://github.com/sponsors/wevm) * Send us crypto * Mainnet: 0x4557B18E779944BFE9d78A672452331C186a9f48 * Multichain: 0xd2135CfB216b74109775236E36d4b433F1DF507B * [Become a supporter on Drips](https://www.drips.network/app/projects/github/wevm/wagmi) If you use Wagmi at work, consider asking your company to sponsor Wagmi. This may not be easy, but **business sponsorships typically make a much larger impact on the sustainability of OSS projects** than individual donations, so you will help us much more if you succeed. Is Wagmi production ready? [​](#is-wagmi-production-ready) ----------------------------------------------------------- Yes. Wagmi is very stable and is used in production by thousands of organizations, like [Stripe](https://stripe.com) , [Shopify](https://shopify.com) , [Coinbase](https://coinbase.com) , [Uniswap](https://uniswap.org) , [ENS](https://ens.domains) , [Optimism](https://optimism.com) . Is Wagmi strict with semver? [​](#is-wagmi-strict-with-semver) --------------------------------------------------------------- Yes, Wagmi is very strict with [semantic versioning](https://semver.org) and we will never introduce breaking changes to the runtime API in a minor version bump. For exported types, we try our best to not introduce breaking changes in non-major versions, however, [TypeScript doesn't follow semver](https://www.learningtypescript.com/articles/why-typescript-doesnt-follow-strict-semantic-versioning) and often introduces breaking changes in minor releases that can cause Wagmi type issues. See the [TypeScript docs](/core/typescript#requirements) for more information. How can I contribute to Wagmi? [​](#how-can-i-contribute-to-wagmi) ------------------------------------------------------------------- The Wagmi team accepts all sorts of contributions. Check out the [Contributing](/dev/contributing) guide to get started. If you are interested in adding a new connector to Wagmi, check out the [Creating Connectors](/dev/creating-connectors) guide. Anything else you want to know? [​](#anything-else-you-want-to-know) --------------------------------------------------------------------- Please create a new [GitHub Discussion thread](https://github.com/wevm/wagmi) . You're also free to suggest changes to this or any other page on the site using the "Suggest changes to this page" button at the bottom of the page. --- # createStorage | Wagmi Return to top createStorage [​](#createstorage) ================================== Creates new [`Storage`](#storage) object. Import [​](#import) -------------------- ts import { createStorage } from 'wagmi' Usage [​](#usage) ------------------ ts import { createStorage } from 'wagmi' const storage = createStorage({ storage: localStorage }) Parameters [​](#parameters) ---------------------------- ts import { type CreateStorageParameters } from 'wagmi' ### deserialize [​](#deserialize) `((value: string) => T) | undefined` * Function to deserialize data from storage. * Defaults to [`deserialize`](/react/api/utilities/deserialize) . ts import { createStorage, deserialize } from 'wagmi' const storage = createStorage({ deserialize, storage: localStorage, }) WARNING If you use a custom `deserialize` function, make sure it can handle `bigint` and `Map` values. ### key [​](#key) `string | undefined` * Key prefix to use when persisting data. * Defaults to `'wagmi'`. ts import { createStorage } from 'wagmi' const storage = createStorage({ key: 'my-app', storage: localStorage, }) ### serialize [​](#serialize) `((value: T) => string) | undefined` * Function to serialize data for storage. * Defaults to [`serialize`](/react/api/utilities/serialize) . ts import { createStorage, serialize } from 'wagmi' const storage = createStorage({ serialize, storage: localStorage, }) WARNING If you use a custom `serialize` function, make sure it can handle `bigint` and `Map` values. ### storage [​](#storage) `{ getItem(key: string): string | null | undefined | Promise; setItem(key: string, value: string): void | Promise; removeItem(key: string): void | Promise; }` * Storage interface to use for persisting data. * Defaults to `localStorage`. * Supports synchronous and asynchronous storage methods. ts import { createStorage } from 'wagmi' // Using IndexedDB via https://github.com/jakearchibald/idb-keyval import { del, get, set } from 'idb-keyval' const storage = createStorage({ storage: { async getItem(name) { return get(name) }, async setItem(name, value) { await set(name, value) }, async removeItem(name) { await del(name) }, }, }) Return Type [​](#return-type) ------------------------------ ts import { type Storage } from 'wagmi' Storage [​](#storage-1) ------------------------ Object responsible for persisting Wagmi [`State`](/react/api/createConfig#state-1) and other data. ts import { type Storage } from 'wagmi' ### getItem [​](#getitem) `getItem(key: string, defaultValue?: value | null | undefined): value | null | Promise` ts import { createStorage } from 'wagmi' const storage = createStorage({ storage: localStorage }) const recentConnectorId = storage.getItem('recentConnectorId') ### setItem [​](#setitem) `setItem(key: string, value: any): void | Promise` ts import { createStorage } from 'wagmi' const storage = createStorage({ storage: localStorage }) storage.setItem('recentConnectorId', 'foo') ### removeItem [​](#removeitem) `removeItem(key: string): void | Promise` ts import { createStorage } from 'wagmi' const storage = createStorage({ storage: localStorage }) storage.removeItem('recentConnectorId') --- # Plugins | Wagmi Return to top Plugins [​](#plugins) ====================== Plugins for managing ABIs, generating code, and more. Import [​](#import) -------------------- Import via the `'@wagmi/cli/plugins'` entrypoint. ts import { etherscan } from '@wagmi/cli/plugins' Available Plugins [​](#available-plugins) ------------------------------------------ * [`actions`](/cli/api/plugins/actions) Generate type-safe VanillaJS actions from configuration `contracts`. * [`blockExplorer`](/cli/api/plugins/blockExplorer) Fetch ABIs from Block Explorers that support `?module=contract&action=getabi`. * [`etherscan`](/cli/api/plugins/etherscan) Fetch ABIs from Etherscan and add into configuration. * [`fetch`](/cli/api/plugins/fetch) Fetch and parse ABIs from network resource with `fetch`. * [`foundry`](/cli/api/plugins/foundry) Generate ABIs and watch for Foundry project changes. * [`hardhat`](/cli/api/plugins/hardhat) Generate ABIs and watch for Hardhat projects changes. * [`react`](/cli/api/plugins/react) Generate type-safe React Hooks from configuration `contracts`. * [`sourcify`](/cli/api/plugins/sourcify) Fetch ABIs from Sourcify from configuration `contracts`. Create Plugin [​](#create-plugin) ---------------------------------- Creating plugins to hook into the CLI is quite simple. Plugins most commonly inject contracts into `contracts` config, e.g. [`etherscan`](/cli/api/plugins/etherscan) , and/or generate code using the `run` option, e.g. [`react`](/cli/api/plugins/react) . All you need to do is write a function that returns the `Plugin` type. ts import { type Plugin, defineConfig } from '@wagmi/cli' function myPlugin(): Plugin { // `name` is the only required property. name: 'MyPlugin', // You likely want to at least include `contracts` or `run`. // ... } export default defineConfig({ out: 'src/generated.ts', plugins: [myPlugin()], }) --- # Read from Contract | Wagmi Return to top Read from Contract [​](#read-from-contract) ============================================ Overview [​](#overview) ------------------------ The [`useReadContract` Composable](/vue/api/composables/useReadContract) allows you to read data on a smart contract, from a `view` or `pure` (read-only) function. They can only read the state of the contract, and cannot make any changes to it. Since read-only methods do not change the state of the contract, they do not require any gas to be executed, and can be called by any user without the need to pay for gas. The component below shows how to retrieve the token balance of an address from the [Wagmi Example](https://etherscan.io/token/0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2) contract ReadContract.vuecontracts.ts vue ts export const wagmiContractConfig = { address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', abi: [\ {\ type: 'function',\ name: 'balanceOf',\ stateMutability: 'view',\ inputs: [{ name: 'account', type: 'address' }],\ outputs: [{ type: 'uint256' }],\ },\ {\ type: 'function',\ name: 'totalSupply',\ stateMutability: 'view',\ inputs: [],\ outputs: [{ name: 'supply', type: 'uint256' }],\ },\ ], } as const If `useReadContract` depends on another value (`address` in the example below), you can use the [`query.enabled`](/vue/api/composables/useReadContract#enabled) option to prevent the query from running until the dependency is ready. tsx const { data: balance } = useReadContract({ ...wagmiContractConfig, functionName: 'balanceOf', args: [address], query: { enabled: !!address, }, }) Loading & Error States [​](#loading-error-states) -------------------------------------------------- The [`useReadContract` Composable](/vue/api/composables/useReadContract) also returns loading & error states, which can be used to display a loading indicator while the data is being fetched, or an error message if contract execution reverts. ReadContract.vue vue ---