# 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)

[🚀\
\
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://github.com/tmm)
[](https://bsky.app/profile/tmm.dev)
[](https://twitter.com/awkweb)
[](https://warpcast.com/awkweb)

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
Loading ENS name
Error fetching ENS name: {{error.message}}
ENS name: {{data}}
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.

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 |  |  |  |
| Open Issues |  |  |  |
| Downloads |  |  |  |
| License |  |  |  |
| 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.

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 && }
{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 && }
{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
{{ balance }}
### 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
Block Number: {{ blockNumber }}
Balance: {{ 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.
vue
// 2. Add a button that invalidates the balance query.
vue
{{ 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.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
Block details
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 (
)
}
### 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 (
)
}
### 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 (
)
}
### 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 (
)
}
### 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 (
)
}
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
< v-if="?. === 'HttpRequestError'">
A HTTP error occurred. Status: {{ . }}
>
< v-else-if="?. === 'LimitExceededRpcError'">
Rate limit exceeded. Code: {{ . }}
>
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 (
)
}
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 (
)
}
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 (
)
}
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 (
)
}
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 (
)
}
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
Address: {{ address }}
Connected to {{ connector?.name }} Connector.
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
Address: {{ address }}
Connected to {{ connector?.name }} Connector.
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
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`](/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
Loading...
Error: {{ (error as BaseError).shortMessage || error.message }}