+
+## Installing Node.js and pnpm
+
+wagmi uses [pnpm workspaces](https://pnpm.io/workspaces) to manage multiple projects. You need to install **Node.js v16 or higher** and **pnpm v7 or higher**.
+
+You can run the following commands in your terminal to check your local Node.js and npm versions:
+
+```bash
+node -v
+pnpm -v
+```
+
+If the versions are not correct or you don't have Node.js or pnpm installed, download and follow their setup instructions:
+
+- Install Node.js using [fnm](https://github.com/Schniz/fnm) or from the [official website](https://nodejs.org)
+- Install [pnpm](https://pnpm.io/installation)
+
+
+
+## Installing dependencies
+
+Once in the project's root directory, run the following command to install 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.
+
+
+
+## Starting the development playground
+
+To start the local development playground, run the following. This will run a [Next.js](https://nextjs.org) app (located at [`examples/_dev`](../examples/_dev)) that is set up for playing around with code while making changes.
+
+```bash
+pnpm playground
+```
+
+Once the Next.js 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. (If the playground isn't automatically updating, try running `pnpm dev` to relink packages in development mode.)
+
+
+
+## Running the test suite
+
+wagmi uses [Anvil](https://github.com/foundry-rs/foundry/tree/master/anvil) to execute tests against a local Ethereum node. First, install Anvil via [Foundry](https://book.getfoundry.sh/getting-started/installation). Next, add the following to your environment (recommended to use [`direnv`](https://github.com/direnv/direnv)):
+
+```bash
+ANVIL_FORK_URL=https://eth-mainnet.alchemyapi.io/v2/
+```
+
+`ANVIL_FORK_URL` can be for any RPC service provider (e.g. Alchemy or Infura). Now you are ready to run the tests! In one terminal session, spin up Anvil using `pnpm anvil`. Next, in a different terminal session, you have the following options for running tests:
+
+- `pnpm test` — runs tests in watch mode
+- `pnpm test:run` — performs single run without watch mode
+
+When adding new features or fixing bugs, it's important to add test cases to cover the new/updated behavior. If snapshot tests fail, you can run the `test:update` command to update the snapshots.
+
+
+
+## Writing documentation
+
+Documentation is crucial to helping developers of all experience levels use wagmi. wagmi uses [Nextra](https://github.com/shuding/nextra) and [MDX](https://mdxjs.com) for the documentation site (located at [`docs`](../docs)). 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.
+
+
+
+## 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.
+
+
+ ✅ Now you're ready to contribute to wagmi! Follow the next steps if you need more advanced instructions.
+
+
+---
+
+
+
+## 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.
+
+> **Note**
+>
+> Only changes to the codebase that affect the public API or existing behavior (e.g. bugs) need changesets.
+
+Each changeset defines which package(s) 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.
+
+Since we’re currently in beta, all changes should be marked as a minor/patch release to keep us within the `v0.x` range.
+
+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
+
+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
+
+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/wagmi-dev/wagmi/actions/workflows/snapshot.yml) the Snapshot workflow. This publishes a tagged version to npm with the PR branch name and timestamp.
+
+
+ )
+}
+```
+
+## Wrap Up
+
+That's it! You now have a way for users to connect wallets and view information about the connected account. wagmi also listens for account and chain changes to keep connections and information up-to-date.
diff --git a/docs/pages/examples/contract-write-dynamic.en-US.mdx b/docs/pages/examples/contract-write-dynamic.en-US.mdx
new file mode 100644
index 0000000000..c2ea224e55
--- /dev/null
+++ b/docs/pages/examples/contract-write-dynamic.en-US.mdx
@@ -0,0 +1,406 @@
+---
+title: 'Contract Write'
+description: 'Learn how to perform a contract write with wagmi.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+import { ContractWriteDynamic } from '../../components/examples'
+
+# Contract Write (Dynamic Args)
+
+The following example teaches you how to implement a "Mint NFT" form that takes in a dynamic argument (token ID) using wagmi. The example below builds on the [Contract Write Example](/examples/contract-write) and uses the [`usePrepareContractWrite`](/react/prepare-hooks/usePrepareContractWrite), [`useContractWrite`](/react/hooks/useContractWrite) & [`useWaitForTransaction`](/react/hooks/useWaitForTransaction) hooks. Try it out before moving on.
+
+
+
+## Step 1: Connect Wallet
+
+Follow the [Connect Wallet](/examples/connect-wallet#step-1-configuring-connectors) guide to get this set up.
+
+## Step 2: Create a new component
+
+Create a new component that will contain the NFT mint form.
+
+```tsx
+import * as React from 'react'
+
+export function MintNFTForm() {
+ return (
+
+ )
+}
+```
+
+## Step 3: Add some state to the form
+
+Next, let's add some state to the input field.
+
+```tsx {4,11,13}
+import * as React from 'react'
+
+export function MintNFTForm() {
+ const [tokenId, setTokenId] = React.useState('')
+
+ return (
+
+ )
+}
+```
+
+## Step 4: Add the `usePrepareContractWrite` hook
+
+Add the [`usePrepareContractWrite` hook](/react/prepare-hooks/usePrepareContractWrite). This hook eagerly fetches the parameters required for sending a contract write transaction such as the gas estimate.
+
+You will need to:
+
+1. Add the hook
+2. Pass in your contract configuration (address, contract interface, function name and arguments)
+
+```tsx {2,7-21}
+import * as React from 'react'
+import { usePrepareContractWrite } from 'wagmi'
+
+export function MintNFTForm() {
+ const [tokenId, setTokenId] = React.useState('')
+
+ const { config } = usePrepareContractWrite({
+ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
+ abi: [
+ {
+ name: 'mint',
+ type: 'function',
+ stateMutability: 'nonpayable',
+ inputs: [{ internalType: 'uint32', name: 'tokenId', type: 'uint32' }],
+ outputs: [],
+ },
+ ],
+ functionName: 'mint',
+ args: [parseInt(tokenId)],
+ enabled: Boolean(tokenId),
+ })
+
+ return (
+
+ )
+}
+```
+
+
+ By defining inline or adding a [const
+ assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions)
+ to `abi`, TypeScript will infer the correct types for `functionName` and
+ `args`. See the wagmi [TypeScript docs](/react/typescript) for more
+ information.
+
+
+## Step 5: Add a debounce to the input value
+
+As the `usePrepareContractWrite` hook performs an RPC request to obtain the gas estimate **on mount** and **on every change to `args`**, we don't want to spam the RPC and become rate-limited.
+
+To mitigate this, we can add a [`useDebounce` hook](https://usehooks-ts.com/react-hook/use-debounce) to our component. Let's set it so that it updates the token ID if no change has been made for 500 milliseconds.
+
+```tsx {3,7,21-22}
+import * as React from 'react'
+import { usePrepareContractWrite } from 'wagmi'
+import { useDebounce } from './useDebounce'
+
+export function MintNFTForm() {
+ const [tokenId, setTokenId] = React.useState('')
+ const debouncedTokenId = useDebounce(tokenId, 500)
+
+ const { config } = usePrepareContractWrite({
+ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
+ abi: [
+ {
+ name: 'mint',
+ type: 'function',
+ stateMutability: 'nonpayable',
+ inputs: [{ internalType: 'uint32', name: 'tokenId', type: 'uint32' }],
+ outputs: [],
+ },
+ ],
+ functionName: 'mint',
+ args: [parseInt(debouncedTokenId)],
+ enabled: Boolean(debouncedTokenId),
+ })
+
+ return (
+
+ )
+}
+```
+
+## Step 6: Add the `useContractWrite` hook
+
+Now add the [`useContractWrite` hook](/react/hooks/useContractWrite). This hook performs the actual contract write transaction.
+
+We will need to:
+
+1. Add the hook.
+2. Pass in the configuration (`config`) that we created in the previous step.
+3. Hook it up to our form via an `onChange` prop.
+4. Disable the button when the `write` function is not ready (still preparing).
+
+```tsx {2,24,28-31,40}
+import * as React from 'react'
+import { usePrepareContractWrite, useContractWrite } from 'wagmi'
+import { useDebounce } from './useDebounce'
+
+export function MintNFTForm() {
+ const [tokenId, setTokenId] = React.useState('')
+ const debouncedTokenId = useDebounce(tokenId)
+
+ const { config } = usePrepareContractWrite({
+ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
+ abi: [
+ {
+ name: 'mint',
+ type: 'function',
+ stateMutability: 'nonpayable',
+ inputs: [{ internalType: 'uint32', name: 'tokenId', type: 'uint32' }],
+ outputs: [],
+ },
+ ],
+ functionName: 'mint',
+ args: [parseInt(debouncedTokenId)],
+ enabled: Boolean(debouncedTokenId),
+ })
+ const { write } = useContractWrite(config)
+
+ return (
+
+ )
+}
+```
+
+Clicking the "Mint" button will invoke the `mint` function on the contract and mint the NFT for the user.
+
+However, there is currently no feedback to show when the `mint` transaction is successful. We will add some feedback in the next step.
+
+
+ [Why do I need a `usePrepareContractWrite` & `useContractWrite`
+ hook?](/react/prepare-hooks)
+
+
+## Step 7: Add the `useWaitForTransaction` hook
+
+Using the [`useWaitForTransaction` hook](/react/hooks/useWaitForTransaction) provides you with the ability to show feedback on the status of the transaction to the user.
+
+We will need to:
+
+1. Add the hook
+2. Pass in the transaction hash (`data.hash`) as a parameter to the hook
+3. Add loading state to the button when the transaction is pending.
+4. Add a success state for when the transaction is successful.
+
+```tsx {5,28,30-32,48-58}
+import * as React from 'react'
+import {
+ usePrepareContractWrite,
+ useContractWrite,
+ useWaitForTransaction,
+} from 'wagmi'
+import { useDebounce } from './useDebounce'
+
+export function MintNFTForm() {
+ const [tokenId, setTokenId] = React.useState('')
+ const debouncedTokenId = useDebounce(tokenId)
+
+ const { config } = usePrepareContractWrite({
+ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
+ abi: [
+ {
+ name: 'mint',
+ type: 'function',
+ stateMutability: 'nonpayable',
+ inputs: [{ internalType: 'uint32', name: 'tokenId', type: 'uint32' }],
+ outputs: [],
+ },
+ ],
+ functionName: 'mint',
+ args: [parseInt(debouncedTokenId)],
+ enabled: Boolean(debouncedTokenId),
+ })
+ const { data, write } = useContractWrite(config)
+
+ const { isLoading, isSuccess } = useWaitForTransaction({
+ hash: data?.hash,
+ })
+
+ return (
+
+ )
+}
+```
+
+## Step 8: Add To App
+
+Import the `MintNFTForm` component and display it when the account is connected.
+
+```tsx {3,12}
+import { useAccount, useConnect, useDisconnect } from 'wagmi'
+
+import { MintNFTForm } from './MintNFTForm'
+
+export function App() {
+ const { isConnected } = useAccount()
+
+ if (isConnected) {
+ return (
+
+ {/* Account content goes here */}
+
+
+ )
+ }
+
+ return
{/* Connect wallet content goes here */}
+}
+```
+
+## Bonus Point: Add some error handling
+
+Now let's provide some feedback to the user if the prepare hook fails, or if the write hook fails.
+
+```tsx {16-17,33,64-66}
+import * as React from 'react'
+import {
+ usePrepareContractWrite,
+ useContractWrite,
+ useWaitForTransaction,
+} from 'wagmi'
+import { useDebounce } from './useDebounce'
+
+export function MintNFTForm() {
+ const [tokenId, setTokenId] = React.useState('')
+ const debouncedTokenId = useDebounce(tokenId)
+
+ const {
+ config,
+ error: prepareError,
+ isError: isPrepareError,
+ } = usePrepareContractWrite({
+ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
+ abi: [
+ {
+ name: 'mint',
+ type: 'function',
+ stateMutability: 'nonpayable',
+ inputs: [{ internalType: 'uint32', name: 'tokenId', type: 'uint32' }],
+ outputs: [],
+ },
+ ],
+ functionName: 'mint',
+ args: [parseInt(debouncedTokenId)],
+ enabled: Boolean(debouncedTokenId),
+ })
+ const { data, error, isError, write } = useContractWrite(config)
+
+ const { isLoading, isSuccess } = useWaitForTransaction({
+ hash: data?.hash,
+ })
+
+ return (
+
+ )
+}
+```
+
+## Wrap Up
+
+That's it! You have now added a basic "Mint NFT" form with dynamic arguments to your app.
diff --git a/docs/pages/examples/contract-write.en-US.mdx b/docs/pages/examples/contract-write.en-US.mdx
new file mode 100644
index 0000000000..b2c77a0f3d
--- /dev/null
+++ b/docs/pages/examples/contract-write.en-US.mdx
@@ -0,0 +1,261 @@
+---
+title: 'Contract Write'
+description: 'Learn how to perform a contract write with wagmi.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+import { ContractWrite } from '../../components/examples'
+
+# Contract Write
+
+The following example teaches you how to implement a simple "Mint NFT" component using wagmi. The example below builds on the [Connect Wallet Example](/examples/connect-wallet) and uses the [`usePrepareContractWrite`](/react/prepare-hooks/usePrepareContractWrite), [`useContractWrite`](/react/hooks/useContractWrite) & [`useWaitForTransaction`](/react/hooks/useWaitForTransaction) hooks. Try it out before moving on.
+
+
+
+## Step 1: Connect Wallet
+
+Follow the [Connect Wallet](/examples/connect-wallet#step-1-configuring-connectors) guide to get this set up.
+
+## Step 2: Create a new component
+
+Create a new component that will contain the NFT mint logic.
+
+```tsx
+import * as React from 'react'
+
+export function MintNFT() {
+ return (
+
+
+
+ )
+}
+```
+
+## Step 3: Add the `usePrepareContractWrite` hook
+
+Add the [`usePrepareContractWrite` hook](/react/prepare-hooks/usePrepareContractWrite). This hook eagerly fetches the parameters required for sending a contract write transaction such as the gas estimate.
+
+You will need to:
+
+1. Add the hook
+2. Pass in your contract configuration (address, contract interface, and function name)
+
+```tsx {2,5-17}
+import * as React from 'react'
+import { usePrepareContractWrite } from 'wagmi'
+
+export function MintNFT() {
+ const { config } = usePrepareContractWrite({
+ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
+ abi: [
+ {
+ name: 'mint',
+ type: 'function',
+ stateMutability: 'nonpayable',
+ inputs: [],
+ outputs: [],
+ },
+ ],
+ functionName: 'mint',
+ })
+
+ return (
+
+
+
+ )
+}
+```
+
+## Step 4: Add the `useContractWrite` hook
+
+Now add the [`useContractWrite` hook](/react/hooks/useContractWrite). This hook performs the actual contract write transaction.
+
+We will need to:
+
+1. Add the hook.
+2. Pass in the configuration (`config`) that we created in the previous step.
+3. Hook it up to our button element via an `onClick` prop.
+4. Disable the button when the `write` function is not ready (still preparing).
+
+```tsx {2,18,22-24}
+import * as React from 'react'
+import { usePrepareContractWrite, useContractWrite } from 'wagmi'
+
+export function MintNFT() {
+ const { config } = usePrepareContractWrite({
+ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
+ abi: [
+ {
+ name: 'mint',
+ type: 'function',
+ stateMutability: 'nonpayable',
+ inputs: [],
+ outputs: [],
+ },
+ ],
+ functionName: 'mint',
+ })
+ const { write } = useContractWrite(config)
+
+ return (
+
+
+
+ )
+}
+```
+
+Clicking the "Mint" button will invoke the `mint` function on the contract and mint the NFT for the user.
+
+However, there is currently no feedback to show when the `mint` transaction is successful. We will add some feedback in the next step.
+
+
+ [Why do I need a `usePrepareContractWrite` & `useContractWrite`
+ hook?](/react/prepare-hooks)
+
+
+## Step 5: Add the `useWaitForTransaction` hook
+
+Using the [`useWaitForTransaction` hook](/react/hooks/useWaitForTransaction) provides you with the ability to show feedback on the status of the transaction to the user.
+
+We will need to:
+
+1. Add the hook
+2. Add loading state to the button when the transaction is pending.
+3. Add a success state for when the transaction is successful.
+
+```tsx {5,24-26,30-40}
+import * as React from 'react'
+import {
+ usePrepareContractWrite,
+ useContractWrite,
+ useWaitForTransaction,
+} from 'wagmi'
+
+export function MintNFT() {
+ const { config } = usePrepareContractWrite({
+ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
+ abi: [
+ {
+ name: 'mint',
+ type: 'function',
+ stateMutability: 'nonpayable',
+ inputs: [],
+ outputs: [],
+ },
+ ],
+ functionName: 'mint',
+ })
+ const { data, write } = useContractWrite(config)
+
+ const { isLoading, isSuccess } = useWaitForTransaction({
+ hash: data?.hash,
+ })
+
+ return (
+
+ )
+}
+```
+
+## Wrap Up
+
+That's it! You have now added a basic "Mint NFT" component to your app.
diff --git a/docs/pages/examples/custom-connector.en-US.mdx b/docs/pages/examples/custom-connector.en-US.mdx
new file mode 100644
index 0000000000..815f81be5e
--- /dev/null
+++ b/docs/pages/examples/custom-connector.en-US.mdx
@@ -0,0 +1,76 @@
+---
+title: 'Create Custom Connector Example'
+description: 'Learn how to build a custom connector for wagmi'
+---
+
+# Create Custom Connector
+
+wagmi has a number of [built-in](/react/connectors/injected) [Connectors](/react/connectors/walletconnect) that cover support for tens of millions of wallets. If none of the built-in connectors work for your app, you can create a custom Connector. Creating a custom Connector is surprisingly easy to do.
+
+## Prerequisite: Decide What Type of Connector to Create
+
+You can ask yourself the following questions to decide what type of connector to create:
+
+- **Do you want to create a connector for an [injected](/react/connectors/injected) wallet (e.g. browser wallet or extension)?** You can likely extend the `InjectedConnector` class. The `MetaMaskConnector` is a good example of this (check out the [source code](https://github.com/wagmi-dev/wagmi/blob/main/packages/core/src/connectors/metaMask.ts) for more info).
+- **Do you want to create a non-injected connector (e.g. wrap an existing SDK)?** Both `WalletConnectConnector` and `CoinbaseWalletConnector` wrap underlying SDKs and are good examples of this. Continue reading to learn more!
+
+## Step 1: Extend Connector
+
+Create a new class that extends `Connector` and implement required methods. `Connector` is exported by both `wagmi` and `@wagmi/core` packages.
+
+```ts
+import { Connector, Chain } from 'wagmi'
+import { CoolWalletOptions, CoolWalletProvider } from 'cool-wallet-sdk'
+
+export class CoolWalletConnector extends Connector<
+ CoolWalletProvider,
+ CoolWalletOptions
+> {
+ readonly id = 'coolWallet'
+ readonly name = 'Cool Wallet'
+ readonly ready = true
+
+ #provider?: CoolWalletProvider
+
+ constructor(config: { chains?: Chain[]; options: CoolWalletOptions }) {
+ super(config)
+ }
+
+ async getProvider() {
+ if (!this.#provider) {
+ this.#provider = new CoolWalletProvider(this.options)
+ }
+ return this.#provider
+ }
+
+ // Implement other methods
+ // connect, disconnect, getAccount, etc.
+}
+```
+
+## Step 2: Use Connector
+
+Once your custom Connector class is set up, you are ready to use it! You can plug it in anywhere built-in connectors work.
+
+```ts
+import { createClient, mainnet } from 'wagmi'
+
+import { CoolWalletConnector } from './CoolWalletConnector'
+
+const connector = new CoolWalletConnector({
+ chains: [mainnet],
+ options: {
+ // Custom connector options
+ },
+})
+
+const client = createClient({
+ connectors: [connector],
+})
+```
+
+## Step 3: Share With Others
+
+Congrats! You created a custom wagmi Connector! Others might benefit from this work and knowledge. You are welcome to publish your custom Connector as a standalone package or tell folks about it by [creating a new GitHub Discussion](https://github.com/wagmi-dev/wagmi/discussions/new?category=show-and-tell).
+
+If the Connector covers a unique/useful use-case and enough folks are interested, it might make sense for your custom Connector to be built into wagmi. You can [start a new discussion](https://github.com/wagmi-dev/wagmi/discussions/new?category=ideas) to tell us more about the use-case, and why it should be included. It's not always possible to add new built-in connectors to wagmi as they increase the surface area for the core team, but it could make sense!
diff --git a/docs/pages/examples/send-transaction.en-US.mdx b/docs/pages/examples/send-transaction.en-US.mdx
new file mode 100644
index 0000000000..e1641f2a10
--- /dev/null
+++ b/docs/pages/examples/send-transaction.en-US.mdx
@@ -0,0 +1,286 @@
+---
+title: 'Send Transaction'
+description: 'Learn how to send transactions with wagmi.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+import { SendTransaction } from '../../components/examples'
+
+# Send Transaction
+
+The following example teaches you how to send transactions in wagmi. The example below builds on the [Connect Wallet Example](/examples/connect-wallet) and uses the [`usePrepareSendTransaction`](/react/prepare-hooks/usePrepareSendTransaction), [`useSendTransaction`](/react/hooks/useSendTransaction) & [`useWaitForTransaction`](/react/hooks/useWaitForTransaction) hooks. Try it out before moving on.
+
+
+
+## Step 1: Connect Wallet
+
+Follow the [Connect Wallet](/examples/connect-wallet#step-1-configuring-connectors) guide to get this set up.
+
+## Step 2: Create a new component
+
+Create a new component that will contain the send transaction logic.
+
+```tsx
+import * as React from 'react'
+
+export function SendTransaction() {
+ return (
+
+ )
+}
+```
+
+## Step 3: Set up some form state
+
+Hook up your form to some simple state.
+
+```tsx {4,6,12,14,18,20,22}
+import * as React from 'react'
+
+export function SendTransaction() {
+ const [to, setTo] = React.useState('')
+
+ const [amount, setAmount] = React.useState('')
+
+ return (
+
+ )
+}
+```
+
+## Step 4: Add the `usePrepareSendTransaction` hook
+
+Create a new component and add the [`usePrepareSendTransaction` hook](/react/prepare-hooks/usePrepareSendTransaction). This hook eagerly fetches the parameters required for sending a transaction such as the gas estimate.
+
+You will need to:
+
+1. Add the hook
+2. Add a debounce to your input values (we don't want to call the RPC on every keystroke – we are using the [`use-debounce` package](https://github.com/xnimorz/use-debounce) in this example)
+3. Pass these values to `usePrepareSendTransaction`
+
+```tsx {2,3,7,10,12-17}
+import * as React from 'react'
+import { useDebounce } from 'use-debounce'
+import { usePrepareSendTransaction } from 'wagmi'
+import { utils } from 'ethers'
+
+export function SendTransaction() {
+ const [to, setTo] = React.useState('')
+ const [debouncedTo] = useDebounce(to, 500)
+
+ const [amount, setAmount] = React.useState('')
+ const [debouncedAmount] = useDebounce(amount, 500)
+
+ const { config } = usePrepareSendTransaction({
+ request: {
+ to: debouncedTo,
+ value: debouncedAmount ? utils.parseEther(debouncedAmount) : undefined,
+ },
+ })
+
+ return (
+
+ )
+}
+```
+
+## Step 5: Add the `useSendTransaction` hook
+
+Now add the [`useSendTransaction` hook](/react/hooks/useSendTransaction). This hook performs the actual transaction.
+
+We will need to:
+
+1. Add the hook.
+2. Pass in the configuration (`config`) that we created in the previous step.
+3. Hook it up to our form element via an `onSubmit` prop.
+4. Disable the "Send" button when the `sendTransaction` function is not ready (still preparing).
+
+```tsx {3,19,23-26,40}
+import * as React from 'react'
+import { useDebounce } from 'use-debounce'
+import { usePrepareSendTransaction, useSendTransaction } from 'wagmi'
+import { utils } from 'ethers'
+
+export function SendTransaction() {
+ const [to, setTo] = React.useState('')
+ const [debouncedTo] = useDebounce(to, 500)
+
+ const [amount, setAmount] = React.useState('')
+ const [debouncedAmount] = useDebounce(amount, 500)
+
+ const { config } = usePrepareSendTransaction({
+ request: {
+ to: debouncedTo,
+ value: debouncedAmount ? utils.parseEther(debouncedAmount) : undefined,
+ },
+ })
+ const { sendTransaction } = useSendTransaction(config)
+
+ return (
+
+ )
+}
+```
+
+Clicking the "Send" button will trigger the `sendTransaction` function and instantiate the transaction.
+
+However, there is currently no feedback on the status of the transaction. We will add some feedback in the next step.
+
+
+ [Why do I need a `usePrepareSendTransaction` & `useSendTransaction`
+ hook?](/react/prepare-hooks)
+
+
+## Step 6: Add the `useWaitForTransaction` hook
+
+Using the [`useWaitForTransaction` hook](/react/hooks/useWaitForTransaction) provides you with the ability to show feedback on the status of the transaction to the user.
+
+We will need to:
+
+1. Add the hook
+2. Add loading state to the button when the transaction is pending.
+3. Add a success state for when the transaction is successful.
+
+```tsx {6,25-27,48-58}
+import * as React from 'react'
+import { useDebounce } from 'use-debounce'
+import {
+ usePrepareSendTransaction,
+ useSendTransaction,
+ useWaitForTransaction,
+} from 'wagmi'
+import { utils } from 'ethers'
+
+export function SendTransaction() {
+ const [to, setTo] = React.useState('')
+ const [debouncedTo] = useDebounce(to, 500)
+
+ const [amount, setAmount] = React.useState('')
+ const [debouncedAmount] = useDebounce(amount, 500)
+
+ const { config } = usePrepareSendTransaction({
+ request: {
+ to: debouncedTo,
+ value: debouncedAmount ? utils.parseEther(debouncedAmount) : undefined,
+ },
+ })
+ const { data, sendTransaction } = useSendTransaction(config)
+
+ const { isLoading, isSuccess } = useWaitForTransaction({
+ hash: data?.hash,
+ })
+
+ return (
+
+ )
+}
+```
+
+## Step 7: Add To App
+
+Import the `SendTransaction` component and display it when the account is connected.
+
+```tsx {3,12}
+import { useAccount, useConnect, useDisconnect } from 'wagmi'
+
+import { SendTransaction } from './SendTransaction'
+
+export function App() {
+ const { isConnected } = useAccount()
+
+ if (isConnected) {
+ return (
+
+ {/* Account content goes here */}
+
+
+ )
+ }
+
+ return
{/* Connect wallet content goes here */}
+}
+```
+
+## Wrap Up
+
+That's it! You have now added a basic send transaction component to your app.
diff --git a/docs/pages/examples/sign-in-with-ethereum.en-US.mdx b/docs/pages/examples/sign-in-with-ethereum.en-US.mdx
new file mode 100644
index 0000000000..5951d8b01f
--- /dev/null
+++ b/docs/pages/examples/sign-in-with-ethereum.en-US.mdx
@@ -0,0 +1,358 @@
+---
+title: 'Sign-In with Ethereum Example'
+description: 'Learn how to use the SIWE authentication standard with wagmi.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+import { SignInWithEthereum } from '../../components/examples'
+
+# Sign-In with Ethereum
+
+[Sign-In with Ethereum](https://login.xyz) is an authentication standard ([EIP-4361](https://docs.login.xyz/general-information/siwe-overview/eip-4361)) that enables secure communication between a frontend and backend. SIWE is a powerful method for creating user sessions based on a wallet connection, and much more!
+
+The example below builds on the [Connect Wallet](/examples/connect-wallet) and [Sign Message](/examples/sign-message) examples. Try it out before moving on.
+
+
+
+Pretty cool, right?! You can refresh the window or disconnect your wallet, and you are still securely logged in.
+
+## Overview
+
+Implementing SIWE only takes four steps:
+
+1. Connect wallet
+2. Sign SIWE message with nonce generated by backend
+3. Verify submitted SIWE message and signature via POST request
+4. Add validated SIWE fields to session (via JWT, cookie, etc.)
+
+
+ This guide uses Next.js [API
+ Routes](https://nextjs.org/docs/api-routes/introduction) for the backend and
+ [`iron-session`](https://github.com/vvo/iron-session) to secure the user
+ session, but you can also use other backend frameworks and storage methods.
+
+
+## Prerequisites
+
+Install [`siwe`](https://www.npmjs.com/package/siwe) and [`iron-session`](https://github.com/vvo/iron-session) with your package manager of choice:
+
+```plaintext
+npm install siwe iron-session
+```
+
+
+ `iron-session` TypeScript Set Up
+In order for TypeScript to work properly with `iron-session` and `siwe`, you need to add a couple properties to the `IronSessionData` interface. Add the following to `types/iron-session/index.d.ts`.
+
+```ts filename="types/iron-session/index.d.ts"
+import 'iron-session'
+import { SiweMessage } from 'siwe'
+
+declare module 'iron-session' {
+ interface IronSessionData {
+ nonce?: string
+ siwe?: SiweMessage
+ }
+}
+```
+
+Then, update your `tsconfig.json` to include the custom types directory:
+
+```diff filename="tsconfig.json"
+{
+ "compilerOptions": {
+ // ...
+ },
+- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
++ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "types/**/*.d.ts"],
+ "exclude": ["node_modules"]
+}
+```
+
+
+
+## Step 1: Connect Wallet
+
+Follow the [Connect Wallet](/examples/connect-wallet#step-1-configuring-connectors) guide to get this set up.
+
+## Step 2: Add API routes
+
+First, create an API route for generating a random nonce. This is used to identify the session and prevent against [replay attacks](https://en.wikipedia.org/wiki/Replay_attack).
+
+```ts filename="pages/api/nonce.ts" {9-10}
+import { withIronSessionApiRoute } from 'iron-session/next'
+import { NextApiRequest, NextApiResponse } from 'next'
+import { generateNonce } from 'siwe'
+
+const handler = async (req: NextApiRequest, res: NextApiResponse) => {
+ const { method } = req
+ switch (method) {
+ case 'GET':
+ req.session.nonce = generateNonce()
+ await req.session.save()
+ res.setHeader('Content-Type', 'text/plain')
+ res.send(req.session.nonce)
+ break
+ default:
+ res.setHeader('Allow', ['GET'])
+ res.status(405).end(`Method ${method} Not Allowed`)
+ }
+}
+
+export default withIronSessionApiRoute(handler, ironOptions)
+```
+
+Next, add an API route for verifying a SIWE message and creating the user session.
+
+```ts filename="pages/api/verify.ts" {11-12,14,17-18}
+import { withIronSessionApiRoute } from 'iron-session/next'
+import { NextApiRequest, NextApiResponse } from 'next'
+import { SiweMessage } from 'siwe'
+
+const handler = async (req: NextApiRequest, res: NextApiResponse) => {
+ const { method } = req
+ switch (method) {
+ case 'POST':
+ try {
+ const { message, signature } = req.body
+ const siweMessage = new SiweMessage(message)
+ const fields = await siweMessage.validate(signature)
+
+ if (fields.nonce !== req.session.nonce)
+ return res.status(422).json({ message: 'Invalid nonce.' })
+
+ req.session.siwe = fields
+ await req.session.save()
+ res.json({ ok: true })
+ } catch (_error) {
+ res.json({ ok: false })
+ }
+ break
+ default:
+ res.setHeader('Allow', ['POST'])
+ res.status(405).end(`Method ${method} Not Allowed`)
+ }
+}
+
+export default withIronSessionApiRoute(handler, ironOptions)
+```
+
+`ironOptions` should look something like this:
+
+```ts
+{
+ cookieName: 'siwe',
+ password: 'complex_password_at_least_32_characters_long',
+ cookieOptions: {
+ secure: process.env.NODE_ENV === 'production',
+ },
+}
+```
+
+Finally, add two simple API routes for retrieving the signed-in user:
+
+```ts filename="pages/api/me.ts"
+import { withIronSessionApiRoute } from 'iron-session/next'
+import { NextApiRequest, NextApiResponse } from 'next'
+
+const handler = async (req: NextApiRequest, res: NextApiResponse) => {
+ const { method } = req
+ switch (method) {
+ case 'GET':
+ res.send({ address: req.session.siwe?.address })
+ break
+ default:
+ res.setHeader('Allow', ['GET'])
+ res.status(405).end(`Method ${method} Not Allowed`)
+ }
+}
+
+export default withIronSessionApiRoute(handler, ironOptions)
+```
+
+And logging out:
+
+```ts filename="pages/api/logout.ts"
+import { withIronSessionApiRoute } from 'iron-session/next'
+import { NextApiRequest, NextApiResponse } from 'next'
+
+const handler = async (req: NextApiRequest, res: NextApiResponse) => {
+ const { method } = req
+ switch (method) {
+ case 'GET':
+ req.session.destroy()
+ res.send({ ok: true })
+ break
+ default:
+ res.setHeader('Allow', ['GET'])
+ res.status(405).end(`Method ${method} Not Allowed`)
+ }
+}
+
+export default withIronSessionApiRoute(handler, ironOptions)
+```
+
+
+ Before going to production, you likely want to invalidate nonces on logout to prevent replay attacks through session duplication (e.g. store expired nonce and make sure they can't be used again).
+
+
+## Step 3: Sign & Verify Message
+
+Now that the connect wallet logic and API routes are set up, we can sign in the user! We'll create a new `SiweMessage` and sign it using the [`useSignMessage`](/react/hooks/useSignMessage) hook. We can also add a log out button and a side effect for fetching the logged in user when the page loads or window gains focus.
+
+```tsx {19,43-53,58-65,97,120}
+import * as React from 'react'
+import { useAccount, useNetwork, useSignMessage } from 'wagmi'
+import { SiweMessage } from 'siwe'
+
+function SignInButton({
+ onSuccess,
+ onError,
+}: {
+ onSuccess: (args: { address: string }) => void
+ onError: (args: { error: Error }) => void
+}) {
+ const [state, setState] = React.useState<{
+ loading?: boolean
+ nonce?: string
+ }>({})
+
+ const fetchNonce = async () => {
+ try {
+ const nonceRes = await fetch('/api/nonce')
+ const nonce = await nonceRes.text()
+ setState((x) => ({ ...x, nonce }))
+ } catch (error) {
+ setState((x) => ({ ...x, error: error as Error }))
+ }
+ }
+
+ // Pre-fetch random nonce when button is rendered
+ // to ensure deep linking works for WalletConnect
+ // users on iOS when signing the SIWE message
+ React.useEffect(() => {
+ fetchNonce()
+ }, [])
+
+ const { address } = useAccount()
+ const { chain } = useNetwork()
+ const { signMessageAsync } = useSignMessage()
+
+ const signIn = async () => {
+ try {
+ const chainId = chain?.id
+ if (!address || !chainId) return
+
+ setState((x) => ({ ...x, loading: true }))
+ // Create SIWE message with pre-fetched nonce and sign with wallet
+ const message = new SiweMessage({
+ domain: window.location.host,
+ address,
+ statement: 'Sign in with Ethereum to the app.',
+ uri: window.location.origin,
+ version: '1',
+ chainId,
+ nonce: state.nonce,
+ })
+ const signature = await signMessageAsync({
+ message: message.prepareMessage(),
+ })
+
+ // Verify signature
+ const verifyRes = await fetch('/api/verify', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ message, signature }),
+ })
+ if (!verifyRes.ok) throw new Error('Error verifying message')
+
+ setState((x) => ({ ...x, loading: false }))
+ onSuccess({ address })
+ } catch (error) {
+ setState((x) => ({ ...x, loading: false, nonce: undefined }))
+ onError({ error: error as Error })
+ fetchNonce()
+ }
+ }
+
+ return (
+
+ )
+}
+
+export function Profile() {
+ const { isConnected } = useAccount()
+
+ const [state, setState] = React.useState<{
+ address?: string
+ error?: Error
+ loading?: boolean
+ }>({})
+
+ // Fetch user when:
+ React.useEffect(() => {
+ const handler = async () => {
+ try {
+ const res = await fetch('/api/me')
+ const json = await res.json()
+ setState((x) => ({ ...x, address: json.address }))
+ } catch (_error) {}
+ }
+ // 1. page loads
+ handler()
+
+ // 2. window is focused (in case user logs out of another window)
+ window.addEventListener('focus', handler)
+ return () => window.removeEventListener('focus', handler)
+ }, [])
+
+ if (isConnected) {
+ return (
+
+}
+```
+
+## Wrap Up
+
+That's it! You now have a way for users to securely sign in to an app using Ethereum wallets. You can start building rich web apps that use persistent user sessions while still letting users control their login identity (and so much more). Check out the [Sign-In with Ethereum](https://login.xyz) website for more info.
+
+
+ While it might be tempting to combine the "Connect Wallet" and "Sign In" steps
+ into a single action, this causes issues with deep linking for WalletConnect
+ on iOS. This is because the browser doesn't open the corresponding native app
+ if the navigation wasn't immediately triggered by a user action.
+
+
+### Additional Resources
+
+- [**Sign-In with Ethereum to Next.js Applications**](https://blog.spruceid.com/sign-in-with-ethereum-on-next-js-applications) Guide for setting up SIWE with [`next-auth`](https://next-auth.js.org) from the [Spruce team](https://www.spruceid.com).
diff --git a/docs/pages/examples/sign-message.en-US.mdx b/docs/pages/examples/sign-message.en-US.mdx
new file mode 100644
index 0000000000..312f0c4d88
--- /dev/null
+++ b/docs/pages/examples/sign-message.en-US.mdx
@@ -0,0 +1,99 @@
+---
+title: 'Sign Message Example'
+description: 'Learn how to sign messages with wagmi.'
+---
+
+import { SignMessage } from '../../components/examples'
+
+# Sign Message
+
+Signing messages is a great way to securely prove control of a specific address. The example below builds on the [Connect Wallet Example](/examples/connect-wallet) and uses the [`useSignMessage`](/react/hooks/useSignMessage) hook. Try it out before moving on.
+
+
+
+## Step 1: Connect Wallet
+
+Follow the [Connect Wallet](/examples/connect-wallet#step-1-configuring-connectors) guide to get this set up.
+
+## Step 2: Add SignMessage Component
+
+Add the `useSignMessage` hook and set up a basic form:
+
+```tsx
+import * as React from 'react'
+import { useSignMessage } from 'wagmi'
+import { verifyMessage } from 'ethers/lib/utils'
+
+export function SignMessage() {
+ const recoveredAddress = React.useRef()
+ const { data, error, isLoading, signMessage } = useSignMessage({
+ onSuccess(data, variables) {
+ // Verify signature when sign message succeeds
+ const address = verifyMessage(variables.message, data)
+ recoveredAddress.current = address
+ },
+ })
+
+ return (
+
+ )
+}
+```
+
+## Step 3: Add To App
+
+Import the `SignMessage` component and display it when the account is connected.
+
+```tsx
+import { useAccount, useConnect, useDisconnect } from 'wagmi'
+
+import { SignMessage } from './SignMessage'
+
+export function Profile() {
+ const { isConnected } = useAccount()
+ const { connect, connectors, error, isLoading, pendingConnector } =
+ useConnect()
+ const { disconnect } = useDisconnect()
+
+ if (isConnected) {
+ return (
+
+ {/* Account content goes here */}
+
+
+ )
+ }
+
+ return
{/* Connect wallet content goes here */}
+}
+```
+
+## Wrap Up
+
+That's it! You now have a way for users to sign messages and securely prove control over a wallet address.
diff --git a/docs/pages/index.en-US.mdx b/docs/pages/index.en-US.mdx
new file mode 100644
index 0000000000..ea3e2367d9
--- /dev/null
+++ b/docs/pages/index.en-US.mdx
@@ -0,0 +1,122 @@
+---
+title: 'wagmi: React Hooks for Ethereum'
+---
+
+import { Tabs, Tab } from 'nextra-theme-docs'
+
+import { Header } from '../components/docs'
+import { Sponsors } from '../components/docs'
+
+= new Date('2022-09-07') && new Date() < new Date('2022-09-23')} />
+
+**wagmi** is a collection of React Hooks containing everything you need to start working with Ethereum. wagmi makes it easy to "Connect Wallet," display ENS and balance information, sign messages, interact with contracts, and much more — all with caching, request deduplication, and persistence.
+
+{/* prettier-ignore-start */}
+
+ )
+ return
+}
+```
+
+In this example, we create a wagmi `Client` and pass it to the `WagmiConfig` React Context. The client is set up to use the ethers Default Provider and automatically connect to previously connected wallets.
+
+Next, we use the `useConnect` hook to connect an injected wallet (e.g. MetaMask) to the app. Finally, we show the connected account's address with `useAccount` and allow them to disconnect with `useDisconnect`.
+
+We've only scratched the surface for what you can do with wagmi!
+
+## Features
+
+wagmi supports all these features out-of-the-box:
+
+- 20+ hooks for working with wallets, ENS, contracts, transactions, signing, etc.
+- Built-in wallet connectors for MetaMask, WalletConnect, Coinbase Wallet, Injected, and more
+- Caching, request deduplication, multicall, batching, and persistence
+- Auto-refresh data on wallet, block, and network changes
+- TypeScript ready (infer types from ABIs and EIP-712 Typed Data)
+- Command-line interface for managing ABIs and code generation
+- Test suite running against forked Ethereum network
+
+...and a lot more.
+
+## Community
+
+Check out the following places for more wagmi-related content:
+
+- Follow [@wagmi_sh](https://twitter.com/wagmi_sh), [@awkweb](https://twitter.com/awkweb), and [@jakemoxey](https://twitter.com/jakemoxey) on Twitter for project updates
+- Join the [discussions on GitHub](https://github.com/wagmi-dev/wagmi/discussions)
+- Share [your project/organization](https://github.com/wagmi-dev/wagmi/discussions/201) that uses wagmi
+- Browse the [awesome-wagmi](https://github.com/wagmi-dev/awesome-wagmi) list of awesome projects and resources
+
+## Support
+
+Help support future development and make wagmi a sustainable open-source project. Thank you 🙏
+
+- [GitHub Sponsors](https://github.com/sponsors/wagmi-dev?metadata_campaign=docs_support)
+- [Gitcoin Grant](https://wagmi.sh/gitcoin)
+- [wagmi-dev.eth](https://etherscan.io/enslookup-search?search=wagmi-dev.eth)
+
+## Sponsors
+
+
diff --git a/docs/pages/index.zh-CN.mdx b/docs/pages/index.zh-CN.mdx
new file mode 100644
index 0000000000..5087c47f5d
--- /dev/null
+++ b/docs/pages/index.zh-CN.mdx
@@ -0,0 +1,125 @@
+---
+title: 'wagmi: React Hooks for Ethereum'
+---
+
+import { Tabs, Tab } from 'nextra-theme-docs'
+
+import { Header } from '../components/docs'
+import { Sponsors } from '../components/docs'
+
+= new Date('2022-09-07') && new Date() < new Date('2022-09-23')
+ }
+/>
+
+**wagmi** 是一个 React Hook 的集合,包含了你与以太坊交互所需的一切。wagmi 使连接钱包、显示 ENS 和余额信息、签署消息、与合约交互等变得简单——所有这些都有缓存、重复请求降重和持久化。
+
+{/* prettier-ignore-start */}
+
}
+ >
+ )
+}
+```
+
+## Return Value
+
+```tsx
+{
+ connect: (
+ config: { connector?: Connector; chainId?: number },
+ ) => void
+ connectAsync: (
+ config: { connector?: Connector; chainId?: number },
+ ) => Promise<{
+ account: `0x${string}`
+ chain: {
+ id: number
+ unsupported?: boolean
+ }
+ connector: Connector
+ provider: Provider
+ }>
+ connectors: Connector[]
+ data?: {
+ account: `0x${string}`
+ chain: {
+ id: number
+ unsupported?: boolean
+ }
+ connector: Connector
+ provider: Provider
+ }
+ error?: Error
+ isError: boolean
+ isIdle: boolean
+ isLoading: boolean
+ isSuccess: boolean
+ pendingConnector: Connector
+ reset: () => void
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### chainId (optional)
+
+Chain ID to connect.
+
+```tsx {6}
+import { chain, useConnect } from 'wagmi'
+import { optimism } from 'wagmi/chains'
+
+function App() {
+ const connect = useConnect({
+ chainId: optimism.id,
+ })
+}
+```
+
+Note: The above example is using the `optimism` chain from the [`wagmi/chains` entrypoint](/react/chains#wagmichains).
+
+### connector (optional)
+
+Connector to use for connecting wallet. Useful if you want to connect to a specific connector, instead of [displaying a list](/react/hooks/useConnect#usage).
+
+```tsx {6}
+import { useConnect } from 'wagmi'
+import { InjectedConnector } from 'wagmi/connectors/injected'
+
+function App() {
+ const connect = useConnect({
+ connector: new InjectedConnector(),
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while connecting.
+
+```tsx {5-7}
+import { useConnect } from 'wagmi'
+
+function App() {
+ const connect = useConnect({
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onMutate (optional)
+
+Function to invoke before connect and is passed same variables connect function would receive. Value returned from this function will be passed to both `onError` and `onSettled` functions in event of a connect failure.
+
+```tsx {5-7}
+import { useConnect } from 'wagmi'
+
+function App() {
+ const connect = useConnect({
+ onMutate(connector) {
+ console.log('Before Connect', connector)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when connect is settled (either successfully connected, or an error has thrown).
+
+```tsx {5-7}
+import { useConnect } from 'wagmi'
+
+function App() {
+ const connect = useConnect({
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when connect is successful.
+
+```tsx {5-7}
+import { useConnect } from 'wagmi'
+
+function App() {
+ const connect = useConnect({
+ onSuccess(data) {
+ console.log('Connect', data)
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useContract.en-US.mdx b/docs/pages/react/hooks/useContract.en-US.mdx
new file mode 100644
index 0000000000..1355e3827e
--- /dev/null
+++ b/docs/pages/react/hooks/useContract.en-US.mdx
@@ -0,0 +1,93 @@
+---
+title: 'useContract'
+description: 'React Hook for declaratively creating an ethers Contract instance.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# useContract
+
+Hook for declaratively creating a type-safe [Contract](https://docs.ethers.io/v5/api/contract/contract) instance.
+
+```tsx
+import { useContract } from 'wagmi'
+```
+
+
+ If needing to invoke a read or write method from a contract, it is recommended
+ to use [`useContractRead`](/react/hooks/useContractRead) or
+ [`useContractWrite`](/react/hooks/useContractWrite) instead of imperatively
+ calling the function.
+
+
+## Usage
+
+The following examples use the [ENS Registry](https://etherscan.io/address/0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e#code) contract.
+
+```tsx
+import { useContract } from 'wagmi'
+
+function App() {
+ const contract = useContract({
+ address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
+ abi: ensRegistryABI,
+ })
+}
+```
+
+## Return Value
+
+```tsx
+ethers.Contract | null
+```
+
+## Configuration
+
+### address (optional)
+
+Contract address. If `address` is not defined, response is `null`.
+
+```tsx {5}
+import { useContract } from 'wagmi'
+
+function App() {
+ const contract = useContract({
+ address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
+ abi: ensRegistryABI,
+ })
+}
+```
+
+### abi (optional)
+
+Contract ABI. If `abi` is not defined, response is `null`.
+
+By defining inline or adding a [const assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) to `abi`, TypeScript will infer the correct types for properties and methods on the contract object. See the wagmi [TypeScript docs](/react/typescript) for more information.
+
+```tsx {6}
+import { useContract } from 'wagmi'
+
+function App() {
+ const contract = useContract({
+ address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
+ abi: ensRegistryABI,
+ })
+}
+```
+
+### signerOrProvider (optional)
+
+An ethers [Provider](https://docs.ethers.io/v5/api/providers/provider/#Provider) or [Signer](https://docs.ethers.io/v5/api/signer/#Signer).
+
+```tsx {8}
+import { useContract, useProvider } from 'wagmi'
+
+function App() {
+ const provider = useProvider()
+ const contract = useContract({
+ address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
+ abi: ensRegistryABI,
+ signerOrProvider: provider,
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useContractEvent.en-US.mdx b/docs/pages/react/hooks/useContractEvent.en-US.mdx
new file mode 100644
index 0000000000..9403e0854e
--- /dev/null
+++ b/docs/pages/react/hooks/useContractEvent.en-US.mdx
@@ -0,0 +1,151 @@
+---
+title: 'useContractEvent'
+description: 'React Hook for subscribing to ethers Contract events.'
+---
+
+# useContractEvent
+
+Hook for subscribing to ethers Contract [events](https://docs.ethers.io/v5/api/contract/contract/#Contract--events).
+
+```tsx
+import { useContractEvent } from 'wagmi'
+```
+
+## Usage
+
+The following examples use the [ENS Registry](https://etherscan.io/address/0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e#code) contract.
+
+```tsx
+import { useContractEvent } from 'wagmi'
+
+function App() {
+ useContractEvent({
+ address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
+ abi: ensRegistryABI,
+ eventName: 'NewOwner',
+ listener(node, label, owner) {
+ console.log(node, label, owner)
+ },
+ })
+}
+```
+
+## Configuration
+
+### address (optional)
+
+Contract address. If `address` is not defined, hook will not run.
+
+```tsx {5}
+import { useContractEvent } from 'wagmi'
+
+function App() {
+ useContractEvent({
+ address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
+ abi: ensRegistryABI,
+ eventName: 'NewOwner',
+ listener(node, label, owner) {
+ console.log(node, label, owner)
+ },
+ })
+}
+```
+
+### abi (optional)
+
+Contract ABI. If `abi` is not defined, hook will not run.
+
+By defining inline or adding a [const assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) to `abi`, TypeScript will infer the correct types for `eventName` and `listener`. See the wagmi [TypeScript docs](/react/typescript) for more information.
+
+```tsx {6}
+import { useContractEvent } from 'wagmi'
+
+function App() {
+ useContractEvent({
+ address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
+ abi: ensRegistryABI,
+ eventName: 'NewOwner',
+ listener(node, label, owner) {
+ console.log(node, label, owner)
+ },
+ })
+}
+```
+
+### eventName (optional)
+
+Name of the event to listen to. If `eventName` is not defined, hook will not run.
+
+```tsx {7}
+import { useContractEvent } from 'wagmi'
+
+function App() {
+ useContractEvent({
+ address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
+ abi: ensRegistryABI,
+ eventName: 'NewResolver',
+ listener(node, resolver) {
+ console.log(node, resolver)
+ },
+ })
+}
+```
+
+### listener
+
+Callback that receives event.
+
+```tsx {8-10}
+import { useContractEvent } from 'wagmi'
+
+function App() {
+ useContractEvent({
+ address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
+ abi: ensRegistryABI,
+ eventName: 'NewOwner',
+ listener(node, label, owner) {
+ console.log(node, label, owner)
+ },
+ })
+}
+```
+
+### chainId (optional)
+
+Force a specific chain id. The wagmi `Client`'s ethers `webSocketProvider` must be set up as a [chain-aware function](/react/client#websocketprovider-optional) for this to work correctly.
+
+```tsx {11}
+import { useContractEvent } from 'wagmi'
+
+function App() {
+ useContractEvent({
+ address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
+ abi: ensRegistryABI,
+ eventName: 'NewOwner',
+ listener(node, label, owner) {
+ console.log(node, label, owner)
+ },
+ chainId: 1,
+ })
+}
+```
+
+### once (optional)
+
+Receive only a single event, then stop listener. Defaults to `false`.
+
+```tsx {11}
+import { useContractEvent } from 'wagmi'
+
+function App() {
+ useContractEvent({
+ address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
+ abi: ensRegistryABI,
+ eventName: 'NewOwner',
+ listener(node, label, owner) {
+ console.log(node, label, owner)
+ },
+ once: true,
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useContractInfiniteReads.en-US.mdx b/docs/pages/react/hooks/useContractInfiniteReads.en-US.mdx
new file mode 100644
index 0000000000..91db8020d4
--- /dev/null
+++ b/docs/pages/react/hooks/useContractInfiniteReads.en-US.mdx
@@ -0,0 +1,763 @@
+---
+title: 'useContractInfiniteReads'
+description: 'React Hook for calling multiple ethers Contract read-only methods with "infinite scrolling" ("fetch more") support. Useful for rendering a dynamic list of contract data.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# useContractInfiniteReads
+
+Hook for calling multiple ethers Contract [read-only](https://docs.ethers.io/v5/api/contract/contract/#Contract--readonly) methods with "infinite scrolling" ("fetch more") support. Useful for rendering a dynamic list of contract data.
+
+```tsx
+import { useContractInfiniteReads } from 'wagmi'
+```
+
+## Usage
+
+The following example uses the [more loot](https://etherscan.io/address/0x1dfe7ca09e99d10835bf73044a23b73fc20623df) contract.
+
+The `useContractInfiniteReads` hook requires:
+
+- `cacheKey`: unique key to store the data in the cache
+- `contracts`: a function that provides a `param` (derived from `getNextPageParam` or `fetchNextPage`) as an argument and expects to return an array of contracts. In the example below, `param` is the token ID.
+
+```tsx
+import { BigNumber } from 'ethers'
+import { useContractInfiniteReads } from 'wagmi'
+import mlootABI from './mlootABI.json'
+
+const mlootContractConfig = {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+}
+
+function App() {
+ const { data, fetchNextPage } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ { ...mlootContractConfig, functionName: 'getChest', args },
+ { ...mlootContractConfig, functionName: 'getFoot', args },
+ { ...mlootContractConfig, functionName: 'getHand', args },
+ ],
+ },
+ })
+}
+```
+
+You can also optionally provide `getNextPageParam` which will derive the `param` provided to `contracts`. In the example below, we want the `param` to increment by 1.
+
+```tsx {12}
+function App() {
+ const { data, fetchNextPage } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ { ...mlootContractConfig, functionName: 'getChest', args },
+ { ...mlootContractConfig, functionName: 'getFoot', args },
+ { ...mlootContractConfig, functionName: 'getHand', args },
+ ],
+ },
+ getNextPageParam: (_, pages) => pages.length + 1,
+ })
+}
+```
+
+### Paginated indexes
+
+Import the `paginatedIndexesConfig` helper to assist with paginated indexes. Useful for infinite pagination of token IDs.
+
+In the example below, we are fetching 10 `tokenURI`s at a time from the [more loot](https://etherscan.io/address/0x1dfe7ca09e99d10835bf73044a23b73fc20623df) contract.
+
+```tsx
+import { BigNumber } from 'ethers'
+import { useContractInfiniteReads, paginatedIndexesConfig } from 'wagmi'
+import mlootABI from './mlootABI.json'
+
+const mlootContractConfig = {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+}
+
+function App() {
+ const { data, fetchNextPage } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ ...paginatedIndexesConfig(
+ (index) => {
+ return [
+ {
+ ...mlootContractConfig,
+ functionName: 'tokenURI',
+ args: [BigNumber.from(index)] as const,
+ },
+ ]
+ },
+ { start: 0, perPage: 10, direction: 'increment' },
+ ),
+ })
+}
+```
+
+## Return Value
+
+```tsx
+{
+ data: {
+ pages: Result[][]
+ pageParam: PageParam
+ }
+ error?: Error
+ fetchNextPage: (options?: FetchNextPageOptions) => Promise
+ hasNextPage: boolean
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isFetchingNextPage: boolean;
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ refetch: (options: {
+ throwOnError: boolean
+ cancelRefetch: boolean
+ }) => Promise
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### cacheKey
+
+Unique key used to store the data in the cache.
+
+```tsx {5}
+import { useContractInfiniteReads } from 'wagmi'
+
+function App() {
+ const { data, fetchNextPage } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ { ...mlootContractConfig, functionName: 'getChest', args },
+ { ...mlootContractConfig, functionName: 'getFoot', args },
+ { ...mlootContractConfig, functionName: 'getHand', args },
+ ],
+ },
+ })
+}
+```
+
+### contracts
+
+#### address
+
+Contract address.
+
+```tsx {11,17}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ })
+}
+```
+
+#### abi
+
+Contract ABI.
+
+By defining inline or adding a [const assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) to `abi`, TypeScript will infer the correct types for `functionName`, `args`, and hook result. See the wagmi [TypeScript docs](/react/typescript) for more information.
+
+```tsx {12,18}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ })
+}
+```
+
+#### functionName
+
+Name of function to call.
+
+```tsx {13,19}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ })
+}
+```
+
+#### args
+
+Arguments to pass to function call.
+
+```tsx {14,20}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ })
+}
+```
+
+#### chainId
+
+Force a specific chain id for the request. The wagmi `Client`'s ethers `provider` must be set up as a [chain-aware function](/react/client#provider-optional) for this to work correctly.
+
+```tsx {16,23}
+import { useContractReads } from 'wagmi'
+import { optimism } from 'wagmi/chains'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ chainId: optimism.id,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ chainId: optimism.id,
+ },
+ ]
+ },
+ })
+}
+```
+
+Note: The above example is using the `optimism` chain from the [`wagmi/chains` entrypoint](/react/chains#wagmichains).
+
+### getNextPageParam (optional)
+
+Derives the `param` provided to `contracts`. Provides the last page of the infinite list and an array of pages.
+
+If there is no next page available, return `undefined`.
+
+```tsx {24-25}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ getNextPageParam: (lastPage, allPages) =>
+ !lastPage ? allPages.length + 1 : undefined,
+ })
+}
+```
+
+### allowFailure (optional)
+
+If a contract read fails while fetching, it will fail silently and not throw an error.
+
+```tsx {24}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ allowFailure: false,
+ })
+}
+```
+
+### overrides (optional)
+
+Overrides to pass to function call.
+
+```tsx {24}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ overrides: { from: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e' },
+ })
+}
+```
+
+### cacheTime (optional)
+
+Time (in ms) which the data should remain in the cache. Defaults to `0`.
+
+```tsx {24}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ cacheTime: 2_000,
+ })
+}
+```
+
+### enabled (optional)
+
+Set this to `false` to disable this query from automatically running. Defaults to `true`.
+
+```tsx {24}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ enabled: false,
+ })
+}
+```
+
+### isDataEqual (deprecated, optional)
+
+Use [`structuralSharing`](#structuralsharing-optional) instead.
+
+```tsx {24}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ isDataEqual: (prev, next) => prev === next,
+ })
+}
+```
+
+### staleTime (optional)
+
+Time (in ms) after data is considered stale. If set to `Infinity` the data will never be considered stale. Defaults to `0`.
+
+```tsx {24}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ staleTime: 2_000,
+ })
+}
+```
+
+### select (optional)
+
+Transform or select a part of the data returned by the contract.
+
+```tsx {24}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ select: (data) => transform(data),
+ })
+}
+```
+
+### structuralSharing (optional)
+
+Keep referential identity of data and prevent rerenders. Defaults to `(oldData, newData) => deepEqual(oldData, newData) ? oldData : replaceEqualDeep(oldData, newData)`. If set to `false`, structural sharing between query results will be disabled.
+
+If set to a function, the old and new data values will be passed through this function, which should combine them into resolved data for the query. This way, you can retain references from the old data to improve performance even when that data contains non-serializable values.
+
+```tsx {24}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ structuralSharing: (prev, next) => (prev === next ? prev : next),
+ })
+}
+```
+
+### suspense (optional)
+
+Set this to `true` to enable suspense mode.
+
+```tsx {24}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ suspense: true,
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching new data is successful.
+
+```tsx {24-26}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {24-26}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ onError(error) {
+ console.log('error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {24-26}
+import { useContractInfiniteReads } from 'wagmi'
+import { BigNumber } from 'ethers'
+
+function App() {
+ const { data, isError, isLoading } = useContractInfiniteReads({
+ cacheKey: 'mlootAttributes',
+ contracts(param = 0) {
+ const args = [BigNumber.from(param)] as const
+ return [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args,
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args,
+ },
+ ]
+ },
+ onSettled(data) {
+ console.log('Settled', data)
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useContractRead.en-US.mdx b/docs/pages/react/hooks/useContractRead.en-US.mdx
new file mode 100644
index 0000000000..f93db5fac9
--- /dev/null
+++ b/docs/pages/react/hooks/useContractRead.en-US.mdx
@@ -0,0 +1,382 @@
+---
+title: 'useContractRead'
+description: 'React Hook for calling an ethers Contract read-only method.'
+---
+
+# useContractRead
+
+Hook for calling an ethers Contract [read-only](https://docs.ethers.io/v5/api/contract/contract/#Contract--readonly) method.
+
+```tsx
+import { useContractRead } from 'wagmi'
+```
+
+## Usage
+
+The following examples use the [wagmigotchi](https://etherscan.io/address/0xecb504d39723b0be0e3a9aa33d646642d1051ee1) contract.
+
+```tsx
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getHunger',
+ })
+}
+```
+
+## Return Value
+
+```tsx
+{
+ data?: Result
+ error?: Error
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ refetch: (options: {
+ throwOnError: boolean
+ cancelRefetch: boolean
+ }) => Promise
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### address (optional)
+
+Contract address. If `address` is not defined, hook will not run.
+
+```tsx {5}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ })
+}
+```
+
+### abi (optional)
+
+Contract ABI. If `abi` is not defined, hook will not run.
+
+By defining inline or adding a [const assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) to `abi`, TypeScript will infer the correct types for `functionName`, `args`, and hook result. See the wagmi [TypeScript docs](/react/typescript) for more information.
+
+```tsx {6}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ })
+}
+```
+
+### functionName (optional)
+
+Name of function to call. If `functionName` is not defined, hook will not run.
+
+```tsx {7}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ })
+}
+```
+
+### args (optional)
+
+Arguments to pass to function call.
+
+```tsx {8}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'love',
+ args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'],
+ })
+}
+```
+
+### chainId (optional)
+
+Force a specific chain id for the request. The wagmi `Client`'s ethers `provider` must be set up as a [chain-aware function](/react/client#provider-optional) for this to work correctly.
+
+```tsx {8}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ chainId: 1,
+ })
+}
+```
+
+### overrides (optional)
+
+Overrides to pass to function call.
+
+```tsx {8}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ overrides: { from: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e' },
+ })
+}
+```
+
+### cacheOnBlock (optional)
+
+Caches & persists the return data against the current block. Data will be considered stale when a new block arrives.
+
+```tsx {8}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ cacheOnBlock: true,
+ })
+}
+```
+
+### watch (optional)
+
+Watches and refreshes data for new blocks.
+
+```tsx {8}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ watch: true,
+ })
+}
+```
+
+### cacheTime (optional)
+
+Time (in ms) which the data should remain in the cache. Defaults to `0`.
+
+```tsx {8}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ cacheTime: 2_000,
+ })
+}
+```
+
+### enabled (optional)
+
+Set this to `false` to disable this query from automatically running. Defaults to `true`.
+
+```tsx {8}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ enabled: false,
+ })
+}
+```
+
+### isDataEqual (deprecated, optional)
+
+Use [`structuralSharing`](#structuralsharing-optional) instead.
+
+```tsx {8}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ isDataEqual: (prev, next) => prev === next,
+ })
+}
+```
+
+### scopeKey (optional)
+
+Scopes the cache to a given context. Hooks that have identical context will share the same cache.
+
+```tsx {7}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ scopeKey: 'wagmi',
+ functionName: 'getSleep',
+ })
+}
+```
+
+### staleTime (optional)
+
+Time (in ms) after data is considered stale. If set to `Infinity` the data will never be considered stale. Defaults to `0`.
+
+```tsx {8}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ staleTime: 2_000,
+ })
+}
+```
+
+### select (optional)
+
+Transform or select a part of the data returned by the contract.
+
+```tsx {8}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ select: (data) => transform(data),
+ })
+}
+```
+
+### structuralSharing (optional)
+
+Keep referential identity of data and prevent rerenders. Defaults to `(oldData, newData) => deepEqual(oldData, newData) ? oldData : replaceEqualDeep(oldData, newData)`. If set to `false`, structural sharing between query results will be disabled.
+
+If set to a function, the old and new data values will be passed through this function, which should combine them into resolved data for the query. This way, you can retain references from the old data to improve performance even when that data contains non-serializable values.
+
+```tsx {8}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ structuralSharing: (prev, next) => (prev === next ? prev : next),
+ })
+}
+```
+
+### suspense (optional)
+
+Set this to `true` to enable suspense mode.
+
+```tsx {8}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ suspense: true,
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching new data is successful.
+
+```tsx {8-10}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {8-10}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {8-10}
+import { useContractRead } from 'wagmi'
+
+function App() {
+ const contractRead = useContractRead({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getSleep',
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useContractReads.en-US.mdx b/docs/pages/react/hooks/useContractReads.en-US.mdx
new file mode 100644
index 0000000000..2186339698
--- /dev/null
+++ b/docs/pages/react/hooks/useContractReads.en-US.mdx
@@ -0,0 +1,584 @@
+---
+title: 'useContractReads'
+description: 'React Hook for calling multiple ethers Contract read-only methods.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# useContractReads
+
+Hook for calling multiple ethers Contract [read-only](https://docs.ethers.io/v5/api/contract/contract/#Contract--readonly) methods.
+
+```tsx
+import { useContractReads } from 'wagmi'
+```
+
+## Usage
+
+The following examples use the [wagmigotchi](https://etherscan.io/address/0xecb504d39723b0be0e3a9aa33d646642d1051ee1) & [more loot](https://etherscan.io/address/0x1dfe7ca09e99d10835bf73044a23b73fc20623df) contracts.
+
+```tsx
+import { useContractReads } from 'wagmi'
+
+const wagmigotchiContract = {
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+}
+const mlootContract = {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+}
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ {
+ ...mlootContract,
+ functionName: 'getChest',
+ args: [69],
+ },
+ {
+ ...mlootContract,
+ functionName: 'getWaist',
+ args: [69],
+ },
+ ],
+ })
+}
+```
+
+## Return Value
+
+```tsx
+{
+ data?: Result[]
+ error?: Error
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ refetch: (options: {
+ throwOnError: boolean
+ cancelRefetch: boolean
+ }) => Promise
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### contracts
+
+#### address (optional)
+
+Contract address. Hook will not run unless `address` is defined for all `contracts`.
+
+```tsx {7,12}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getAlive',
+ },
+ {
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getBoredom',
+ },
+ ],
+ })
+}
+```
+
+#### abi (optional)
+
+Contract ABI. Hook will not run unless `abi` is defined for all `contracts`.
+
+By defining inline or adding a [const assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) to `abi`, TypeScript will infer the correct types for `functionName`, `args`, and hook result. See the wagmi [TypeScript docs](/react/typescript) for more information.
+
+```tsx {8,13}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getAlive',
+ },
+ {
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getBoredom',
+ },
+ ],
+ })
+}
+```
+
+#### functionName (optional)
+
+Name of function to call. Hook will not run unless `functionName` is defined for all `contracts`.
+
+```tsx {9,14}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getAlive',
+ },
+ {
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getBoredom',
+ },
+ ],
+ })
+}
+```
+
+#### args (optional)
+
+Arguments to pass to function call.
+
+```tsx {10,16}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getChest',
+ args: [69],
+ },
+ {
+ address: '0x1dfe7ca09e99d10835bf73044a23b73fc20623df',
+ abi: mlootABI,
+ functionName: 'getWaist',
+ args: [69],
+ },
+ ],
+ })
+}
+```
+
+#### chainId (optional)
+
+Force a specific chain id for the request. The wagmi `Client`'s ethers `provider` must be set up as a [chain-aware function](/react/client#provider-optional) for this to work correctly.
+
+```tsx {10,15}
+import { useContractReads } from 'wagmi'
+import { optimism } from 'wagmi/chains'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ chainId: optimism.id,
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ chainId: optimism.id,
+ },
+ ],
+ })
+}
+```
+
+Note: The above example is using the `optimism` chain from the [`wagmi/chains` entrypoint](/react/chains#wagmichains).
+
+### allowFailure (optional)
+
+If a contract read fails while fetching, it will fail silently and not throw an error.
+
+```tsx {15}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ allowFailure: false,
+ })
+}
+```
+
+### overrides (optional)
+
+Overrides to pass to function call.
+
+```tsx {15}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ overrides: { from: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e' },
+ })
+}
+```
+
+### cacheOnBlock (optional)
+
+Caches & persists the return data against the current block. Data will be considered stale when a new block arrives.
+
+```tsx {15}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ cacheOnBlock: true,
+ })
+}
+```
+
+### watch (optional)
+
+Watches and refreshes data for new blocks.
+
+```tsx {15}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ watch: true,
+ })
+}
+```
+
+### cacheTime (optional)
+
+Time (in ms) which the data should remain in the cache. Defaults to `0`.
+
+```tsx {15}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ cacheTime: 2_000,
+ })
+}
+```
+
+### enabled (optional)
+
+Set this to `false` to disable this query from automatically running. Defaults to `true`.
+
+```tsx {15}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ enabled: false,
+ })
+}
+```
+
+### isDataEqual (deprecated, optional)
+
+Use [`structuralSharing`](#structuralsharing-optional) instead.
+
+```tsx {15}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ isDataEqual: (prev, next) => prev === next,
+ })
+}
+```
+
+### scopeKey (optional)
+
+Scopes the cache to a given context. Hooks that have identical context will share the same cache.
+
+```tsx {5}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ scopeKey: 'wagmi',
+ contracts: [
+ {
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getAlive',
+ },
+ {
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'getBoredom',
+ },
+ ],
+ })
+}
+```
+
+### staleTime (optional)
+
+Time (in ms) after data is considered stale. If set to `Infinity` the data will never be considered stale. Defaults to `0`.
+
+```tsx {15}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ staleTime: 2_000,
+ })
+}
+```
+
+### select (optional)
+
+Transform or select a part of the data returned by the contract.
+
+```tsx {15}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ select: (data) => transform(data),
+ })
+}
+```
+
+### structuralSharing (optional)
+
+Keep referential identity of data and prevent rerenders. Defaults to `(oldData, newData) => deepEqual(oldData, newData) ? oldData : replaceEqualDeep(oldData, newData)`. If set to `false`, structural sharing between query results will be disabled.
+
+If set to a function, the old and new data values will be passed through this function, which should combine them into resolved data for the query. This way, you can retain references from the old data to improve performance even when that data contains non-serializable values.
+
+```tsx {15}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ structuralSharing: (prev, next) => (prev === next ? prev : next),
+ })
+}
+```
+
+### suspense (optional)
+
+Set this to `true` to enable suspense mode.
+
+```tsx {15}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ suspense: true,
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching new data is successful.
+
+```tsx {15-17}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {15-17}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {15-17}
+import { useContractReads } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useContractReads({
+ contracts: [
+ {
+ ...wagmigotchiContract,
+ functionName: 'getAlive',
+ },
+ {
+ ...wagmigotchiContract,
+ functionName: 'getBoredom',
+ },
+ ],
+ onSettled(data) {
+ console.log('Settled', data)
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useContractWrite.en-US.mdx b/docs/pages/react/hooks/useContractWrite.en-US.mdx
new file mode 100644
index 0000000000..0a900baf44
--- /dev/null
+++ b/docs/pages/react/hooks/useContractWrite.en-US.mdx
@@ -0,0 +1,387 @@
+---
+title: 'useContractWrite'
+description: 'React Hook for calling a ethers Contract write method.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# useContractWrite
+
+Hook for calling an ethers Contract [write](https://docs.ethers.io/v5/api/contract/contract/#Contract--write) method. Pairs with the [`usePrepareContractWrite` hook](/react/prepare-hooks/usePrepareContractWrite).
+
+```tsx
+import { useContractWrite } from 'wagmi'
+```
+
+## Usage
+
+The following examples use the [wagmigotchi](https://etherscan.io/address/0xecb504d39723b0be0e3a9aa33d646642d1051ee1) contract.
+
+```tsx
+import { useContractWrite, usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ })
+ const { data, isLoading, isSuccess, write } = useContractWrite(config)
+
+ return (
+
+
+ {isLoading &&
Check Wallet
}
+ {isSuccess &&
Transaction: {JSON.stringify(data)}
}
+
+ )
+}
+```
+
+
+ It is highly recommended to pair `useContractWrite` with the
+ [`usePrepareContractWrite` hook](/react/prepare-hooks/usePrepareContractWrite)
+ to [avoid UX
+ pitfalls](/react/prepare-hooks#ux-pitfalls-without-prepare-hooks).
+
+
+## Return Value
+
+```tsx
+{
+ data?: TransactionResponse
+ error?: Error
+ isError: boolean
+ isIdle: boolean
+ isLoading: boolean
+ isSuccess: boolean
+ write: ((args?: WriteContractConfig) => void) | undefined
+ writeAsync: ((args?: WriteContractConfig) => Promise) | undefined
+ reset: () => void
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### mode
+
+> This is automatically populated when using [`usePrepareContractWrite` hook](/react/prepare-hooks/usePrepareContractWrite).
+
+- `recklesslyUnprepared`: Allow to pass through an adhoc unprepared config. Note: This has [UX pitfalls](/react/prepare-hooks#ux-pitfalls-without-prepare-hooks), it is highly recommended to not use this and instead prepare the config upfront using the `usePrepareContractWrite` hook.
+- `prepared`: The config has been prepared with parameters required for performing a contract write via the [`usePrepareContractWrite` hook](/react/prepare-hooks/usePrepareContractWrite)
+
+```tsx {5}
+import { useContractWrite } from 'wagmi'
+
+function App() {
+ const { sendTransaction } = useContractWrite({
+ mode: 'recklesslyUnprepared',
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ })
+}
+```
+
+### address (optional)
+
+> This is automatically populated when using [`usePrepareContractWrite` hook](/react/prepare-hooks/usePrepareContractWrite).
+
+Contract address.
+
+```tsx {6}
+import { useContractWrite } from 'wagmi'
+
+function App() {
+ const contractWrite = useContractWrite({
+ mode: 'recklesslyUnprepared',
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ })
+
+ return
+}
+```
+
+### chainId (optional)
+
+> This is automatically populated when using [`usePrepareContractWrite` hook](/react/prepare-hooks/usePrepareContractWrite).
+
+Checks the current chain to make sure it is the same as `chainId`. If `chainId` is not the current chain, the connector attempts to switch to it before sending the transaction.
+
+```tsx {7}
+import { useContractWrite } from 'wagmi'
+
+function App() {
+ const contractWrite = useContractWrite({
+ mode: 'recklesslyUnprepared',
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ chainId: 1,
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ })
+
+ return
+}
+```
+
+### abi
+
+> This is automatically populated when using [`usePrepareContractWrite` hook](/react/prepare-hooks/usePrepareContractWrite).
+
+Contract ABI.
+
+By defining inline or adding a [const assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) to `abi`, TypeScript will infer the correct types for `functionName` and `args`. See the wagmi [TypeScript docs](/react/typescript) for more information.
+
+```tsx {7}
+import { useContractWrite } from 'wagmi'
+
+function App() {
+ const contractWrite = useContractWrite({
+ mode: 'recklesslyUnprepared',
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ })
+
+ return
+}
+```
+
+### functionName
+
+> This is automatically populated when using [`usePrepareContractWrite` hook](/react/prepare-hooks/usePrepareContractWrite).
+
+Name of function to call.
+
+```tsx {8}
+import { useContractWrite } from 'wagmi'
+
+function App() {
+ const contractWrite = useContractWrite({
+ mode: 'recklesslyUnprepared',
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ })
+
+ return
+}
+```
+
+### args (optional)
+
+> This is automatically populated when using [`usePrepareContractWrite` hook](/react/prepare-hooks/usePrepareContractWrite).
+
+Arguments to pass to function call.
+
+```tsx {9}
+import { useContractWrite } from 'wagmi'
+
+function App() {
+ const contractWrite = useContractWrite({
+ mode: 'recklesslyUnprepared',
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ args: [],
+ })
+
+ return
+}
+```
+
+### overrides (optional)
+
+> This is automatically populated when using [`usePrepareContractWrite` hook](/react/prepare-hooks/usePrepareContractWrite).
+
+Overrides to pass to function call. If the function is payable, you can pass a `value` here.
+
+```tsx {9-12}
+import { useContractWrite } from 'wagmi'
+
+function App() {
+ const contractWrite = useContractWrite({
+ mode: 'recklesslyUnprepared',
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ overrides: {
+ from: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ value: ethers.utils.parseEther('0.01'),
+ },
+ })
+
+ return
+}
+```
+
+### request (optional)
+
+> This is automatically populated when using [`usePrepareContractWrite` hook](/react/prepare-hooks/usePrepareContractWrite).
+
+The request to use when sending the contract transaction.
+
+```tsx {7}
+import { usePrepareContractWrite, useContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({ ... })
+ const { sendTransaction } = useContractWrite({
+ ...config,
+ request: config.request
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while attempting to write.
+
+```tsx {7-9}
+import { usePrepareContractWrite, useContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({ ... })
+ const { write } = useContractWrite({
+ ...config,
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onMutate (optional)
+
+Function fires before the contract write function and is passed same variables the contract write function would receive. Value returned from this function will be passed to both `onError` and `onSettled` functions in event of a failure.
+
+```tsx {7-9}
+import { usePrepareContractWrite, useContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({ ... })
+ const { write } = useContractWrite({
+ ...config,
+ onMutate({ args, overrides }) {
+ console.log('Mutate', { args, overrides })
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when write is settled (either successfully sent, or an error has thrown).
+
+```tsx {7-9}
+import { usePrepareContractWrite, useContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({ ... })
+ const { write } = useContractWrite({
+ ...config,
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when write is successful.
+
+```tsx {7-9}
+import { usePrepareContractWrite, useContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({ ... })
+ const { write } = useContractWrite({
+ ...config,
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+## Override Config
+
+It is possible to pass through override config. Any override config prefixed with `recklesslySetUnprepared` means that it will break the previously prepared config. It will need to prepare the request again at the time of invoking `write`/`writeAsync`.
+
+
+ This usage is not recommended. It comes with [UX
+ pitfalls](/react/prepare-hooks#ux-pitfalls-without-prepare-hooks). Only
+ use it as a last resort.
+
+
+```tsx {17-21}
+import { useContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'claim',
+ })
+ const { data, isLoading, isSuccess, write } = useContractWrite(config)
+
+ return (
+
+
+ {isLoading &&
Check Wallet
}
+ {isSuccess &&
Transaction: {JSON.stringify(data)}
}
+
+ )
+}
+```
+
+## Reckless Usage
+
+It is possible to use `useContractWrite` without pairing it with `usePrepareContractWrite` by using "recklessly unprepared" mode.
+
+
+ This usage is not recommended. It comes with [UX
+ pitfalls](/react/prepare-hooks#ux-pitfalls-without-prepare-hooks). Only
+ use it as a last resort.
+
+
+```tsx {5-9}
+import { useContractWrite } from 'wagmi'
+
+function App() {
+ const { data, isLoading, isSuccess, write } = useContractWrite({
+ mode: 'recklesslyUnprepared',
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'claim',
+ tokenId: 69,
+ })
+
+ return (
+
+
+ {isLoading &&
Check Wallet
}
+ {isSuccess &&
Transaction: {JSON.stringify(data)}
}
+
+ )
+}
+```
diff --git a/docs/pages/react/hooks/useDisconnect.en-US.mdx b/docs/pages/react/hooks/useDisconnect.en-US.mdx
new file mode 100644
index 0000000000..9799d4f5ec
--- /dev/null
+++ b/docs/pages/react/hooks/useDisconnect.en-US.mdx
@@ -0,0 +1,106 @@
+---
+title: 'useDisconnect'
+description: 'React Hook for disconnecting the connected account.'
+---
+
+# useDisconnect
+
+Hook for disconnecting the connected account.
+
+```ts
+import { useDisconnect } from 'wagmi'
+```
+
+## Usage
+
+```tsx
+import { useDisconnect } from 'wagmi'
+
+function App() {
+ const { disconnect } = useDisconnect()
+
+ return
+}
+```
+
+## Return Value
+
+```tsx
+{
+ disconnect: () => void
+ disconnectAsync: () => Promise
+ error?: Error
+ isError: boolean
+ isIdle: boolean
+ isLoading: boolean
+ isSuccess: boolean
+ reset: () => void
+ status: "error" | "idle" | "loading" | "success"
+}
+```
+
+## Configuration
+
+### onError (optional)
+
+Function to invoke when an error is thrown while disconnecting.
+
+```tsx {5-7}
+import { useDisconnect } from 'wagmi'
+
+function App() {
+ const disconnect = useDisconnect({
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onMutate (optional)
+
+Function fires before disconnect function. Value returned from this function will be passed to both `onError` and `onSettled` functions in event of a disconnect failure.
+
+```tsx {5-7}
+import { useDisconnect } from 'wagmi'
+
+function App() {
+ const disconnect = useDisconnect({
+ onMutate(args) {
+ console.log('Mutate', args)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when disconnect is settled (either successfully disconnected, or an error has thrown).
+
+```tsx {5-7}
+import { useDisconnect } from 'wagmi'
+
+function App() {
+ const disconnect = useDisconnect({
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when disconnect is successful.
+
+```tsx {5-7}
+import { useDisconnect } from 'wagmi'
+
+function App() {
+ const disconnect = useDisconnect({
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useEnsAddress.en-US.mdx b/docs/pages/react/hooks/useEnsAddress.en-US.mdx
new file mode 100644
index 0000000000..6f1415da8c
--- /dev/null
+++ b/docs/pages/react/hooks/useEnsAddress.en-US.mdx
@@ -0,0 +1,207 @@
+---
+title: 'useEnsAddress'
+description: 'React Hook for fetching address for ENS name.'
+---
+
+# useEnsAddress
+
+Hook for fetching address for ENS name.
+
+```ts
+import { useEnsAddress } from 'wagmi'
+```
+
+## Usage
+
+```tsx
+import { useEnsAddress } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useEnsAddress({
+ name: 'awkweb.eth',
+ })
+
+ if (isLoading) return
Fetching address…
+ if (isError) return
Error fetching address
+ return
Address: {data}
+}
+```
+
+## Return Value
+
+```tsx
+{
+ data?: string
+ error?: Error
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ refetch: (options: {
+ throwOnError: boolean
+ cancelRefetch: boolean
+ }) => Promise
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### chainId (optional)
+
+Force a specific chain id for the request. The wagmi `Client`'s ethers `provider` must be set up as a [chain-aware function](/react/client#provider-optional) for this to work correctly.
+
+```tsx {6}
+import { useEnsAddress } from 'wagmi'
+
+function App() {
+ const ensAddress = useEnsAddress({
+ name: 'awkweb.eth',
+ chainId: 1,
+ })
+}
+```
+
+### name (optional)
+
+ENS name to fetch address for. If `name` is not defined, hook will not run.
+
+```tsx {5}
+import { useEnsAddress } from 'wagmi'
+
+function App() {
+ const ensAddress = useEnsAddress({
+ name: 'moxey.eth',
+ })
+}
+```
+
+### cacheTime (optional)
+
+Time (in ms) which the data should remain in the cache. Defaults to `0`.
+
+```tsx {6}
+import { useEnsAddress } from 'wagmi'
+
+function App() {
+ const ensAddress = useEnsAddress({
+ name: 'awkweb.eth',
+ cacheTime: 2_000,
+ })
+}
+```
+
+### enabled (optional)
+
+Set this to `false` to disable this query from automatically running. Defaults to `true`.
+
+```tsx {6}
+import { useEnsAddress } from 'wagmi'
+
+function App() {
+ const ensAddress = useEnsAddress({
+ name: 'awkweb.eth',
+ enabled: false,
+ })
+}
+```
+
+### scopeKey (optional)
+
+Scopes the cache to a given context. Hooks that have identical context will share the same cache.
+
+```tsx {6}
+import { useEnsAddress } from 'wagmi'
+
+function App() {
+ const ensAddress = useEnsAddress({
+ name: 'awkweb.eth',
+ scopeKey: 'wagmi',
+ })
+}
+```
+
+### staleTime (optional)
+
+Time (in ms) after data is considered stale. If set to `Infinity` the data will never be considered stale. Defaults to `1000 * 60 * 60 * 24` (24 hours).
+
+```tsx {6}
+import { useEnsAddress } from 'wagmi'
+
+function App() {
+ const ensAddress = useEnsAddress({
+ name: 'awkweb.eth',
+ staleTime: 2_000,
+ })
+}
+```
+
+### suspense (optional)
+
+Set this to `true` to enable suspense mode.
+
+```tsx {6}
+import { useEnsAddress } from 'wagmi'
+
+function App() {
+ const ensAddress = useEnsAddress({
+ name: 'awkweb.eth',
+ suspense: true,
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching new data is successful.
+
+```tsx {6-8}
+import { useEnsAddress } from 'wagmi'
+
+function App() {
+ const ensAddress = useEnsAddress({
+ name: 'awkweb.eth',
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {6-8}
+import { useEnsAddress } from 'wagmi'
+
+function App() {
+ const ensAddress = useEnsAddress({
+ name: 'awkweb.eth',
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {6-8}
+import { useEnsAddress } from 'wagmi'
+
+function App() {
+ const ensAddress = useEnsAddress({
+ name: 'awkweb.eth',
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useEnsAvatar.en-US.mdx b/docs/pages/react/hooks/useEnsAvatar.en-US.mdx
new file mode 100644
index 0000000000..e0be877a26
--- /dev/null
+++ b/docs/pages/react/hooks/useEnsAvatar.en-US.mdx
@@ -0,0 +1,207 @@
+---
+title: 'useEnsAvatar'
+description: 'React Hook for fetching avatar for ENS name.'
+---
+
+# useEnsAvatar
+
+Hook for fetching avatar for ENS name.
+
+```ts
+import { useEnsAvatar } from 'wagmi'
+```
+
+## Usage
+
+```tsx
+import { useEnsAvatar } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useEnsAvatar({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ })
+
+ if (isLoading) return
Fetching avatar…
+ if (isError) return
Error fetching avatar
+ return
Avatar: {data}
+}
+```
+
+## Return Value
+
+```tsx
+{
+ data?: string
+ error?: Error
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ refetch: (options: {
+ throwOnError: boolean
+ cancelRefetch: boolean
+ }) => Promise
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### address (optional)
+
+Address or ENS name to fetch avatar for. If `address` is not defined, hook will not run.
+
+```tsx {5}
+import { useEnsAvatar } from 'wagmi'
+
+function App() {
+ const ensAvatar = useEnsAvatar({
+ address: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac',
+ })
+}
+```
+
+### chainId (optional)
+
+Force a specific chain id for the request. The wagmi `Client`'s ethers `provider` must be set up as a [chain-aware function](/react/client#provider-optional) for this to work correctly.
+
+```tsx {6}
+import { useEnsAvatar } from 'wagmi'
+
+function App() {
+ const ensAvatar = useEnsAvatar({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ chainId: 1,
+ })
+}
+```
+
+### cacheTime (optional)
+
+Time (in ms) which the data should remain in the cache. Defaults to `0`.
+
+```tsx {6}
+import { useEnsAvatar } from 'wagmi'
+
+function App() {
+ const ensAvatar = useEnsAvatar({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ cacheTime: 2_000,
+ })
+}
+```
+
+### enabled (optional)
+
+Set this to `false` to disable this query from automatically running. Defaults to `true`.
+
+```tsx {6}
+import { useEnsAvatar } from 'wagmi'
+
+function App() {
+ const ensAvatar = useEnsAvatar({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ enabled: false,
+ })
+}
+```
+
+### scopeKey (optional)
+
+Scopes the cache to a given context. Hooks that have identical context will share the same cache.
+
+```tsx {6}
+import { useEnsAvatar } from 'wagmi'
+
+function App() {
+ const ensAvatar = useEnsAvatar({
+ addressOrName: 'awkweb.eth',
+ scopeKey: 'wagmi',
+ })
+}
+```
+
+### staleTime (optional)
+
+Time (in ms) after data is considered stale. If set to `Infinity` the data will never be considered stale. Defaults to `1000 * 60 * 60 * 24` (24 hours).
+
+```tsx {6}
+import { useEnsAvatar } from 'wagmi'
+
+function App() {
+ const ensAvatar = useEnsAvatar({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ staleTime: 2_000,
+ })
+}
+```
+
+### suspense (optional)
+
+Set this to `true` to enable suspense mode.
+
+```tsx {6}
+import { useEnsAvatar } from 'wagmi'
+
+function App() {
+ const ensAvatar = useEnsAvatar({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ suspense: true,
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching new data is successful.
+
+```tsx {6-8}
+import { useEnsAvatar } from 'wagmi'
+
+function App() {
+ const ensAvatar = useEnsAvatar({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {6-8}
+import { useEnsAvatar } from 'wagmi'
+
+function App() {
+ const ensAvatar = useEnsAvatar({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {6-8}
+import { useEnsAvatar } from 'wagmi'
+
+function App() {
+ const ensAvatar = useEnsAvatar({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useEnsName.en-US.mdx b/docs/pages/react/hooks/useEnsName.en-US.mdx
new file mode 100644
index 0000000000..77be7f3ba2
--- /dev/null
+++ b/docs/pages/react/hooks/useEnsName.en-US.mdx
@@ -0,0 +1,207 @@
+---
+title: 'useEnsName'
+description: 'React Hook for fetching ENS name for address.'
+---
+
+# useEnsName
+
+Hook for fetching ENS name for address.
+
+```ts
+import { useEnsName } from 'wagmi'
+```
+
+## Usage
+
+```tsx
+import { useEnsName } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useEnsName({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ })
+
+ if (isLoading) return
Fetching name…
+ if (isError) return
Error fetching name
+ return
Name: {data}
+}
+```
+
+## Return Value
+
+```tsx
+{
+ data?: string
+ error?: Error
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ refetch: (options: {
+ throwOnError: boolean
+ cancelRefetch: boolean
+ }) => Promise
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### address (optional)
+
+Address to fetch ENS name for. If `address` is not defined, hook will not run.
+
+```tsx {5}
+import { useEnsName } from 'wagmi'
+
+function App() {
+ const ensName = useEnsName({
+ address: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac',
+ })
+}
+```
+
+### chainId (optional)
+
+Force a specific chain id for the request. The wagmi `Client`'s ethers `provider` must be set up as a [chain-aware function](/react/client#provider-optional) for this to work correctly.
+
+```tsx {6}
+import { useEnsName } from 'wagmi'
+
+function App() {
+ const ensName = useEnsName({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ chainId: 1,
+ })
+}
+```
+
+### cacheTime (optional)
+
+Time (in ms) which the data should remain in the cache. Defaults to `0`.
+
+```tsx {6}
+import { useEnsName } from 'wagmi'
+
+function App() {
+ const ensName = useEnsName({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ cacheTime: 2_000,
+ })
+}
+```
+
+### enabled (optional)
+
+Set this to `false` to disable this query from automatically running. Defaults to `true`.
+
+```tsx {6}
+import { useEnsName } from 'wagmi'
+
+function App() {
+ const ensName = useEnsName({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ enabled: false,
+ })
+}
+```
+
+### scopeKey (optional)
+
+Scopes the cache to a given context. Hooks that have identical context will share the same cache.
+
+```tsx {6}
+import { useEnsName } from 'wagmi'
+
+function App() {
+ const ensName = useEnsName({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ scopeKey: 'wagmi',
+ })
+}
+```
+
+### staleTime (optional)
+
+Time (in ms) after data is considered stale. If set to `Infinity` the data will never be considered stale. Defaults to `1000 * 60 * 60 * 24` (24 hours).
+
+```tsx {6}
+import { useEnsName } from 'wagmi'
+
+function App() {
+ const ensName = useEnsName({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ staleTime: 2_000,
+ })
+}
+```
+
+### suspense (optional)
+
+Set this to `true` to enable suspense mode.
+
+```tsx {6}
+import { useEnsName } from 'wagmi'
+
+function App() {
+ const ensName = useEnsName({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ suspense: true,
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching new data is successful.
+
+```tsx {6-8}
+import { useEnsName } from 'wagmi'
+
+function App() {
+ const ensName = useEnsName({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {6-8}
+import { useEnsName } from 'wagmi'
+
+function App() {
+ const ensName = useEnsName({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {6-8}
+import { useEnsName } from 'wagmi'
+
+function App() {
+ const ensName = useEnsName({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useEnsResolver.en-US.mdx b/docs/pages/react/hooks/useEnsResolver.en-US.mdx
new file mode 100644
index 0000000000..05883d61aa
--- /dev/null
+++ b/docs/pages/react/hooks/useEnsResolver.en-US.mdx
@@ -0,0 +1,177 @@
+---
+title: 'useEnsResolver'
+description: 'React Hook for fetching resolver for ENS name.'
+---
+
+# useEnsResolver
+
+Hook for fetching the resolver for ENS name.
+
+```ts
+import { useEnsResolver } from 'wagmi'
+```
+
+## Usage
+
+```tsx
+import { useEnsResolver } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useEnsResolver({
+ name: 'awkweb.eth',
+ })
+
+ if (isLoading) return
Fetching resolver…
+ if (isError) return
Error fetching resolver
+ return
Resolver: {JSON.stringify(data)}
+}
+```
+
+## Return Value
+
+```tsx
+{
+ data?: EnsResolver
+ error?: Error
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ refetch: (options: {
+ throwOnError: boolean
+ cancelRefetch: boolean
+ }) => Promise
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### chainId (optional)
+
+Force a specific chain id for the request. The wagmi `Client`'s ethers `provider` must be set up as a [chain-aware function](/react/client#provider-optional) for this to work correctly.
+
+```tsx {6}
+import { useEnsResolver } from 'wagmi'
+
+function App() {
+ const ensResolver = useEnsResolver({
+ name: 'awkweb.eth',
+ chainId: 1,
+ })
+}
+```
+
+### name (optional)
+
+ENS name to fetch address for. If `name` is not defined, hook will not run.
+
+```tsx {5}
+import { useEnsResolver } from 'wagmi'
+
+function App() {
+ const ensResolver = useEnsResolver({
+ name: 'moxey.eth',
+ })
+}
+```
+
+### enabled (optional)
+
+Set this to `false` to disable this query from automatically running. Defaults to `true`.
+
+```tsx {6}
+import { useEnsResolver } from 'wagmi'
+
+function App() {
+ const ensResolver = useEnsResolver({
+ name: 'awkweb.eth',
+ enabled: false,
+ })
+}
+```
+
+### scopeKey (optional)
+
+Scopes the cache to a given context. Hooks that have identical context will share the same cache.
+
+```tsx {6}
+import { useEnsResolver } from 'wagmi'
+
+function App() {
+ const ensResolver = useEnsResolver({
+ name: 'awkweb.eth',
+ scopeKey: 'wagmi',
+ })
+}
+```
+
+### suspense (optional)
+
+Set this to `true` to enable suspense mode.
+
+```tsx {6}
+import { useEnsResolver } from 'wagmi'
+
+function App() {
+ const ensResolver = useEnsResolver({
+ name: 'awkweb.eth',
+ suspense: true,
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching new data is successful.
+
+```tsx {6-8}
+import { useEnsResolver } from 'wagmi'
+
+function App() {
+ const ensResolver = useEnsResolver({
+ name: 'awkweb.eth',
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {6-8}
+import { useEnsResolver } from 'wagmi'
+
+function App() {
+ const ensResolver = useEnsResolver({
+ name: 'awkweb.eth',
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {6-8}
+import { useEnsResolver } from 'wagmi'
+
+function App() {
+ const ensResolver = useEnsResolver({
+ name: 'awkweb.eth',
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useFeeData.en-US.mdx b/docs/pages/react/hooks/useFeeData.en-US.mdx
new file mode 100644
index 0000000000..fd2aada40c
--- /dev/null
+++ b/docs/pages/react/hooks/useFeeData.en-US.mdx
@@ -0,0 +1,228 @@
+---
+title: 'useFeeData'
+description: 'React Hook for fetching network fee information.'
+---
+
+# useFeeData
+
+Hook for fetching network fee information.
+
+```ts
+import { useFeeData } from 'wagmi'
+```
+
+## Usage
+
+```tsx
+import { useFeeData } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useFeeData()
+
+ if (isLoading) return
Fetching fee data…
+ if (isError) return
Error fetching fee data
+ return
Fee data: {JSON.stringify(data?.formatted)}
+}
+```
+
+## Return Value
+
+```tsx
+{
+ data?: {
+ gasPrice: BigNumber
+ maxFeePerGas: BigNumber
+ maxPriorityFeePerGas: BigNumber
+ formatted: {
+ gasPrice: string
+ maxFeePerGas: string
+ maxPriorityFeePerGas: string
+ }
+ }
+ error?: Error
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ refetch: (options: {
+ throwOnError: boolean
+ cancelRefetch: boolean
+ }) => Promise<{
+ gasPrice: BigNumber
+ maxFeePerGas: BigNumber
+ maxPriorityFeePerGas: BigNumber
+ formatted: {
+ gasPrice: string
+ maxFeePerGas: string
+ maxPriorityFeePerGas: string
+ }
+ }>
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### chainId (optional)
+
+Force a specific chain id for the request. The wagmi `Client`'s ethers `provider` must be set up as a [chain-aware function](/react/client#provider-optional) for this to work correctly.
+
+```tsx {5}
+import { useFeeData } from 'wagmi'
+
+function App() {
+ const feeData = useFeeData({
+ chainId: 1,
+ })
+}
+```
+
+### formatUnits (optional)
+
+Formats fee data using ethers [units](https://docs.ethers.io/v5/api/utils/display-logic/#display-logic--units). Defaults to `wei`.
+
+```tsx {5}
+import { useFeeData } from 'wagmi'
+
+function App() {
+ const feeData = useFeeData({
+ formatUnits: 'gwei',
+ })
+}
+```
+
+### watch (optional)
+
+Watches and refreshes data for new blocks.
+
+```tsx {5}
+import { useFeeData } from 'wagmi'
+
+function App() {
+ const feeData = useFeeData({
+ watch: true,
+ })
+}
+```
+
+### cacheTime (optional)
+
+Time (in ms) which the data should remain in the cache. Defaults to `0`.
+
+```tsx {5}
+import { useFeeData } from 'wagmi'
+
+function App() {
+ const feeData = useFeeData({
+ cacheTime: 2_000,
+ })
+}
+```
+
+### enabled (optional)
+
+Set this to `false` to disable this query from automatically running. Defaults to `true`.
+
+```tsx {5}
+import { useFeeData } from 'wagmi'
+
+function App() {
+ const feeData = useFeeData({
+ enabled: false,
+ })
+}
+```
+
+### scopeKey (optional)
+
+Scopes the cache to a given context. Hooks that have identical context will share the same cache.
+
+```tsx {5}
+import { useFeeData } from 'wagmi'
+
+function App() {
+ const feeData = useFeeData({
+ scopeKey: 'wagmi',
+ })
+}
+```
+
+### staleTime (optional)
+
+Time (in ms) after data is considered stale. If set to `Infinity` the data will never be considered stale. Defaults to `0`.
+
+```tsx {5}
+import { useFeeData } from 'wagmi'
+
+function App() {
+ const feeData = useFeeData({
+ staleTime: 2_000,
+ })
+}
+```
+
+### suspense (optional)
+
+Set this to `true` to enable suspense mode.
+
+```tsx {5}
+import { useFeeData } from 'wagmi'
+
+function App() {
+ const feeData = useFeeData({
+ suspense: true,
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching new data is successful.
+
+```tsx {5-7}
+import { useFeeData } from 'wagmi'
+
+function App() {
+ const feeData = useFeeData({
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {5-7}
+import { useFeeData } from 'wagmi'
+
+function App() {
+ const feeData = useFeeData({
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {5-7}
+import { useFeeData } from 'wagmi'
+
+function App() {
+ const feeData = useFeeData({
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useNetwork.en-US.mdx b/docs/pages/react/hooks/useNetwork.en-US.mdx
new file mode 100644
index 0000000000..835b55e905
--- /dev/null
+++ b/docs/pages/react/hooks/useNetwork.en-US.mdx
@@ -0,0 +1,47 @@
+---
+title: 'useNetwork'
+description: 'React Hook for accessing network data, such as current connected chain and connector chains.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# useNetwork
+
+Hook for accessing network data, such as current connected chain and [connector chains](https://wagmi.sh/react/connectors/injected#chains-optional).
+
+```tsx
+import { useNetwork } from 'wagmi'
+```
+
+## Usage
+
+```tsx
+import { useNetwork } from 'wagmi'
+
+function App() {
+ const { chain, chains } = useNetwork()
+
+ return (
+ <>
+ {chain &&
Connected to {chain.name}
}
+ {chains && (
+
Available chains: {chains.map((chain) => chain.name)}
+ )}
+ >
+ )
+}
+```
+
+
+ If you want the functionality to switch networks, [check out
+ `useSwitchNetwork`](https://wagmi.sh/react/hooks/useSwitchNetwork).
+
+
+## Return Value
+
+```tsx
+{
+ chain?: Chain & { unsupported?: boolean }
+ chains: Chain[]
+}
+```
diff --git a/docs/pages/react/hooks/useProvider.en-US.mdx b/docs/pages/react/hooks/useProvider.en-US.mdx
new file mode 100644
index 0000000000..ba70121b91
--- /dev/null
+++ b/docs/pages/react/hooks/useProvider.en-US.mdx
@@ -0,0 +1,44 @@
+---
+title: 'useProvider'
+description: "React Hook for accessing Client's ethers Provider."
+---
+
+# useProvider
+
+Hook for accessing `Client`'s ethers Provider.
+
+```ts
+import { useProvider } from 'wagmi'
+```
+
+## Usage
+
+```tsx
+import { useProvider } from 'wagmi'
+
+function App() {
+ const provider = useProvider()
+}
+```
+
+## Return Value
+
+```tsx
+Provider
+```
+
+## Configuration
+
+### chainId (optional)
+
+Force a specific chain id. The wagmi `Client`'s ethers `provider` must be set up as a [chain-aware function](/react/client#provider-optional) for this to work correctly.
+
+```tsx {5}
+import { useProvider } from 'wagmi'
+
+function App() {
+ const provider = useProvider({
+ chainId: 1,
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useSendTransaction.en-US.mdx b/docs/pages/react/hooks/useSendTransaction.en-US.mdx
new file mode 100644
index 0000000000..2c521b68db
--- /dev/null
+++ b/docs/pages/react/hooks/useSendTransaction.en-US.mdx
@@ -0,0 +1,246 @@
+---
+title: 'useSendTransaction'
+description: 'React Hook for sending a transaction.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# useSendTransaction
+
+Hook for sending a transaction.
+
+```tsx
+import { useSendTransaction } from 'wagmi'
+```
+
+## Usage
+
+```tsx
+import { useSendTransaction, usePrepareSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({
+ request: { to: 'moxey.eth', value: BigNumber.from('10000000000000000') },
+ })
+ const { data, isLoading, isSuccess, sendTransaction } =
+ useSendTransaction(config)
+
+ return (
+
+
+ {isLoading &&
Check Wallet
}
+ {isSuccess &&
Transaction: {JSON.stringify(data)}
}
+
+ )
+}
+```
+
+
+ It is highly recommended to pair `useSendTransaction` with the
+ [`usePrepareSendTransaction`
+ hook](/react/prepare-hooks/usePrepareSendTransaction) to [avoid UX
+ pitfalls](/react/prepare-hooks#ux-pitfalls-without-prepare-hooks).
+
+
+## Return Value
+
+```tsx
+{
+ data?: TransactionResponse
+ error?: Error
+ isError: boolean
+ isIdle: boolean
+ isLoading: boolean
+ isSuccess: boolean
+ sendTransaction: ((args?: SendTransactionArgs) => void) | undefined
+ sendTransactionAsync: ((args?: SendTransactionArgs) => Promise) | undefined
+ reset: () => void
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### mode
+
+> This is automatically populated when using [`usePrepareSendTransaction` hook](/react/prepare-hooks/usePrepareSendTransaction).
+
+- `recklesslyUnprepared`: Allow to pass through an adhoc unprepared `request`. Note: This has [UX pitfalls](/react/prepare-hooks#ux-pitfalls-without-prepare-hooks), it is highly recommended to not use this and instead prepare the request upfront using the `usePrepareSendTransaction` hook.
+- `prepared`: The request has been prepared with parameters required for sending a transaction via the `usePrepareSendTransaction` hook
+
+```tsx {5}
+import { useSendTransaction } from 'wagmi'
+
+function App() {
+ const { sendTransaction } = useSendTransaction({
+ mode: 'recklesslyUnprepared',
+ request: {
+ to: 'moxey.eth',
+ value: BigNumber.from('10000000000000000'),
+ },
+ })
+}
+```
+
+### request (optional)
+
+> This is automatically populated when using [`usePrepareSendTransaction` hook](/react/prepare-hooks/usePrepareSendTransaction).
+
+The request to use when sending the transaction.
+
+```tsx {7}
+import { usePrepareSendTransaction, useSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({ ... })
+ const { sendTransaction } = useSendTransaction({
+ ...config,
+ request: config.request
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while attempting to send.
+
+```tsx {7-9}
+import { usePrepareSendTransaction, useSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({ ... })
+ const { sendTransaction } = useSendTransaction({
+ ...config,
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onMutate (optional)
+
+Function fires before send transaction function and is passed same variables send transaction function would receive. Value returned from this function will be passed to both `onError` and `onSettled` functions in event of a send transaction failure.
+
+```tsx {7-9}
+import { usePrepareSendTransaction, useSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({ ... })
+ const { sendTransaction } = useSendTransaction({
+ ...config,
+ onMutate({ args, overrides }) {
+ console.log('Mutate', { args, overrides })
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when send transaction is settled (either successfully sent, or an error has thrown).
+
+```tsx {7-9}
+import { usePrepareSendTransaction, useSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({ ... })
+ const { sendTransaction } = useSendTransaction({
+ ...config,
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when send transaction is successful.
+
+```tsx {7-9}
+import { usePrepareSendTransaction, useSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({ ... })
+ const { sendTransaction } = useSendTransaction({
+ ...config,
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+## Override Config
+
+It is possible to pass through override config. Any override config prefixed with `recklesslySetUnprepared` means that it will break the previously prepared config. It will need to prepare the request again at the time of invoking `sendTransaction`/`sendTransactionAsync`.
+
+
+ This usage is not recommended. It comes with [UX
+ pitfalls](/react/prepare-hooks#ux-pitfalls-without-prepare-hooks). Only use it
+ as a last resort.
+
+
+```tsx {15-18}
+import { usePrepareSendTransaction, useSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({
+ request: { to: 'moxey.eth', value: BigNumber.from('10000000000000000') },
+ })
+ const { data, isLoading, isSuccess, sendTransaction } =
+ useSendTransaction(config)
+
+ return (
+
+
+ {isLoading &&
Check Wallet
}
+ {isSuccess &&
Transaction: {JSON.stringify(data)}
}
+
+ )
+}
+```
+
+## Reckless Usage
+
+It is possible to use `useSendTransaction` without pairing it with `usePrepareSendTransaction` by using "recklessly unprepared" mode.
+
+
+ This usage is not recommended. It comes with [UX
+ pitfalls](/react/prepare-hooks#ux-pitfalls-without-prepare-hooks). Only use it
+ as a last resort.
+
+
+```tsx {5-7}
+import { useSendTransaction } from 'wagmi'
+
+function App() {
+ const { data, isLoading, isSuccess, sendTransaction } = useSendTransaction({
+ mode: 'recklesslyUnprepared',
+ request: {
+ to: 'moxey.eth',
+ value: BigNumber.from('10000000000000000'),
+ }
+ })
+
+ return (
+
+
+ {isLoading &&
Check Wallet
}
+ {isSuccess &&
Transaction: {JSON.stringify(data)}
}
+
+ )
+}
+```
diff --git a/docs/pages/react/hooks/useSignMessage.en-US.mdx b/docs/pages/react/hooks/useSignMessage.en-US.mdx
new file mode 100644
index 0000000000..6deb4d6390
--- /dev/null
+++ b/docs/pages/react/hooks/useSignMessage.en-US.mdx
@@ -0,0 +1,139 @@
+---
+title: 'useSignMessage'
+description: 'React Hook for signing messages with connected account.'
+---
+
+# useSignMessage
+
+Hook for signing messages with connected account.
+
+```tsx
+import { useSignMessage } from 'wagmi'
+```
+
+## Usage
+
+The following examples use the message: `gm wagmi frens`.
+
+```tsx
+import { useSignMessage } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading, isSuccess, signMessage } = useSignMessage({
+ message: 'gm wagmi frens',
+ })
+
+ return (
+
+
+ {isSuccess &&
Signature: {data}
}
+ {isError &&
Error signing message
}
+
+ )
+}
+```
+
+## Return Value
+
+```tsx
+{
+ data?: string
+ error?: Error
+ isError: boolean
+ isIdle: boolean
+ isLoading: boolean
+ isSuccess: boolean
+ signMessage: (args?: SignMessageArgs) => void
+ signMessageAsync: (args?: SignMessageArgs) => Promise
+ reset: () => void
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### message (optional)
+
+Message to sign with wallet. This can be a fixed string or a reactive state variable.
+
+```tsx {7}
+import * as React from 'react'
+import { useSignMessage } from 'wagmi'
+
+function App() {
+ const [message, setMessage] = React.useState('gm wagmi frens')
+ const signMessage = useSignMessage({
+ message,
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while attempting to sign.
+
+```tsx {6-8}
+import { useSignMessage } from 'wagmi'
+
+function App() {
+ const signMessage = useSignMessage({
+ message: 'gm wagmi frens',
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onMutate (optional)
+
+Function fires before sign message function and is passed same variables sign message function would receive. Value returned from this function will be passed to both `onError` and `onSettled` functions in event of a sign message failure.
+
+```tsx {6-8}
+import { useSignMessage } from 'wagmi'
+
+function App() {
+ const signMessage = useSignMessage({
+ message: 'gm wagmi frens',
+ onMutate(args) {
+ console.log('Mutate', args)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when sign message is settled (either successfully signed, or an error has thrown).
+
+```tsx {6-8}
+import { useSignMessage } from 'wagmi'
+
+function App() {
+ const signMessage = useSignMessage({
+ message: 'gm wagmi frens',
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when sign message is successful.
+
+```tsx {6-8}
+import { useSignMessage } from 'wagmi'
+
+function App() {
+ const signMessage = useSignMessage({
+ message: 'gm wagmi frens',
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useSignTypedData.en-US.mdx b/docs/pages/react/hooks/useSignTypedData.en-US.mdx
new file mode 100644
index 0000000000..5e2b9aec6a
--- /dev/null
+++ b/docs/pages/react/hooks/useSignTypedData.en-US.mdx
@@ -0,0 +1,253 @@
+---
+title: 'useSignTypedData'
+description: 'React Hook for signing typed data with connected account.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# useSignTypedData
+
+
+ This hook uses an experimental ethers feature. If using it, please specify the
+ exact version of ethers you are using (e.g. specify "5.6.0", not "^5.6.0").
+
+
+Hook for signing typed data with connected account.
+
+```tsx
+import { useSignTypedData } from 'wagmi'
+```
+
+## Usage
+
+The following examples use the typed data:
+
+```ts
+// All properties on a domain are optional
+const domain = {
+ name: 'Ether Mail',
+ version: '1',
+ chainId: 1,
+ verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
+} as const
+
+// The named list of all type definitions
+const types = {
+ Person: [
+ { name: 'name', type: 'string' },
+ { name: 'wallet', type: 'address' },
+ ],
+ Mail: [
+ { name: 'from', type: 'Person' },
+ { name: 'to', type: 'Person' },
+ { name: 'contents', type: 'string' },
+ ],
+} as const
+
+const value = {
+ from: {
+ name: 'Cow',
+ wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
+ },
+ to: {
+ name: 'Bob',
+ wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
+ },
+ contents: 'Hello, Bob!',
+} as const
+```
+
+From now on, the typed data variables (above) are referenced only by name for brevity.
+
+```tsx
+import { useSignTypedData } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading, isSuccess, signTypedData } =
+ useSignTypedData({
+ domain,
+ types,
+ value,
+ })
+
+ return (
+
+
+ {isSuccess &&
Signature: {data}
}
+ {isError &&
Error signing message
}
+
+ )
+}
+```
+
+## Return Value
+
+```tsx
+{
+ data?: string
+ error?: Error
+ isError: boolean
+ isIdle: boolean
+ isLoading: boolean
+ isSuccess: boolean
+ signTypedData: (args?: SignTypedDataArgs) => void
+ signTypedDataAsync: (args?: SignTypedDataArgs) => Promise
+ reset: () => void
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### domain (optional)
+
+Typed data domain. This can be a fixed object or a reactive state variable.
+
+```tsx {5-10}
+import { useSignTypedData } from 'wagmi'
+
+function App() {
+ const signTypedData = useSignTypedData({
+ domain: {
+ name: 'Ether Mail',
+ version: '1',
+ chainId: 1,
+ verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
+ },
+ types,
+ value,
+ })
+}
+```
+
+### types (optional)
+
+Typed data type definition.
+
+By defining inline or adding a [const assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) to `types`, TypeScript will infer the correct types `value`. See the wagmi [TypeScript docs](/react/typescript) for more information.
+
+```tsx {6-16}
+import { useSignTypedData } from 'wagmi'
+
+function App() {
+ const signTypedData = useSignTypedData({
+ domain,
+ types: {
+ Person: [
+ { name: 'name', type: 'string' },
+ { name: 'wallet', type: 'address' },
+ ],
+ Mail: [
+ { name: 'from', type: 'Person' },
+ { name: 'to', type: 'Person' },
+ { name: 'contents', type: 'string' },
+ ],
+ },
+ value,
+ })
+}
+```
+
+### value (optional)
+
+Typed data value. This can be a fixed object or a reactive state variable.
+
+```tsx {7-17}
+import { useSignTypedData } from 'wagmi'
+
+function App() {
+ const signTypedData = useSignTypedData({
+ domain,
+ types,
+ value: {
+ from: {
+ name: 'Cow',
+ wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
+ },
+ to: {
+ name: 'Bob',
+ wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
+ },
+ contents: 'Hello, Bob!',
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while attempting to sign.
+
+```tsx {8-10}
+import { useSignTypedData } from 'wagmi'
+
+function App() {
+ const signTypedData = useSignTypedData({
+ domain,
+ types,
+ value,
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onMutate (optional)
+
+Function fires before sign message function and is passed same variables sign message function would receive. Value returned from this function will be passed to both `onError` and `onSettled` functions in event of a sign message failure.
+
+```tsx {8-10}
+import { useSignTypedData } from 'wagmi'
+
+function App() {
+ const signTypedData = useSignTypedData({
+ domain,
+ types,
+ value,
+ onMutate(args) {
+ console.log('Mutate', args)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when sign message is settled (either successfully signed, or an error has thrown).
+
+```tsx {8-10}
+import { useSignTypedData } from 'wagmi'
+
+function App() {
+ const signTypedData = useSignTypedData({
+ domain,
+ types,
+ value,
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when sign message is successful.
+
+```tsx {8-10}
+import { useSignTypedData } from 'wagmi'
+
+function App() {
+ const signTypedData = useSignTypedData({
+ domain,
+ types,
+ value,
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useSigner.en-US.mdx b/docs/pages/react/hooks/useSigner.en-US.mdx
new file mode 100644
index 0000000000..7983c64f52
--- /dev/null
+++ b/docs/pages/react/hooks/useSigner.en-US.mdx
@@ -0,0 +1,113 @@
+---
+title: 'useSigner'
+description: 'React Hook for accessing ethers Signer object for connected account.'
+---
+
+# useSigner
+
+Hook for accessing ethers [Signer](https://docs.ethers.io/v5/api/signer) object for connected account.
+
+```ts
+import { useSigner } from 'wagmi'
+```
+
+## Usage
+
+The following examples use the [ENS Registry](https://etherscan.io/address/0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e#code) contract.
+
+```tsx {4, 9}
+import { useContract, useSigner } from 'wagmi'
+
+function App() {
+ const { data: signer, isError, isLoading } = useSigner()
+
+ const contract = useContract({
+ address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
+ abi: ensRegistryABI,
+ signerOrProvider: signer,
+ })
+}
+```
+
+## Return Value
+
+```tsx
+{
+ data?: Signer
+ error?: Error
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### chainId (optional)
+
+Chain ID to use for signer.
+
+```tsx {5-7}
+import { useContract, useSigner } from 'wagmi'
+import { optimism } from 'wagmi/chains'
+
+function App() {
+ const { data: signer } = useSigner({
+ chainId: optimism.id,
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {5-7}
+import { useContract, useSigner } from 'wagmi'
+
+function App() {
+ const { data: signer } = useSigner({
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {5-7}
+import { useContract, useSigner } from 'wagmi'
+
+function App() {
+ const { data: signer } = useSigner({
+ onSettled(data, error) {
+ console.log('Settled', data, error)
+ },
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching new data is successful.
+
+```tsx {5-7}
+import { useContract, useSigner } from 'wagmi'
+
+function App() {
+ const { data: signer } = useSigner({
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useSwitchNetwork.en-US.mdx b/docs/pages/react/hooks/useSwitchNetwork.en-US.mdx
new file mode 100644
index 0000000000..5874ad91b0
--- /dev/null
+++ b/docs/pages/react/hooks/useSwitchNetwork.en-US.mdx
@@ -0,0 +1,158 @@
+---
+title: 'useSwitchNetwork'
+description: 'React Hook for switching networks with a connector.'
+---
+
+# useSwitchNetwork
+
+Hook for switching networks with a connector.
+
+```tsx
+import { useSwitchNetwork } from 'wagmi'
+```
+
+## Usage
+
+Some wallet apps do not support programmatic network switching and `switchNetwork` will be `undefined`. For those situations, you can typically switch networks in the wallet app and wagmi will stay up-to-date.
+
+```tsx
+import { useNetwork, useSwitchNetwork } from 'wagmi'
+
+function App() {
+ const { chain } = useNetwork()
+ const { chains, error, isLoading, pendingChainId, switchNetwork } =
+ useSwitchNetwork()
+
+ return (
+ <>
+ {chain &&
Connected to {chain.name}
}
+
+ {chains.map((x) => (
+
+ ))}
+
+
{error && error.message}
+ >
+ )
+}
+```
+
+## Return Value
+
+```tsx
+{
+ chains: Chain[]
+ data?: Chain
+ error?: Error
+ isError: boolean
+ isIdle: boolean
+ isLoading: boolean
+ isSuccess: boolean
+ pendingChainId?: number
+ switchNetwork?: (chainId?: number) => void
+ switchNetworkAsync?: (chainId?: number) => Promise
+ status: 'idle' | 'error' | 'loading' | 'success'
+ reset: () => void
+}
+```
+
+## Configuration
+
+### chainId (optional)
+
+Chain id to switch to. Useful if you want to switch to a specific chain, instead of [displaying a list](/react/hooks/useNetwork#usage).
+
+```tsx {5}
+import { useSwitchNetwork } from 'wagmi'
+
+function App() {
+ const network = useSwitchNetwork({
+ chainId: 69,
+ })
+}
+```
+
+### throwForSwitchChainNotSupported (optional)
+
+Flag that forces `switchNetwork` to be defined, even if the connected wallet does not support programmatic network switching.
+
+```tsx {5}
+import { useSwitchNetwork } from 'wagmi'
+
+function App() {
+ const network = useSwitchNetwork({
+ throwForSwitchChainNotSupported: true,
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while attempting to switch network.
+
+```tsx {5-7}
+import { useSwitchNetwork } from 'wagmi'
+
+function App() {
+ const network = useSwitchNetwork({
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onMutate (optional)
+
+Function fires before switch network function and is passed same variables switch network function would receive. Value returned from this function will be passed to both `onError` and `onSettled` functions in event of a switch network failure.
+
+```tsx {5-7}
+import { useSwitchNetwork } from 'wagmi'
+
+function App() {
+ const network = useSwitchNetwork({
+ onMutate(args) {
+ console.log('Mutate', args)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when switch network is settled (either successfully switched, or an error has thrown).
+
+```tsx {5-7}
+import { useSwitchNetwork } from 'wagmi'
+
+function App() {
+ const network = useSwitchNetwork({
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when switch network is successful.
+
+```tsx {5-7}
+import { useSwitchNetwork } from 'wagmi'
+
+function App() {
+ const network = useSwitchNetwork({
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useToken.en-US.mdx b/docs/pages/react/hooks/useToken.en-US.mdx
new file mode 100644
index 0000000000..589a6a43f6
--- /dev/null
+++ b/docs/pages/react/hooks/useToken.en-US.mdx
@@ -0,0 +1,241 @@
+---
+title: 'useToken'
+description: 'React Hook for fetching ERC-20 token information.'
+---
+
+# useToken
+
+Hook for fetching ERC-20 token information.
+
+```ts
+import { useToken } from 'wagmi'
+```
+
+## Usage
+
+The follow examples use [$ENS](https://etherscan.io/token/0xc18360217d8f7ab5e7c516566761ea12ce7f9d72).
+
+```tsx
+import { useToken } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useToken({
+ address: '0xc18360217d8f7ab5e7c516566761ea12ce7f9d72',
+ })
+
+ if (isLoading) return
Fetching token…
+ if (isError) return
Error fetching token
+ return
Token: {data?.symbol}
+}
+```
+
+## Return Value
+
+```tsx
+{
+ data?: {
+ address: string
+ decimals: number
+ name: string
+ symbol: string
+ totalSupply: {
+ formatted: string
+ value: BigNumber
+ }
+ }
+ error?: Error
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ refetch: (options: {
+ throwOnError: boolean
+ cancelRefetch: boolean
+ }) => Promise<{
+ address: string
+ decimals: number
+ symbol: string
+ totalSupply: {
+ formatted: string
+ value: BigNumber
+ }
+ }>
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### address (optional)
+
+Address of ERC-20 token. If `address` is not defined, hook will not run.
+
+```tsx {5}
+import { useToken } from 'wagmi'
+
+function App() {
+ const token = useToken({
+ address: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984',
+ })
+}
+```
+
+### chainId (optional)
+
+Force a specific chain id for the request. The wagmi `Client`'s ethers `provider` must be set up as a [chain-aware function](/react/client#provider-optional) for this to work correctly.
+
+```tsx {6}
+import { useToken } from 'wagmi'
+
+function App() {
+ const token = useToken({
+ address: '0xc18360217d8f7ab5e7c516566761ea12ce7f9d72',
+ chainId: 1,
+ })
+}
+```
+
+### cacheTime (optional)
+
+Time (in ms) which the data should remain in the cache. Defaults to `0`.
+
+```tsx {6}
+import { useToken } from 'wagmi'
+
+function App() {
+ const token = useToken({
+ address: '0xc18360217d8f7ab5e7c516566761ea12ce7f9d72',
+ cacheTime: 2_000,
+ })
+}
+```
+
+### enabled (optional)
+
+Set this to `false` to disable this query from automatically running. Defaults to `true`.
+
+```tsx {6}
+import { useToken } from 'wagmi'
+
+function App() {
+ const token = useToken({
+ address: '0xc18360217d8f7ab5e7c516566761ea12ce7f9d72',
+ enabled: false,
+ })
+}
+```
+
+### formatUnits (optional)
+
+Formats fee data using ethers [units](https://docs.ethers.io/v5/api/utils/display-logic/#display-logic--units). Defaults to `ether`.
+
+```tsx {6}
+import { useToken } from 'wagmi'
+
+function App() {
+ const token = useToken({
+ address: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984',
+ formatUnits: 'gwei',
+ })
+}
+```
+
+### scopeKey (optional)
+
+Scopes the cache to a given context. Hooks that have identical context will share the same cache.
+
+```tsx {6}
+import { useToken } from 'wagmi'
+
+function App() {
+ const token = useToken({
+ address: '0xc18360217d8f7ab5e7c516566761ea12ce7f9d72',
+ scopeKey: 'wagmi',
+ })
+}
+```
+
+### staleTime (optional)
+
+Time (in ms) after data is considered stale. If set to `Infinity` the data will never be considered stale. Defaults to `1000 * 60 * 60 * 24` (24 hours).
+
+```tsx {6}
+import { useToken } from 'wagmi'
+
+function App() {
+ const token = useToken({
+ address: '0xc18360217d8f7ab5e7c516566761ea12ce7f9d72',
+ staleTime: 2_000,
+ })
+}
+```
+
+### suspense (optional)
+
+Set this to `true` to enable suspense mode.
+
+```tsx {6}
+import { useToken } from 'wagmi'
+
+function App() {
+ const token = useToken({
+ address: '0xc18360217d8f7ab5e7c516566761ea12ce7f9d72',
+ suspense: true,
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching new data is successful.
+
+```tsx {6-8}
+import { useToken } from 'wagmi'
+
+function App() {
+ const token = useToken({
+ address: '0xc18360217d8f7ab5e7c516566761ea12ce7f9d72',
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {6-8}
+import { useToken } from 'wagmi'
+
+function App() {
+ const token = useToken({
+ address: '0xc18360217d8f7ab5e7c516566761ea12ce7f9d72',
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {6-8}
+import { useToken } from 'wagmi'
+
+function App() {
+ const token = useToken({
+ address: '0xc18360217d8f7ab5e7c516566761ea12ce7f9d72',
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useTransaction.en-US.mdx b/docs/pages/react/hooks/useTransaction.en-US.mdx
new file mode 100644
index 0000000000..ce892ea7f8
--- /dev/null
+++ b/docs/pages/react/hooks/useTransaction.en-US.mdx
@@ -0,0 +1,185 @@
+---
+title: 'useTransaction'
+description: 'React Hook for fetching transaction by hash.'
+---
+
+# useTransaction
+
+Hook for fetching transaction by hash.
+
+```ts
+import { useTransaction } from 'wagmi'
+```
+
+## Usage
+
+```tsx
+import { useTransaction } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ })
+
+ if (isLoading) return
Fetching transaction…
+ if (isError) return
Error fetching transaction
+ return
Transaction: {JSON.stringify(data)}
+}
+```
+
+## Return Value
+
+```tsx
+{
+ data?: TransactionResponse
+ error?: Error
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ refetch: (options: {
+ throwOnError: boolean
+ cancelRefetch: boolean
+ }) => Promise
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### chainId (optional)
+
+Force a specific chain id for the request. The wagmi `Client`'s ethers `provider` must be set up as a [chain-aware function](/react/client#provider-optional) for this to work correctly.
+
+```tsx {5}
+import { useTransaction } from 'wagmi'
+
+function App() {
+ const transaction = useTransaction({
+ chainId: 1,
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ })
+}
+```
+
+### cacheTime (optional)
+
+Time (in ms) which the data should remain in the cache. Defaults to `0`.
+
+```tsx {5}
+import { useTransaction } from 'wagmi'
+
+function App() {
+ const transaction = useTransaction({
+ cacheTime: 2_000,
+ })
+}
+```
+
+### enabled (optional)
+
+Set this to `false` to disable this query from automatically running. Defaults to `true`.
+
+```tsx {5}
+import { useTransaction } from 'wagmi'
+
+function App() {
+ const transaction = useTransaction({
+ enabled: false,
+ })
+}
+```
+
+### scopeKey (optional)
+
+Scopes the cache to a given context. Hooks that have identical context will share the same cache.
+
+```tsx {5}
+import { useTransaction } from 'wagmi'
+
+function App() {
+ const transaction = useTransaction({
+ scopeKey: 'wagmi',
+ })
+}
+```
+
+### staleTime (optional)
+
+Time (in ms) after data is considered stale. If set to `Infinity` the data will never be considered stale. Defaults to `0`.
+
+```tsx {5}
+import { useTransaction } from 'wagmi'
+
+function App() {
+ const transaction = useTransaction({
+ staleTime: 2_000,
+ })
+}
+```
+
+### suspense (optional)
+
+Set this to `true` to enable suspense mode.
+
+```tsx {5}
+import { useTransaction } from 'wagmi'
+
+function App() {
+ const transaction = useTransaction({
+ suspense: true,
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching new data is successful.
+
+```tsx {5-7}
+import { useTransaction } from 'wagmi'
+
+function App() {
+ const transaction = useTransaction({
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {5-7}
+import { useTransaction } from 'wagmi'
+
+function App() {
+ const transaction = useTransaction({
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {5-7}
+import { useTransaction } from 'wagmi'
+
+function App() {
+ const transaction = useTransaction({
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useWaitForTransaction.en-US.mdx b/docs/pages/react/hooks/useWaitForTransaction.en-US.mdx
new file mode 100644
index 0000000000..e03264cc83
--- /dev/null
+++ b/docs/pages/react/hooks/useWaitForTransaction.en-US.mdx
@@ -0,0 +1,268 @@
+---
+title: 'useWaitForTransaction'
+description: 'React Hook for declaratively waiting until transaction is processed. Pairs well with useContractWrite and useSendTransaction.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# useWaitForTransaction
+
+Hook for declaratively waiting until transaction is processed. Pairs well with [`useContractWrite`](/react/hooks/useContractWrite) and [`useSendTransaction`](/react/hooks/useSendTransaction).
+
+```ts
+import { useWaitForTransaction } from 'wagmi'
+```
+
+## Usage
+
+```tsx
+import { useWaitForTransaction } from 'wagmi'
+
+function App() {
+ const { data, isError, isLoading } = useWaitForTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ })
+
+ if (isLoading) return
Processing…
+ if (isError) return
Transaction error
+ return
Transaction: {JSON.stringify(data)}
+}
+```
+
+Hook does not run unless `hash` is defined.
+
+## Return Value
+
+```tsx
+{
+ data?: TransactionReceipt
+ error?: Error
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ refetch: (options: {
+ throwOnError: boolean
+ cancelRefetch: boolean
+ }) => Promise
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### chainId (optional)
+
+Force a specific chain id for waiting on transaction. The wagmi `Client`'s ethers `provider` must be set up as a [chain-aware function](/react/client#provider-optional) for this to work correctly.
+
+```tsx {5}
+import { useWaitForTransaction } from 'wagmi'
+
+function App() {
+ const waitForTransaction = useWaitForTransaction({
+ chainId: 1,
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ })
+}
+```
+
+### confirmations (optional)
+
+Waits until confirmations number of blocks are mined on top of the block containing the transaction. Defaults to `1`. If confirmations is `0`, hook will not wait and return immediately without blocking, likely resulting in `data` being `null`.
+
+```tsx {5}
+import { useWaitForTransaction } from 'wagmi'
+
+function App() {
+ const waitForTransaction = useWaitForTransaction({
+ confirmations: 1,
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ })
+}
+```
+
+### hash (optional)
+
+Transaction hash to monitor. Works well with [`useContractWrite`](/react/hooks/useContractWrite) and [`useSendTransaction`](/react/hooks/useSendTransaction).
+
+```tsx {15}
+import {
+ useContractWrite,
+ usePrepareContractWrite,
+ useWaitForTransaction,
+} from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ })
+ const contractWrite = useContractWrite(config)
+ const waitForTransaction = useWaitForTransaction({
+ hash: contractWrite.data?.hash,
+ })
+}
+```
+
+### timeout (optional)
+
+Maximum amount of time to wait before timing out in milliseconds. Defaults to `0` (will wait until transaction processes).
+
+```tsx {6}
+import { useWaitForTransaction } from 'wagmi'
+
+function App() {
+ const waitForTransaction = useWaitForTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ timeout: 2_000, // 2 seconds
+ })
+}
+```
+
+### cacheTime (optional)
+
+Time (in ms) which the data should remain in the cache.
+
+```tsx {6}
+import { useWaitForTransaction } from 'wagmi'
+
+function App() {
+ const waitForTransaction = useWaitForTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ cacheTime: 2_000,
+ })
+}
+```
+
+### enabled (optional)
+
+Set this to `false` to disable this query from automatically running. Defaults to `true`.
+
+```tsx {6}
+import { useWaitForTransaction } from 'wagmi'
+
+function App() {
+ const waitForTransaction = useWaitForTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ enabled: false,
+ })
+}
+```
+
+### scopeKey (optional)
+
+Scopes the cache to a given context. Hooks that have identical context will share the same cache.
+
+```tsx {6}
+import { useWaitForTransaction } from 'wagmi'
+
+function App() {
+ const waitForTransaction = useWaitForTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ scopeKey: 'wagmi',
+ })
+}
+```
+
+### staleTime (optional)
+
+Time (in ms) after data is considered stale. If set to `Infinity` the data will never be considered stale. Defaults to `0`.
+
+```tsx {6}
+import { useWaitForTransaction } from 'wagmi'
+
+function App() {
+ const waitForTransaction = useWaitForTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ staleTime: 2_000,
+ })
+}
+```
+
+### suspense (optional)
+
+Set this to `true` to enable suspense mode.
+
+```tsx {6}
+import { useWaitForTransaction } from 'wagmi'
+
+function App() {
+ const waitForTransaction = useWaitForTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ suspense: true,
+ })
+}
+```
+
+### onSpeedUp (optional)
+
+Callback to invoke when the transaction has been sped up (replaced with higher gas fee values).
+
+```ts {5}
+import { useWaitForTransaction } from 'wagmi'
+
+function App() {
+ const waitForTransaction = useWaitForTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ onSpeedUp(data) {
+ console.log('Transaction has been sped up', data)
+ },
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching new data is successful.
+
+```tsx {6-8}
+import { useWaitForTransaction } from 'wagmi'
+
+function App() {
+ const waitForTransaction = useWaitForTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {6-8}
+import { useWaitForTransaction } from 'wagmi'
+
+function App() {
+ const waitForTransaction = useWaitForTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {6-8}
+import { useWaitForTransaction } from 'wagmi'
+
+function App() {
+ const waitForTransaction = useWaitForTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
diff --git a/docs/pages/react/hooks/useWatchPendingTransactions.en-US.mdx b/docs/pages/react/hooks/useWatchPendingTransactions.en-US.mdx
new file mode 100644
index 0000000000..71ce98d046
--- /dev/null
+++ b/docs/pages/react/hooks/useWatchPendingTransactions.en-US.mdx
@@ -0,0 +1,71 @@
+---
+title: 'useWatchPendingTransactions'
+description: 'Action for subscribing to pending transactions.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# useWatchPendingTransactions
+
+Hook for subscribing to pending transactions in the Provider's transaction [mempool](https://www.alchemy.com/overviews/what-is-a-mempool).
+
+```ts
+import { useWatchPendingTransactions } from 'wagmi'
+```
+
+
+ Only Providers that support the `eth_newPendingTransactionFilter` method will
+ work with this Hook.
+
+
+## Usage
+
+The listener will be invoked when a new transactions enters the memory pool of the Provider.
+
+```ts
+import { useWatchPendingTransactions } from 'wagmi'
+
+useWatchPendingTransactions({
+ listener: (transaction) => console.log(transaction),
+})
+```
+
+## Configuration
+
+### listener
+
+The listener function to be invoked when a new transaction enters the memory pool.
+
+```ts {4}
+import { useWatchPendingTransactions } from 'wagmi'
+
+useWatchPendingTransactions({
+ listener: (transaction) => console.log(transaction),
+})
+```
+
+### chainId (optional)
+
+Force a specific chain id for the request. The wagmi `Client`'s ethers `provider` must be set up as a [chain-aware function](/core/client#provider-optional) for this to work correctly.
+
+```ts {4}
+import { useWatchPendingTransactions } from 'wagmi'
+
+useWatchPendingTransactions({
+ chainId: 1,
+ listener: (transaction) => console.log(transaction),
+})
+```
+
+### enabled (optional)
+
+Whether or not to enable the listener. Defaults to `true`.
+
+```ts {4}
+import { useWatchPendingTransactions } from 'wagmi'
+
+useWatchPendingTransactions({
+ enabled: false,
+ listener: (transaction) => console.log(transaction),
+})
+```
diff --git a/docs/pages/react/hooks/useWebSocketProvider.en-US.mdx b/docs/pages/react/hooks/useWebSocketProvider.en-US.mdx
new file mode 100644
index 0000000000..1a2a5724f0
--- /dev/null
+++ b/docs/pages/react/hooks/useWebSocketProvider.en-US.mdx
@@ -0,0 +1,44 @@
+---
+title: 'useWebSocketProvider'
+description: "React Hook for accessing the Client's ethers WebSocket Provider."
+---
+
+# useWebSocketProvider
+
+Hook for accessing the `Client`'s ethers WebSocket Provider.
+
+```ts
+import { useWebSocketProvider } from 'wagmi'
+```
+
+## Usage
+
+```tsx
+import { useWebSocketProvider } from 'wagmi'
+
+function App() {
+ const webSocketProvider = useWebSocketProvider()
+}
+```
+
+## Return Value
+
+```tsx
+WebSocketProvider
+```
+
+## Configuration
+
+### chainId (optional)
+
+Force a specific chain id. The wagmi `Client`'s ethers `webSocketProvider` must be set up as a [chain-aware function](/react/client#websocketprovider-optional) for this to work correctly.
+
+```tsx {5}
+import { useWebSocketProvider } from 'wagmi'
+
+function App() {
+ const webSocketProvider = useWebSocketProvider({
+ chainId: 1,
+ })
+}
+```
diff --git a/docs/pages/react/migration-guide.en-US.mdx b/docs/pages/react/migration-guide.en-US.mdx
new file mode 100644
index 0000000000..6798f9d957
--- /dev/null
+++ b/docs/pages/react/migration-guide.en-US.mdx
@@ -0,0 +1,2056 @@
+---
+title: 'Migration Guide'
+description: 'Guide for how to migrate to new versions of wagmi'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# Migration Guide
+
+If you are coming from an earlier version of `wagmi`, you will need to make sure to update the following APIs listed below.
+
+## 0.12.x Breaking changes
+
+### WalletConnectConnector
+
+WalletConnect v1 has been sunset and `WalletConnectConnector` now uses WalletConnect v2 by default.
+
+wagmi still supports WalletConnect v1 via a [`WalletConnectLegacyConnector`](/core/migration-guide#if-you-are-still-using-walletconnect-v1), however, it is recommended to migrate to WalletConnect v2. Instructions can be found [here](/core/connectors/walletConnect).
+
+##### If you are already using WalletConnect v2:
+
+The `version` flag has been omitted, and `qrcode` has been renamed to `showQrModal`.
+
+```diff
+import { WalletConnectConnector } from 'wagmi/connectors/walletConnect'
+
+const connector = new WalletConnectConnector({
+ options: {
+- version: '2',
+ projectId: '...',
+- qrcode: true,
++ showQrModal: true,
+ },
+})
+```
+
+[Read more on `WalletConnectConnector`](/core/connectors/walletConnect)
+
+##### If you are still using WalletConnect v1:
+
+
+ You must migrate to the [WalletConnect v2
+ Connector](/core/connectors/walletConnect) before June 28, after which, the
+ `WalletConnectLegacyConnector` will be removed.
+
+
+```diff
+-import { WalletConnectConnector } from 'wagmi/connectors/walletConnect'
++import { WalletConnectLegacyConnector } from 'wagmi/connectors/walletConnectLegacy'
+
+-const connector = new WalletConnectConnector({
++const connector = new WalletConnectLegacyConnector({
+ options: {
+ qrcode: true,
+ },
+})
+```
+
+[Read more on `WalletConnectLegacyConnector`](/core/connectors/walletConnectLegacy)
+
+## 0.11.x Breaking changes
+
+
+ Not ready to migrate yet? You can find the `0.10.x` docs
+ [here](https://0.10.x.wagmi.sh).
+
+
+### Upgrade to typescript@>=4.9.4
+
+[TypeScript 5.0](https://github.com/microsoft/TypeScript/issues/51362) is coming soon and has some great features we are excited to bring into wagmi. To prepare for this, update your TypeScript version to 4.9.4 or higher. There are likely no [breaking changes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html#correctness-fixes-and-breaking-changes) if you are coming from `typescript@4.7.x || typescript@4.8.x`.
+
+## 0.10.x Breaking changes
+
+
+ Not ready to migrate yet? You can find the `0.9.x` docs
+ [here](https://0.9.x.wagmi.sh).
+
+
+### `useSigner`
+
+The `useSigner` hook now always returns `undefined` when no signer is present. Previously, it returned `null` or `undefined`.
+
+When no signer is present, the hook will be in an `"idle"` status.
+
+## 0.9.x Breaking changes
+
+
+ Not ready to migrate yet? You can find the `0.8.x` docs
+ [here](https://0.8.x.wagmi.sh).
+
+
+### Chain exports
+
+With the introduction of the [`wagmi/chains` entrypoint](/react/chains#wagmichains), `wagmi` no longer exports the following:
+
+- `chain`
+- `allChains`
+- `defaultChains`
+- `defaultL2Chains`
+- `chainId`
+- `etherscanBlockExplorers`
+- `alchemyRpcUrls`, `infuraRpcUrls`, `publicRpcUrls`
+
+Read below for migration steps.
+
+#### Removed `chain`
+
+The `chain` export has been removed. `wagmi` now only exports the `mainnet` & `goerli` chains. If you need to use an alternative chain (`polygon`, `optimism`, etc), you will need to import it from the [`wagmi/chains` entrypoint](/react/chains#wagmichains).
+
+```diff
+import {
+- chain
+ configureChains
+} from 'wagmi'
++ import { mainnet, polygon, optimism } from 'wagmi/chains'
+
+const { ... } = configureChains(
+- [chain.mainnet, chain.polygon, chain.optimism],
++ [mainnet, polygon, optimism],
+ {
+ ...
+ }
+)
+```
+
+#### Removed `allChains`
+
+The `allChains` export has been removed. If you need a list of all chains, you can utilize [`wagmi/chains` entrypoint](/react/chains#wagmichains).
+
+```diff
+- import { allChains } from 'wagmi'
++ import * as allChains from 'wagmi/chains'
+
+const { ... } = configureChains(allChains, ...)
+```
+
+#### Removed `defaultChains` & `defaultL2Chains`
+
+The `defaultChains` & `defaultL2Chains` exports have been removed. If you still need the `defaultChains` or `defaultL2Chains` exports, you can build them yourself:
+
+```diff
+- import { defaultChains } from 'wagmi'
++ import { mainnet, goerli } from 'wagmi/chains'
+
++ const defaultChains = [mainnet, goerli]
+```
+
+> The `defaultChains` export was previously populated with `mainnet` & `goerli`.
+
+```diff
+- import { defaultL2Chains } from 'wagmi'
++ import {
++ arbitrum,
++ arbitrumGoerli,
++ polygon,
++ polygonMumbai,
++ optimism,
++ optimismGoerli
++ } from 'wagmi/chains'
+
++ const defaultL2Chains = [
++ arbitrum,
++ arbitrumGoerli,
++ polygon,
++ polygonMumbai,
++ optimism
++ optimismGoerli
++ ]
+```
+
+> The `defaultL2Chains` export was previously populated with `arbitrum` & `optimism`.
+
+#### Removed `chainId`
+
+The `chainId` export has been removed. You can extract a chain ID from the chain itself.
+
+```diff
+- import { chainId } from 'wagmi'
++ import { mainnet, polygon, optimism } from 'wagmi/chains'
+
+-const mainnetChainId = chainId.mainnet
+-const polygonChainId = chainId.polygon
+-const optimismChainId = chainId.optimism
++const mainnetChainId = mainnet.id
++const polygonChainId = polygon.id
++const optimismChainId = optimism.id
+```
+
+#### Removed `etherscanBlockExplorers`
+
+The `etherscanBlockExplorers` export has been removed. You can extract a block explorer from the chain itself.
+
+```diff
+- import { etherscanBlockExplorers } from 'wagmi'
++ import { mainnet, polygon, optimism } from 'wagmi/chains'
+
+-const mainnetEtherscanBlockExplorer = etherscanBlockExplorers.mainnet
+-const polygonEtherscanBlockExplorer = etherscanBlockExplorers.polygon
+-const optimismEtherscanBlockExplorer = etherscanBlockExplorers.optimism
++const mainnetEtherscanBlockExplorer = mainnet.blockExplorers.default
++const polygonEtherscanBlockExplorer = polygon.blockExplorers.default
++const optimismEtherscanBlockExplorer = optimism.blockExplorers.default
+```
+
+#### Removed `alchemyRpcUrls`, `infuraRpcUrls` & `publicRpcUrls`
+
+The `alchemyRpcUrls`, `infuraRpcUrls` & `publicRpcUrls` exports have been removed. You can extract a RPC URL from the chain itself.
+
+```diff
+- import { alchemyRpcUrls, infuraRpcUrls, publicRpcUrls } from 'wagmi'
++ import { mainnet } from 'wagmi/chains'
+
+-const mainnetAlchemyRpcUrl = alchemyRpcUrls.mainnet
+-const mainnetInfuraRpcUrl = infuraRpcUrls.mainnet
+-const mainnetOptimismRpcUrl = publicRpcUrls.mainnet
++const mainnetAlchemyRpcUrl = mainnet.rpcUrls.alchemy
++const mainnetInfuraRpcUrl = mainnet.rpcUrls.infura
++const mainnetOptimismRpcUrl = mainnet.rpcUrls.optimism
+```
+
+### `Chain` type
+
+#### RPC URLs
+
+The `rpcUrls` shape has changed to include an array of URLs, and also the transport method (`http` or `webSocket`):
+
+```diff
+type Chain = {
+ ...
+ rpcUrls: {
+- [key: string]: string
++ [key: string]: {
++ http: string[]
++ webSocket: string[]
++ }
+ }
+ ...
+}
+```
+
+Note that you will also need to ensure that usage is migrated:
+
+```diff
+- const rpcUrl = mainnet.rpcUrls.alchemy
++ const rpcUrl = mainnet.rpcUrls.alchemy.http[0]
+```
+
+#### Contracts
+
+The `multicall` and `ens` attributes have been moved into the `contracts` object:
+
+```diff
+type Contract = {
+ address: Address
+ blockCreated?: number
+}
+
+type Chain = {
+ ...
+- multicall: Contract
+- ens: Contract
++ contracts: {
++ multicall3: Contract
++ ensRegistry: Contract
++ }
+ ...
+}
+```
+
+Note that you will also need to ensure that usage is migrated:
+
+```diff
+- const multicallContract = mainnet.multicall
++ const multicallContract = mainnet.contracts.multicall3
+```
+
+### useEnsResolver
+
+#### Behavioral changes
+
+`useEnsResolver`'s result is no longer persisted by the query client since it cannot serialize its prototype methods.
+
+#### Configuration changes
+
+Removed the `cacheTime` and `staleTime` config options.
+
+```diff
+const { data } = useEnsResolver({
+ name: 'wagmi-dev.eth',
+- cacheTime: 2000,
+- staleTime: 2000,
+})
+```
+
+### useWaitForTransaction
+
+#### Behavioral changes
+
+`useWaitForTransaction` will now return an `error` (and invoke the `onError` callback) if the transaction has been reverted or cancelled.
+
+#### Configuration changes
+
+Removed the `wait` config option on `useWaitForTransaction`. Use the transaction `hash` instead.
+
+```diff
+const { data } = useWaitForTransaction({
+- wait: transaction.wait,
++ hash: transaction.hash,
+})
+```
+
+## 0.8.x Breaking changes
+
+
+ Not ready to migrate yet? You can find the `0.7.x` docs
+ [here](https://0.7.x.wagmi.sh).
+
+
+### CommonJS Support Dropped
+
+wagmi no longer supports CommonJS and only supports [ES Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules). If you are using modern tooling, like [Next.js](https://nextjs.org), [Vite](https://vitejs.dev), or [Vitest](https://vitest.dev), you likely don't need to do anything! [Remix](https://remix.run/docs/en/v1/pages/gotchas#importing-esm-packages) and [Jest](https://jestjs.io/docs/ecmascript-modules) require some additional configuration. Check out [this guide](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) for more info on ESM support and Frequently Asked Questions across various tools and setups.
+
+### Deprecated chains removed
+
+Removed the following deprecated chains:
+
+- `ropsten`
+- `rinkeby`
+- `kovan`
+- `optimismKovan`
+- `arbitrumRinkeby`
+
+If you feel you still need to include one of these testnets in your application, you will have to define it manually:
+
+```diff
+-import { chain } from 'wagmi'
++import { Chain } from 'wagmi'
+
+-export const rinkeby = chain.rinkeby
++export const rinkeby: Chain = {
++ id: 4,
++ name: 'Rinkeby',
++ network: 'rinkeby',
++ nativeCurrency: { name: 'Rinkeby Ether', symbol: 'ETH', decimals: 18 },
++ rpcUrls: {
++ alchemy: 'https://eth-rinkeby.alchemyapi.io/v2',
++ default: 'https://rpc.ankr.com/eth_rinkeby',
++ infura: 'https://rinkeby.infura.io/v3',
++ public: 'https://rpc.ankr.com/eth_rinkeby',
++ },
++ blockExplorers: {
++ etherscan: 'https://rinkeby.etherscan.io',
++ default: 'https://rinkeby.etherscan.io',
++ },
++ ens: {
++ address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e',
++ },
++ multicall: {
++ address: '0xca11bde05977b3631167028862be2a173976ca11',
++ blockCreated: 10299530,
++ },
++ testnet: true,
+}
+```
+
+You can reference these removed chains [here](https://github.com/wagmi-dev/wagmi/blob/389765f7d9af063ab0df07389a2bbfbc10a41060/packages/core/src/constants/chains.ts).
+
+### `alchemyProvider`
+
+Made `apiKey` required on `alchemyProvider`.
+
+```diff
+import { configureChains } from 'wagmi'
+
+const config = configureChains(defaultChains, [
+- alchemyProvider(),
++ alchemyProvider({ apiKey: process.env.ALCHEMY_API_KEY })
+])
+```
+
+You can find your Alchemy API key from the [Alchemy Dashboard](https://dashboard.alchemyapi.io/), or your Infura API key from the [Infura Dashboard](https://infura.io/login).
+
+### `infuraProvider`
+
+Made `apiKey` required on `infuraProvider`.
+
+```diff
+import { configureChains } from 'wagmi'
+
+const config = configureChains(defaultChains, [
+- infuraProvider(),
++ infuraProvider({ apiKey: process.env.INFURA_API_KEY })
+])
+```
+
+You can find your Infura API key from the [Infura Dashboard](https://infura.io/login), or your Infura API key from the [Infura Dashboard](https://infura.io/login).
+
+### `useBalance`
+
+#### Configuration changes
+
+`addressOrName` renamed to `address`.
+
+```diff
+const result = useBalance({
+- addressOrName: '0x…',
++ address: '0x…',
+})
+```
+
+If you were using an ENS name instead of an address, you can resolve the name to an address before passing it to the action. This allows the ENS-to-address resolution to be cached instead of being wasted work before.
+
+```diff
++ const { data: address } = useEnsAddress({ name: 'example.eth' })
+const result = useBalance({
+- addressOrName: 'example.eth',
++ address,
+})
+```
+
+### `useEnsAvatar`
+
+#### Configuration changes
+
+`addressOrName` renamed to `address`.
+
+```diff
+const result = useEnsAvatar({
+- addressOrName: '0x…',
++ address: '0x…',
+})
+```
+
+If you were using an ENS name instead of an address, you can resolve the name to an address before passing it to the action. This allows the ENS-to-address resolution to be cached instead of being wasted work before.
+
+```diff
++ const { data: address } = useEnsAddress({ name: 'example.eth' })
+const result = useEnsAvatar({
+- addressOrName: 'example.eth',
++ address,
+})
+```
+
+## 0.7.x Breaking changes
+
+
+ Not ready to migrate yet? You can find the `0.6.x` docs
+ [here](https://0.6.x.wagmi.sh).
+
+
+### Upgrade to `typescript@>=4.7.4`
+
+wagmi can now infer types based on [ABI](https://docs.soliditylang.org/en/v0.8.15/abi-spec.html#json) and [EIP-712](https://eips.ethereum.org/EIPS/eip-712) Typed Data definitions, giving you full end-to-end type-safety from your contracts to your frontend and incredible developer experience (e.g. autocomplete ABI function names and catch misspellings, type ABI function arguments, etc.).
+
+For this to work, you must upgrade to `typescript@>=4.7.4`. Why is TypeScript v4.7.4 or greater necessary? TypeScript 4.7.4 introduced the ability
+to [extend constraints on inferred type variables](https://devblogs.microsoft.com/typescript/announcing-typescript-4-7/#extends-constraints-on-infer-type-variables), which is used extensively to help narrow types for ABIs. Good news! When upgrading TypeScript from 4.6 to 4.7 there are likely no [breaking changes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#breaking-changes) for your set up.
+
+See the wagmi [TypeScript docs](/react/typescript) for more information on TypeScript support in this version.
+
+
+ When switching over to inferring types based on your ABIs, you may notice
+ TypeScript complaining about types that worked fine before. For example, `Type
+ 'string' is not assignable to type 'BigNumber'`. Previously, you were able to
+ use `string` types in place of `BigNumber` types, `BigNumber` types in place
+ of `number` types, etc.
+
+ The types inferred directly from ABIs are more correct and strict so you will
+ need to convert your types to match. This should be pretty straightforward by
+ following the error from TypeScript. Based on the error above, `args: ['123']`
+ should be updated to `args: [BigNumber.from('123')]`.
+
+
+### `addressOrName` and `contractInterface` renamed for contract hooks
+
+`addressOrName` and `contractInterface` renamed to `address` and `abi` respectively for the following contract hooks: `useContract`, `useContractEvent`, `useContractRead`, `useContractReads`, `useContractInfiniteReads`, `useContractWrite`, and `usePrepareContractWrite`.
+
+```diff
+import { useContractRead } from 'wagmi'
+const result = useContractRead({
+- addressOrName: '0x…',
++ address: '0x…',
+- contractInterface: […],
++ abi: […],
+ functionName: 'balanceOf',
+ args: ['0x…'],
+})
+```
+
+If you were using an ENS name instead of an address, you can resolve the name to an address before passing it to the action.
+
+```diff
+- import { useContractRead } from 'wagmi'
++ import { useContractRead, useEnsAddress } from 'wagmi'
++ const { data: address } = useEnsAddress({ name: 'example.eth' })
+const result = useContractRead({
+- addressOrName: 'example.eth',
++ address,
+ abi: […],
+ functionName: 'balanceOf',
+ args: ['0x…'],
+})
+```
+
+### `args` type changed for contract hooks
+
+`args` config option must now be an array for the following hooks: `useContractRead`, `useContractWrite`, `usePrepareContractWrite`, `useContractReads`, and `useContractInfiniteReads`.
+
+```diff
+const { data } = useContractRead({
+ address: '0x…',
+ abi: […],
+ functionName: 'balanceOf',
+- args: '0x…',
++ args: ['0x…'],
+})
+```
+
+### `useContractEvent`
+
+#### Configuration changes
+
+`signerOrProvider` was removed.
+
+### useContractInfiniteReads
+
+#### Configuration changes
+
+Updated `paginatedIndexesConfig` `fn` parameter return type. `fn` now returns an array instead of a single object.
+
+```diff
+useContractInfiniteReads({
+ cacheKey: 'contracts',
+ ...paginatedIndexesConfig(
+- (index) => ({
++ (index) => [{
+ address: '0x…',
+ abi: […],
+ functionName: 'tokenURI',
+ args: [BigNumber.from(index)] as const,
+- }),
++ }],
+ { start: 0, perPage: 10, direction: 'increment' },
+ ),
+})
+```
+
+### `usePrepareContractWrite`
+
+#### Behavioral changes
+
+Throws an error when a `chainId` is specified and the end-user is on a different chain id (the wrong network). If you wish to defer this check until the click handler is pressed, you can place the `chainId` in `useContractWrite` instead.
+
+### `usePrepareSendTransaction`
+
+#### Behavioral changes
+
+- The `usePrepareSendTransaction` hook will now only run when the end-user is connected to their wallet. This is to reach parity with `usePrepareContractWrite`. If the end-user is not connected, then the `usePrepareSendTransaction` hook will remain idle.
+- Throws an error when a `chainId` is specified and the end-user is on a different chain id (the wrong network). If you wish to defer this check until the click handler is pressed, you can place `chainId` in `useContractWrite` instead.
+
+## 0.6.x Breaking changes
+
+
+ Not ready to migrate yet? You can find the `0.5.x` docs
+ [here](https://0.5.x.wagmi.sh).
+
+
+All the breaking changes in this release are related to the introduction of [Prepare Hooks](/react/prepare-hooks). It is recommended to read the [Prepare Hooks](/react/prepare-hooks) section before migrating to 0.6.x.
+
+### `useContractWrite`
+
+
+ Not ready to migrate to the new `useContractWrite` yet? You can use the
+ [`useDeprecatedContractWrite`
+ hook](/react/deprecated-hooks/useDeprecatedContractWrite).
+
+
+#### Behavioral changes
+
+If a `chainId` is passed to `useContractWrite`, it will no longer attempt to switch chain before sending the transaction. Instead, it will throw an error if the user is on the wrong chain.
+
+> Why? Eagerly prompting to switch chain in these actions created a long-running async task that makes [iOS App Links](/react/prepare-hooks#ios-app-link-constraints) vulnerable.
+
+#### Configuration changes
+
+The configuration passed to the `useContractWrite` hook now needs to be either:
+
+- prepared with the [`usePrepareContractWrite` Prepare Hook](/react/prepare-hooks/usePrepareContractWrite) **(new)**, or
+- recklessly unprepared **(previous functionality)**
+
+> Why? To avoid long-running asynchronous tasks in event handlers. [Read more about Prepare Hooks](/react/prepare-hooks).
+
+**Prepared usage**
+
+```diff
++const { config } = usePrepareContractWrite({
++ addressOrName: '0x...',
++ contractInterface: wagmiAbi,
++ functionName: 'mint',
++ args: [tokenId]
++})
+const { data } = useContractWrite({
+- addressOrName: '0x...',
+- contractInterface: wagmiAbi,
+- functionName: 'mint',
+- args: [tokenId],
++ ...config
+})
+```
+
+**Recklessly unprepared usage**
+
+If you are not ready to upgrade to `usePrepareContractWrite`, it is possible to use `useContractWrite` without preparing the configuration first by passing `mode: 'recklesslyUnprepared'`.
+
+```diff
+const { data } = useContractWrite({
++ mode: 'recklesslyUnprepared',
+ addressOrName: '0x...',
+ contractInterface: wagmiAbi,
+ functionName: 'mint',
+ args: [tokenId],
+})
+```
+
+#### Return value changes
+
+**`data` now only returns `hash` & `wait`**
+
+`data` now returns an object only consisting of `hash` & `wait`, and not the full [`TransactionResponse`](https://docs.ethers.io/v5/api/providers/types/#providers-TransactionResponse).
+
+If you require the full `TransactionResponse`, you can use `useTransaction`:
+
+```diff
+const {
+ data: {
+ hash,
+ wait,
+- ...transaction
+ }
+} = useContractWrite(...)
++const { data: transaction } = useTransaction({ hash })
+```
+
+> Why? The old implementation of `useContractWrite` created a long-running async task, causing [UX pitfalls](/react/prepare-hooks#ux-pitfalls-without-prepare-hooks) when invoked in a click handler.
+
+**`write`/`writeAsync` arguments**
+
+The `write`/`writeAsync` configuration object has now been altered to only accept "reckless" configuration. If one or more of these values are set, it can lead to [UX pitfalls](/react/prepare-hooks#ux-pitfalls-without-prepare-hooks).
+
+```diff
+
+```
+
+**`write`/`writeAsync` can be `undefined`**
+
+When `useContractWrite` is in "prepare mode" (used with `usePrepareContractWrite`), `write`/`writeAsync` will be `undefined` until the configuration has been prepared. Ensure that your usage reflects this.
+
+```tsx
+const { config } = usePrepareContractWrite({ ... })
+const { write } = useContractWrite(config)
+
+
+```
+
+### `useSendTransaction`
+
+
+ Not ready to migrate to the new `useSendTransaction` yet? You can use the
+ [`useDeprecatedSendTransaction`
+ hook](/react/deprecated-hooks/useDeprecatedSendTransaction).
+
+
+#### Behavioral changes
+
+If a `chainId` is passed to `useSendTransaction`, it will no longer attempt to switch chain before sending the transaction. Instead, it will throw an error if the user is on the wrong chain.
+
+> Why? Eagerly prompting to switch chain in these actions created a long-running async task that makes [iOS App Links](/react/prepare-hooks#ios-app-link-constraints) vulnerable.
+
+#### Configuration changes
+
+The configuration passed to the `useSendTransaction` hook now needs to be either:
+
+- prepared with the [`usePrepareSendTransaction` Prepare Hook](/react/prepare-hooks/usePrepareSendTransaction) **(new)**, or
+- recklessly unprepared **(previous functionality)**
+
+> Why? To avoid long-running asynchronous tasks in event handlers. [Read more about Prepare Hooks](/react/prepare-hooks).
+
+**Prepared usage**
+
+```diff
+import { usePrepareSendTransaction, useSendTransaction } from 'wagmi'
+
++const { config } = usePrepareSendTransaction({
++ request: {
++ to: 'moxey.eth',
++ value: parseEther('1'),
++ }
++})
+const { data } = useSendTransaction({
+- request: {
+- to: 'moxey.eth',
+- value: parseEther('1')
+- }
++ ...config
+})
+```
+
+**Recklessly unprepared usage**
+
+If you are not ready to upgrade to `usePrepareSendTransaction`, it is possible to use `useSendTransaction` without preparing the configuration first by passing `mode: 'recklesslyUnprepared'`.
+
+```diff
+import { useSendTransaction } from 'wagmi'
+
+const { data } = useSendTransaction({
++ mode: 'recklesslyUnprepared',
+ request: {
+ to: 'moxey.eth',
+ value: parseEther('1'),
+ }
+})
+```
+
+#### Return value changes
+
+**`data` now only returns `hash` & `wait`**
+
+`data` now returns an object only consisting of `hash` & `wait`, and not the full [`TransactionResponse`](https://docs.ethers.io/v5/api/providers/types/#providers-TransactionResponse).
+
+If you require the full `TransactionResponse`, you can use `useTransaction`:
+
+```diff
+const {
+ data: {
+ hash,
+ wait,
+- ...transaction
+ }
+} = useSendTransaction(...)
++const { data: transaction } = useTransaction({ hash })
+```
+
+> Why? The old implementation of `useSendTransaction` created a long-running async task, causing [UX pitfalls](/react/prepare-hooks#ux-pitfalls-without-prepare-hooks) when invoked in a click handler.
+
+**`sendTransaction`/`sendTransactionAsync` arguments**
+
+The `sendTransaction`/`sendTransactionAsync` configuration object has now been altered to only accept "reckless" configuration. If one or more of these values are set, it can lead to [UX pitfalls](/react/prepare-hooks#ux-pitfalls-without-prepare-hooks).
+
+```diff
+
+```
+
+**`sendTransaction`/`sendTransactionAsync` can be `undefined`**
+
+When `useSendTransaction` is in "prepare mode" (used with `usePrepareSendTransaction`), `sendTransaction`/`sendTransactionAsync` will be `undefined` until the configuration has been prepared. Ensure that your usage reflects this.
+
+```tsx
+const { config } = usePrepareSendTransaction({ ... })
+const { sendTransaction } = useSendTransaction(config)
+
+
+```
+
+### `alchemyProvider` and `infuraProvider`
+
+`alchemyProvider` and `infuraProvider` now use a generic `apiKey` configuration option instead of `alchemyId` and `infuraId`.
+
+```diff
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { infuraProvider } from 'wagmi/providers/infura'
+
+alchemyProvider({
+- alchemyId: 'yourAlchemyApiKey',
++ apiKey: 'yourAlchemyApiKey',
+})
+
+infuraProvider({
+- infuraId: 'yourInfuraApiKey',
++ apiKey: 'yourInfuraApiKey',
+})
+```
+
+## 0.5.x Breaking changes
+
+
+ Not ready to migrate yet? You can find the `0.4.x` docs
+ [here](https://0.4.x.wagmi.sh).
+
+
+### `WagmiConfig`
+
+The `client` prop is now required on `WagmiConfig`.
+
+````diff
+```tsx
+import {
+ createClient,
++ configureChains,
++ defaultChains
+} from 'wagmi'
++import { publicProvider } from 'wagmi/providers/public'
+
++const { provider, webSocketProvider } = configureChains(defaultChains, [
++ publicProvider(),
++])
+
++const client = createClient({
++ provider,
++ webSocketProvider,
++})
+
+function App() {
+ return (
+
+
+
+ )
+}
+````
+
+### `createClient`
+
+#### `provider` is now required
+
+The `provider` config option is now required on `createClient`. It is recommended to pass the [`provider` given from `configureChains`](/react/providers/configuring-chains).
+
+```diff
+import {
+ createClient,
++ defaultChains,
++ configureChains
+} from 'wagmi'
++import { publicProvider } from 'wagmi/providers/publicProvider'
+
++const { provider } = configureChains(defaultChains, [
++ publicProvider
++])
+
+const client = createClient({
++ provider
+})
+```
+
+If you previously used an ethers.js Provider, you now need to provide your `chains` on the Provider instance:
+
+```diff
+import {
+ createClient,
++ defaultChains
+} from 'wagmi'
+import ethers from 'ethers'
+
+const client = createClient({
+- provider: getDefaultProvider()
++ provider: Object.assign(getDefaultProvider(), { chains: defaultChains })
+})
+```
+
+#### `chainId` removed from `connectors`
+
+Removed the `chainId` parameter from `connectors` function on `createClient`.
+
+```diff
+const client = createClient({
+- connectors({ chainId }) {
++ connectors() {
+ ...
+ }
+})
+```
+
+If you previously derived RPC URLs from the `chainId` on `connectors`, you can now remove that logic as `wagmi` now handles RPC URLs internally when used with `configureChains`.
+
+```diff
+import {
+ chain,
++ configureChains,
+ createClient
+} from 'wagmi';
+
++import { publicProvider } from 'wagmi/providers/public'
+
+import { CoinbaseWalletConnector } from 'wagmi/connectors/coinbaseWallet'
+import { InjectedConnector } from 'wagmi/connectors/injected'
+import { MetaMaskConnector } from 'wagmi/connectors/metaMask'
+import { WalletConnectConnector } from 'wagmi/connectors/walletConnect'
+
++const { chains } = configureChains(
++ [chain.mainnet],
++ [publicProvider()]
++);
+
+const client = createClient({
+- connectors({ chainId }) {
+- const chain = chains.find((x) => x.id === chainId) ?? defaultChain
+- const rpcUrl = chain.rpcUrls.alchemy
+- ? `${chain.rpcUrls.alchemy}/${alchemyId}`
+- : chain.rpcUrls.default
+- return [
++ connectors: [
+ new MetaMaskConnector({ chains }),
+ new CoinbaseWalletConnector({
+ chains,
+ options: {
+ appName: 'wagmi',
+- chainId: chain.id,
+- jsonRpcUrl: rpcUrl,
+ },
+ }),
+ new WalletConnectConnector({
+ chains,
+ options: {
+ qrcode: true,
+- rpc: { [chain.id]: rpcUrl },
+ },
+ }),
+ new InjectedConnector({
+ chains,
+ options: { name: 'Injected' },
+ }),
+ ]
+- },
+})
+```
+
+### `useAccount`
+
+#### Return value changes
+
+**The `data` value is now `address` & `connector`**
+
+```diff
+{
+- data?: {
+- address: string
+- connector: Connector
+- }
++ address?: string
++ connector?: Connector
+}
+```
+
+**Global connection status values have been added**
+
+The following global connection status values have been added:
+
+```diff
+{
++ isConnecting: boolean
++ isReconnecting: boolean
++ isConnected: boolean
++ isDisconnected: boolean
++ status: 'connecting' | 'reconnecting' | 'connected' | 'disconnected'
+}
+```
+
+The `useAccount` hook is now aware of any connection event in your application, so now you can use these connection status values to determine if your user is connected, disconnected or connecting to a wallet on a global scope.
+
+**`error`, states & `refetch` values have been removed**
+
+Since the `useAccount` hook never dealt with asynchronous data, all of these values were
+redundant & unused.
+
+```diff
+{
+- error?: Error
+- isIdle: boolean
+- isLoading: boolean
+- isFetching: boolean
+- isSuccess: boolean
+- isError: boolean
+- isFetched: boolean
+- isRefetching: boolean
+- refetch: (options: {
+- throwOnError: boolean
+- cancelRefetch: boolean
+- }) => Promise<{
+- address: string
+- connector: Connector
+- }>
+- status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+**Summary of changes**
+
+Below is the whole diff of changes to the `useAccount` return value.
+
+```diff
+{
+- data?: {
+- address: string
+- connector: Connector
+- }
++ address?: string
++ connector?: Connector
+- error?: Error
+- isIdle: boolean
+- isLoading: boolean
+- isFetching: boolean
+- isSuccess: boolean
+- isError: boolean
+- isFetched: boolean
+- isRefetching: boolean
++ isConnecting: boolean
++ isReconnecting: boolean
++ isConnected: boolean
++ isDisconnected: boolean
+- refetch: (options: {
+- throwOnError: boolean
+- cancelRefetch: boolean
+- }) => Promise<{
+- address: string
+- connector: Connector
+- }>
+- status: 'idle' | 'error' | 'loading' | 'success'
++ status: 'connecting' | 'reconnecting' | 'connected' | 'disconnected'
+}
+```
+
+#### Configuration changes
+
+**`onConnect` has been added**
+
+The `onConnect` callback is invoked when the account connects.
+
+It provides the connected address & connector, as well as a `isReconnected` flag for if the user reconnected via `autoConnect`.
+
+```tsx
+const account = useAccount({
+ onConnect({ address, connector, isReconnected }) {
+ console.log('Connected')
+ },
+})
+```
+
+**`onDisconnect` has been added**
+
+The `onDisconnect` callback is invoked when the account disconnected.
+
+```tsx
+const account = useAccount({
+ onDisconnect() {
+ console.log('Disconnected')
+ },
+})
+```
+
+**`suspense` has been removed**
+
+The `useAccount` hook is a synchronous hook – so `suspense` never worked.
+
+```diff
+const account = useAccount({
+- suspense: true,
+})
+```
+
+**`onError` has been removed**
+
+The `useAccount` hook never had any error definitions – so `onError` was never invoked.
+
+```diff
+const account = useAccount({
+- onError(error) {
+- console.log('Error', error)
+- },
+})
+```
+
+**`onSettled` has been removed**
+
+The `useAccount` hook is a synchronous hook. `onSettled` was always invoked immediately.
+
+```diff
+const account = useAccount({
+- onSettled(data) {
+- console.log('Settled', data)
+- },
+})
+```
+
+If you used `onSettled`, you can move the code beneath the `useAccount` hook:
+
+```diff
+const account = useAccount({
+- onSettled(data) {
+- console.log('Address:', data.address)
+- },
+})
++ console.log('Address:', account.address)
+```
+
+**`onSuccess` has been removed**
+
+The `useAccount` hook is a synchronous hook. `onSuccess` was always invoked immediately.
+
+```diff
+const account = useAccount({
+- onSuccess(data) {
+- console.log('Success', data)
+- },
+})
+```
+
+If you used `onSuccess`, you can move the code beneath the `useAccount` hook:
+
+```diff
+const account = useAccount({
+- onSuccess(data) {
+- console.log('Address:', data.address)
+- },
+})
++ console.log('Address:', account.address)
+```
+
+### `useConnect`
+
+#### Return value changes
+
+**Connection status flags have been moved**
+
+The `isConnected`, `isConnecting`, `isReconnecting` & `isDisconnected` flags have been moved to the `useAccount` hook.
+
+```diff
+-import { useConnect } from 'wagmi'
++import { useAccount } from 'wagmi'
+
+function App() {
+ const {
+ isConnected,
+ isConnecting,
+ isReConnecting,
+ isDisconnected
+- } = useConnect()
++ } = useAccount()
+}
+```
+
+**New `connect` mutation status flags have been added**
+
+The `isLoading`, `isSuccess` and `isError` flags have been added to `useConnect`.
+
+These flags represent the **local** async state of `useConnect`.
+
+**`activeConnector` has been removed**
+
+The `activeConnector` value has been removed. You can find the active connector on `useAccount`.
+
+```diff
+-import { useConnect } from 'wagmi'
++import { useAccount } from 'wagmi'
+
+function App() {
+- const { activeConnector } = useConnect()
++ const { connector } = useAccount()
+}
+```
+
+**`connector` parameter on `connect` & `connectAsync` has been removed**
+
+The `connector` parameter on `connect` & `connectAsync` now has to be in the config object parameter shape.
+
+```diff
+import { useConnect } from 'wagmi'
+
+function App() {
+ const { connect, connectors } = useConnect()
+
+ return (
+
+ )
+}
+```
+
+#### Configuration changes
+
+**`onBeforeConnect` has been renamed**
+
+The `onBeforeConnect` callback has been renamed to `onMutate`
+
+**`onConnect` has been renamed**
+
+The `onConnect` callback has been renamed to `onSuccess`
+
+### `useContractRead`
+
+The `useContractRead` hook parameters have been consolidated into a singular config parameter.
+
+Before:
+
+```tsx
+useContractRead(
+ {
+ addressOrName: wagmigotchiContractAddress,
+ contractInterface: wagmigotchiABI,
+ },
+ 'love',
+ { args: '0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c' },
+)
+```
+
+After:
+
+```tsx
+useContractRead({
+ addressOrName: wagmigotchiContractAddress,
+ contractInterface: wagmigotchiABI,
+ functionName: 'love',
+ args: '0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c',
+})
+```
+
+### `useContractWrite`
+
+The `useContractWrite` hook parameters have been consolidated into a singular config parameter.
+
+Before:
+
+```tsx
+useContractWrite(
+ {
+ addressOrName: mlootContractAddress,
+ contractInterface: mlootABI,
+ },
+ 'claim',
+)
+```
+
+After:
+
+```tsx
+useContractWrite({
+ addressOrName: mlootContractAddress,
+ contractInterface: mlootABI,
+ functionName: 'claim',
+})
+```
+
+### `useContractEvent`
+
+The `useContractEvent` hook parameters have been consolidated into a singular config parameter.
+
+Before:
+
+```tsx
+useContractEvent(
+ {
+ addressOrName: uniContractAddress,
+ contractInterface: erc20ABI,
+ },
+ 'Transfer',
+ listener,
+),
+```
+
+After:
+
+```tsx
+useContractEvent({
+ addressOrName: uniContractAddress,
+ contractInterface: erc20ABI,
+ eventName: 'Transfer',
+ listener,
+})
+```
+
+### `useNetwork`
+
+The "switch network" functionality has been moved out of `useNetwork` into a new `useSwitchNetwork` hook.
+
+The `useNetwork` hook now accepts no configuration and only returns `chain` (renamed from `activeChain`) and `chains`.
+
+```diff
+import {
+ useNetwork
++ useSwitchNetwork
+} from 'wagmi'
+
+const {
+- activeChain
++ chain,
+ chains,
+- data,
+- error,
+- isError,
+- isIdle,
+- isLoading,
+- isSuccess,
+- pendingChainId,
+- switchNetwork,
+- switchNetworkAsync,
+- status,
+- reset,
+-} = useNetwork({
+- chainId: 69,
+- onError(error) {},
+- onMutate(args) {},
+- onSettled(data, error) {},
+- onSuccess(data) {}
+-})
++} = useNetwork()
+
++const {
++ chains,
++ data,
++ error,
++ isError,
++ isIdle,
++ isLoading,
++ isSuccess,
++ pendingChainId,
++ switchNetwork,
++ switchNetworkAsync,
++ status,
++ reset,
++} = useSwitchNetwork({
++ chainId: 69,
++ onError(error) {},
++ onMutate(args) {},
++ onSettled(data, error) {},
++ onSuccess(data) {}
++})
+```
+
+### `Connector` `getProvider`
+
+`Connector`s `getProvider` method no longer supports the `create` config parameter. Use the `chainId` config option instead to force create a new provider.
+
+## 0.4.x Breaking changes
+
+
+ Not ready to migrate yet? You can find the `0.3.x` docs
+ [here](https://0.3.x.wagmi.sh).
+
+
+### `createClient`
+
+Passing a function to `createClient` `connectors` has now been deprecated.
+
+If you previously derived an RPC URL from the `chainId` in `connectors`, you will need to migrate to use the [`configureChains` API](/react/providers/configuring-chains).
+
+Before:
+
+```tsx {15-42}
+import { providers } from 'ethers'
+import { Provider, chain, createClient, defaultChains } from 'wagmi'
+import { CoinbaseWalletConnector } from 'wagmi/connectors/coinbaseWallet'
+import { InjectedConnector } from 'wagmi/connectors/injected'
+import { MetaMaskConnector } from 'wagmi/connectors/metaMask'
+import { WalletConnectConnector } from 'wagmi/connectors/walletConnect'
+
+const alchemyId = process.env.ALCHEMY_ID
+
+const chains = defaultChains
+const defaultChain = chain.mainnet
+
+const client = createClient({
+ autoConnect: true,
+ connectors({ chainId }) {
+ const chain = chains.find((x) => x.id === chainId) ?? defaultChain
+ const rpcUrl = chain.rpcUrls.alchemy
+ ? `${chain.rpcUrls.alchemy}/${alchemyId}`
+ : chain.rpcUrls.default
+ return [
+ new MetaMaskConnector({ chains }),
+ new CoinbaseWalletConnector({
+ chains,
+ options: {
+ appName: 'wagmi',
+ chainId: chain.id,
+ jsonRpcUrl: rpcUrl,
+ },
+ }),
+ new WalletConnectConnector({
+ chains,
+ options: {
+ qrcode: true,
+ rpc: { [chain.id]: rpcUrl },
+ },
+ }),
+ new InjectedConnector({
+ chains,
+ options: {
+ name: 'Injected',
+ shimDisconnect: true,
+ },
+ }),
+ ]
+ },
+})
+```
+
+After:
+
+```tsx {20-38}
+import { Provider, chain, createClient, defaultChains } from 'wagmi'
+
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+import { CoinbaseWalletConnector } from 'wagmi/connectors/coinbaseWallet'
+import { InjectedConnector } from 'wagmi/connectors/injected'
+import { MetaMaskConnector } from 'wagmi/connectors/metaMask'
+import { WalletConnectConnector } from 'wagmi/connectors/walletConnect'
+
+const alchemyId = process.env.ALCHEMY_ID
+
+const { chains } = configureChains(defaultChains, [
+ alchemyProvider({ alchemyId }),
+ publicProvider(),
+])
+
+const client = createClient({
+ autoConnect: true,
+ connectors: [
+ new MetaMaskConnector({ chains }),
+ new CoinbaseWalletConnector({
+ chains,
+ options: {
+ appName: 'wagmi',
+ },
+ }),
+ new WalletConnectConnector({
+ chains,
+ options: {
+ qrcode: true,
+ },
+ }),
+ new InjectedConnector({
+ chains,
+ options: {
+ name: 'Injected',
+ shimDisconnect: true,
+ },
+ }),
+ ],
+})
+```
+
+### Duplicate named exports were removed
+
+Duplicate exports with different names and the same functionality were removed to simplify the public API. In addition, confusing exports were renamed to be more descriptive.
+
+- `createWagmiClient` alias was removed. Use `createClient` instead.
+- `useWagmiClient` alias was removed. Use `useClient` instead.
+- `WagmiClient` alias was removed. Use `Client` instead.
+- `createWagmiStorage` alias was removed. Use `createStorage` instead.
+- `Provider` was renamed and `WagmiProvider` alias is now deprecated. Use `WagmiConfig` instead.
+
+## 0.3.x Breaking changes
+
+
+ Not ready to migrate yet? You can find the `0.2.x` docs
+ [here](https://0.2.x.wagmi.sh).
+
+
+### `Provider`
+
+The `Provider` component no longer supports configuration directly as props. You will now need to create a wagmi [`Client`](/react/client) via `createClient`, and then pass the client to `Provider`:
+
+Before:
+
+```tsx
+import { Provider } from 'wagmi'
+
+function App() {
+ return (
+
+
+
+ )
+}
+```
+
+After:
+
+```tsx
+import { Provider, createClient } from 'wagmi'
+
+const client = createClient({
+ autoConnect: true,
+ connectors,
+ provider,
+})
+
+function App() {
+ return (
+
+
+
+ )
+}
+```
+
+### Hooks now return a singular object
+
+All hooks in wagmi now return a single object instead of an array pair.
+
+Before:
+
+```tsx
+const [{ data, loading, error }, disconnect] = useAccount()
+```
+
+After:
+
+```tsx
+const { data, isLoading, error } = useAccount()
+```
+
+### Declarative getters > imperative getters
+
+Getter functions such as `getBalance`, `getBlockNumber`, `read`, etc have been removed in favor of hook parameters / `refetch`. The `refetch` function does not accept arguments/config, so you will need to restructure your components more declaratively.
+
+Before:
+
+```tsx
+import { useBalance } from 'wagmi'
+
+function Example() {
+ const [address, setAddress] = useState('')
+
+ const [{ data }, getBalance] = useBalance({
+ skip: true,
+ })
+
+ return (
+
+ Get balance:
+ setAddress(e.target.value)} value={address} />
+
+
+ Get balance:
+ setValue(e.target.value)} value={value} />
+
+
+ )
+}
+```
+
+### `useAccount`
+
+- Now returns a singular object, instead of an array pair
+- `fetchEns` was removed in favor of keeping `useAccount` as lightweight as possible. Use [`useEnsName`](/react/hooks/useEnsName) and [`useEnsAvatar`](/react/hooks/useEnsAvatar) instead.
+- `disconnect` was removed. Use [`useDisconnect`](/react/hooks/useDisconnect) instead.
+
+Before:
+
+```tsx
+const [{ data, loading, error }, disconnect] = useAccount({ fetchEns: true })
+```
+
+After:
+
+```tsx
+const { data, isLoading, error } = useAccount({ ens: true })
+const { data: ensName } = useEnsName()
+const { data: ensAvatar } = useEnsAvatar()
+const { disconnect } = useDisconnect()
+```
+
+### `useBalance`
+
+- Now returns a singular object, instead of an array pair
+- `skip` is no longer supported. It was repurposed to `enabled`.
+- `getBalance` was removed in favor of [hook parameters / `refetch`](#declarative-getters--imperative-getters).
+ Before:
+
+```tsx
+const [{ data, loading, error }, getBalance] = useBalance({ skip: true })
+```
+
+After:
+
+```tsx
+const { data, isLoading, error, refetch } = useBalance({ enabled: false })
+```
+
+### `useBlockNumber`
+
+- Now returns a singular object, instead of an array pair
+- `skip` is no longer supported. It was repurposed to `enabled`.
+- `getBlockNumber` was removed in favor of [hook parameters / `refetch`](#declarative-getters--imperative-getters).
+ Before:
+
+```tsx
+const [{ data, loading, error }, getBlockNumber] = useBlockNumber({
+ skip: true,
+})
+```
+
+After:
+
+```tsx
+const { data, isLoading, error, refetch } = useBlockNumber({
+ enabled: false,
+})
+```
+
+### `useConnect`
+
+- Now returns a singular object, instead of an array pair
+- `connect` is no longer asynchronous. Use `connectAsync` instead.
+- `data.connected` no longer exists. Use `isConnected` instead.
+- `data.connectors` no longer exists. Use `connectors` instead.
+- Prefer `connector` over `data.connector`
+ Before:
+
+```tsx
+const [{ data, loading, error }, connect] = useConnect()
+```
+
+After:
+
+```tsx
+const { isConnected, connector, connectors, connectAsync } = useConnect()
+```
+
+### `useContractRead`
+
+- Now returns a singular object, instead of an array pair
+- `skip` is no longer supported. It was repurposed to `enabled`.
+- `read` was removed in favor of [hook parameters / `refetch`](#declarative-getters--imperative-getters).
+ Before:
+
+```tsx
+const [{ data, error, loading }, read] = useContractRead(
+ {
+ addressOrName: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ contractInterface: wagmigotchiABI,
+ },
+ 'getHunger',
+ { skip: true },
+)
+```
+
+After:
+
+```tsx
+const { data, error, isLoading, refetch } = useContractRead(
+ {
+ addressOrName: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ contractInterface: wagmigotchiABI,
+ },
+ 'getHunger',
+ { enabled: false },
+)
+```
+
+### `useContractWrite`
+
+- Now returns a singular object, instead of an array pair
+ Before:
+
+```tsx
+const [{ data, error, loading }, write] = useContractWrite(
+ {
+ addressOrName: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ contractInterface: wagmigotchiABI,
+ },
+ 'feed',
+)
+```
+
+After:
+
+```tsx
+const { data, error, isLoading, write } = useContractWrite(
+ {
+ addressOrName: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ contractInterface: wagmigotchiABI,
+ },
+ 'feed',
+)
+```
+
+### `useEnsAvatar`
+
+- Now returns a singular object, instead of an array pair
+- `skip` is no longer supported. It was repurposed to `enabled`.
+- `getEnsAvatar` was removed in favor of [hook parameters / `refetch`](#declarative-getters--imperative-getters).
+ Before:
+
+```tsx
+const [{ data, error, loading }, getEnsAvatar] = useEnsAvatar({
+ addressOrName: 'awkweb.eth',
+ skip: true,
+})
+```
+
+After:
+
+```tsx
+const { data, error, isLoading, refetch } = useEnsAvatar({
+ addressOrName: 'awkweb.eth',
+ enabled: false,
+})
+```
+
+### `useEnsLookup`
+
+- `useEnsLookup` was renamed to `useEnsName`
+- Now returns a singular object, instead of an array pair
+- `skip` is no longer supported. It was repurposed to `enabled`.
+- `lookupAddress` was removed in favor of [hook parameters / `refetch`](#declarative-getters--imperative-getters).
+ Before:
+
+```tsx
+const [{ data, error, loading }, lookupAddress] = useEnsLookup({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ skip: true,
+})
+```
+
+After:
+
+```tsx
+const { data, error, isLoading, refetch } = useEnsName({
+ address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ enabled: false,
+})
+```
+
+### `useEnsResolveName`
+
+- `useEnsResolveName` was renamed to `useEnsAddress`
+- Now returns a singular object, instead of an array pair
+- `skip` is no longer supported. It was repurposed to `enabled`.
+- `resolveName` was removed in favor of [hook parameters / `refetch`](#declarative-getters--imperative-getters).
+ Before:
+
+```tsx
+const [{ data, error, loading }, resolveName] = useEnsResolveName({
+ name: 'meagher.eth',
+ skip: true,
+})
+```
+
+After:
+
+```tsx
+const { data, error, loading, refetch } = useEnsAddress({
+ name: 'meagher.eth',
+ enabled: false,
+})
+```
+
+### `useEnsResolver`
+
+- Now returns a singular object, instead of an array pair
+- `skip` is no longer supported. It was repurposed to `enabled`.
+- `getEnsResolver` was removed in favor of [hook parameters / `refetch`](#declarative-getters--imperative-getters).
+ Before:
+
+```tsx
+const [{ data, error, loading }, getEnsResolver] = useEnsResolver({
+ name: 'awkweb.eth',
+ skip: true,
+})
+```
+
+After:
+
+```tsx
+const { data, error, isLoading, refetch } = useEnsResolver({
+ name: 'awkweb.eth',
+ enabled: false,
+})
+```
+
+### `useFeeData`
+
+- Now returns a singular object, instead of an array pair
+- `skip` is no longer supported. It was repurposed to `enabled`.
+- `getFeeData` was removed in favor of [hook parameters / `refetch`](#declarative-getters--imperative-getters).
+ Before:
+
+```tsx
+const [{ data, error, loading }, getFeeData] = useFeeData({ skip: true })
+```
+
+After:
+
+```tsx
+const { data, error, isLoading, refetch } = useFeeData({ enabled: false })
+```
+
+### `useNetwork`
+
+- Now returns a singular object, instead of an array pair
+- `data.chain` is now `activeChain`
+- `data.chains` is now `chains`
+- `switchNetwork` now has sync (`switchNetwork`) and async (`switchNetworkAsync`) variants.
+ Before:
+
+```tsx
+const [{ data, error, loading }, switchNetwork] = useNetwork()
+```
+
+After:
+
+```tsx
+const { activeChain, chains, data, isLoading, switchNetworkAsync } =
+ useNetwork()
+```
+
+### `useSigner`
+
+- Now returns a singular object, instead of an array pair
+- `skip` is no longer supported.
+- `getSigner` was removed in favor of `refetch`
+ Before:
+
+```tsx
+const [{ data, error, loading }, getSigner] = useSigner()
+```
+
+After:
+
+```tsx
+const { data, error, isLoading, refetch } = useSigner()
+```
+
+### `useSignMessage`
+
+- Now returns a singular object, instead of an array pair
+- `signMessage` now has sync (`signMessage`) and async (`signMessageAsync`) variants.
+ Before:
+
+```tsx
+const [{ data, error, loading }, signMessage] = useSignMessage({
+ message: 'gm wagmi frens',
+})
+```
+
+After:
+
+```tsx
+const { data, error, isLoading, signMessageAsync } = useSignMessage({
+ message: 'gm wagmi frens',
+})
+```
+
+### `useSignTypedData`
+
+- Now returns a singular object, instead of an array pair
+- `signTypedData` now has sync (`signTypedData`) and async (`signTypedDataAsync`) variants.
+ Before:
+
+```tsx
+const [{ data, error, loading }, signTypedData] = useSignTypedData({
+ domain,
+ types,
+ value,
+})
+```
+
+After:
+
+```tsx
+const { data, error, isLoading, signTypedDataAsync } = useSignTypedData({
+ domain,
+ types,
+ value,
+})
+```
+
+### `useToken`
+
+- Now returns a singular object, instead of an array pair
+- `skip` is no longer supported. It was repurposed to `enabled`.
+- `getToken` was removed in favor of [hook parameters / `refetch`](#declarative-getters--imperative-getters).
+ Before:
+
+```tsx
+const [{ data, error, loading }, getToken] = useToken({
+ address: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984',
+ skip: true,
+})
+```
+
+After:
+
+```tsx
+const { data, error, isLoading, refetch } = useToken({
+ address: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984',
+ enabled: false,
+})
+```
+
+### `useTransaction`
+
+- `useTransaction` was renamed to `useSendTransaction`
+- Now returns a singular object, instead of an array pair
+- `sendTransaction` now has sync (`sendTransaction`) and async (`sendTransactionAsync`) variants.
+ Before:
+
+```tsx
+const [{ data, error, loading }, sendTransaction] = useTransaction({
+ request: {
+ to: 'awkweb.eth',
+ value: parseEther('1'), // 1 ETH
+ },
+})
+```
+
+After:
+
+```tsx
+const { data, error, isLoading, sendTransactionAsync } = useSendTransaction({
+ request: {
+ to: 'awkweb.eth',
+ value: parseEther('1'), // 1 ETH
+ },
+})
+```
+
+### `useWaitForTransaction`
+
+- Now returns a singular object, instead of an array pair
+- `skip` is no longer supported. It was repurposed to `enabled`.
+- `wait` was removed in favor of [hook parameters / `refetch`](#declarative-getters--imperative-getters).
+ Before:
+
+```tsx
+const [{ data, error, loading }, wait] = useWaitForTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ skip: true,
+})
+```
+
+After:
+
+```tsx
+const { data, error, isLoading, refetch } = useWaitForTransaction({
+ hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
+ enabled: false,
+})
+```
+
+### `connector.getProvider`
+
+`connector.getProvider` is now asynchronous
+
+Before:
+
+```tsx
+const { connector } = useConnect()
+
+const provider = connector.getProvider()
+```
+
+After:
+
+```tsx
+const { connector } = useConnect()
+
+const provider = await connector.getProvider()
+```
+
+### `WalletLinkConnector`
+
+The WalletLink connector was replaced with the Coinbase Wallet SDK.
+
+Before:
+
+```tsx
+import { WalletLinkConnector } from 'wagmi/connectors/walletLink'
+
+const connector = new WalletLinkConnector({
+ options: {
+ appName: 'Mirror.xyz',
+ jsonRpcUrl: 'https://mainnet.infura.io/v3',
+ },
+})
+```
+
+After:
+
+```tsx
+import { CoinbaseWalletConnector } from 'wagmi/connectors/coinbaseWallet'
+
+const connector = new CoinbaseWalletConnector({
+ options: {
+ appName: 'Mirror.xyz',
+ jsonRpcUrl: 'https://mainnet.infura.io/v3',
+ },
+})
+```
diff --git a/docs/pages/react/module-types.en-US.mdx b/docs/pages/react/module-types.en-US.mdx
new file mode 100644
index 0000000000..281de26a04
--- /dev/null
+++ b/docs/pages/react/module-types.en-US.mdx
@@ -0,0 +1,43 @@
+---
+title: 'Module Types'
+description: 'Information about ESM + CJS modules.'
+---
+
+import { Callout, Tabs, Tab } from 'nextra-theme-docs'
+
+# Module Types
+
+## Pure ESM
+
+In the best interest of moving wagmi forward and aligning with the future of the web, `wagmi` is a [pure ESM module](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) by default for a number of reasons:
+
+- Most modern libraries, frameworks & browsers (ie. Node 12+, Next, Vite, Vitest, etc.) already support pure ESM,
+- To avoid [Dual Package Hazard](https://github.com/GeoffreyBooth/dual-package-hazard),
+- Native ESM support has been out for a while now ([since 2019](https://blog.logrocket.com/es-modules-in-node-js-12-from-experimental-to-release/)).
+
+Some libraries (such as [Remix](https://remix.run/docs/en/v1/pages/gotchas#importing-esm-packages) or [Jest](https://jestjs.io/docs/ecmascript-modules)) may require additional config for ESM support.
+
+## CJS (Escape Hatch)
+
+In the rare scenario you cannot get the pure ESM module to work with your environment, you can retreat to the CJS Escape Hatch module. The CJS module is available via the `cjs` tag on NPM:
+
+{/* prettier-ignore-start */}
+
+
+
+ ```bash
+ npm i wagmi@cjs
+ ```
+
+
+ ```bash
+ pnpm i wagmi@cjs
+ ```
+
+
+ ```bash
+ yarn add wagmi@cjs
+ ```
+
+
+{/* prettier-ignore-end */}
diff --git a/docs/pages/react/prepare-hooks.en-US.mdx b/docs/pages/react/prepare-hooks.en-US.mdx
new file mode 100644
index 0000000000..11e960472f
--- /dev/null
+++ b/docs/pages/react/prepare-hooks.en-US.mdx
@@ -0,0 +1,90 @@
+---
+title: 'Prepare Hooks'
+description: 'What are Prepare Hooks?'
+---
+
+import { ValidationComparisonTable } from '../../components/docs/ValidationComparisonTable'
+
+# Prepare Hooks
+
+In previous versions of wagmi, "transactional" hooks such as `useSendTransaction` and `useContractWrite` performed potentially long-running asynchronous work. These hooks internally invoke the [ethers `signer.sendTransaction` function](https://docs.ethers.io/v5/api/signer/#Signer-sendTransaction) that fetches the gas estimate & block number, and resolves an ENS name (if needed) before the transaction gets sent. On a slow network, these asynchronous tasks can take a while.
+
+Performing asynchronous tasks in an event handler (like a button) or in an event that wasn't initiated by the user (like a page load) is not ideal as it can lead to a variety of connected user-experience (UX) related pitfalls ([listed below](#ux-pitfalls-without-prepare-hooks)).
+
+Prepare Hooks allow you to eagerly perform this asynchronous work beforehand & generate the parameters required for their paired hook (e.g. `usePrepareSendTransaction` prepares a request for `useSendTransaction`).
+
+wagmi currently has the following Prepare Hooks:
+
+- [`usePrepareContractWrite`](/react/prepare-hooks/usePrepareContractWrite)
+- [`usePrepareSendTransaction`](/react/prepare-hooks/usePrepareSendTransaction)
+
+## UX Pitfalls without Prepare Hooks
+
+You may have noticed one of the following pitfalls when using "transactional" hooks without performing the asynchronous work beforehand.
+
+### Slow TTOW (Time To Open Wallet)
+
+Performing long-running async work in between a user interaction (i.e. click handler) and opening the wallet can lead to a slow TTOW (Time To Open Wallet).
+
+Under slow network conditions, it may confuse the end-user as to why the wallet is taking a while to open.
+
+The video below shows the difference between a slow TTOW and a fast TTOW.
+
+
+
+### iOS App Link Constraints
+
+When using WalletConnect on iOS and triggering a wallet interaction (e.g. when sending a transaction or signing a message), you may experience issues where the native app is not opened as expected and a browser navigation occurs instead (as seen in the above video). For some wallets (e.g. [Rainbow](https://rainbow.me/)) this will present a fallback website, while other wallets (e.g. [MetaMask](https://metamask.io/)) will redirect to the App Store.
+
+This issue occurs because app links on iOS will only open the native app when the following rules are followed:
+
+- **The wallet interaction must be triggered by a user-initiated event**, e.g. in a click handler rather than on page load or in an asynchronous callback.
+- **The wallet interaction must be triggered as soon as possible within the event handler.** Any preceding asynchronous work (e.g. estimating gas, resolving an ENS name, fetching a nonce) should have already completed before the event handler fires.
+
+### No upfront validation
+
+When using "transactional" hooks such as `useContractWrite` & `useSendTransaction`, the user will only get feedback on the status of the transaction once they have invoked the click handler.
+
+There are some cases where we can perform upfront validation on a contract or transaction request before the user interacts with the click handler (such as checking if we can still mint on a contract).
+
+See the comparison below for when a user tries to mint a sold out NFT.
+
+
+
+By using a Prepare Hook, we can perform this eager validation before the click handler is invoked.
+
+```tsx {5,25}
+import * as React from 'react'
+import { usePrepareContractWrite, useContractWrite } from 'wagmi'
+
+export function MintNFT() {
+ const { config, error, isError } = usePrepareContractWrite({
+ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
+ abi: [
+ {
+ name: 'mint',
+ type: 'function',
+ stateMutability: 'nonpayable',
+ inputs: [],
+ outputs: [],
+ },
+ ],
+ functionName: 'mint',
+ })
+ const { data, write } = useContractWrite(config)
+
+ return (
+
+
+ {isError &&
Error: {error.message}
}
+
+ )
+}
+```
diff --git a/docs/pages/react/prepare-hooks/_meta.en-US.json b/docs/pages/react/prepare-hooks/_meta.en-US.json
new file mode 100644
index 0000000000..d9ceeb6407
--- /dev/null
+++ b/docs/pages/react/prepare-hooks/_meta.en-US.json
@@ -0,0 +1,4 @@
+{
+ "usePrepareContractWrite": "usePrepareContractWrite",
+ "usePrepareSendTransaction": "usePrepareSendTransaction"
+}
diff --git a/docs/pages/react/prepare-hooks/usePrepareContractWrite.en-US.mdx b/docs/pages/react/prepare-hooks/usePrepareContractWrite.en-US.mdx
new file mode 100644
index 0000000000..40849625ff
--- /dev/null
+++ b/docs/pages/react/prepare-hooks/usePrepareContractWrite.en-US.mdx
@@ -0,0 +1,329 @@
+---
+title: 'usePrepareContractWrite'
+description: 'Hook for preparing a contract write.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# usePrepareContractWrite
+
+Hook for preparing a contract write to be sent via [`useContractWrite`](/react/hooks/useContractWrite).
+
+Eagerly fetches the parameters required for sending a contract write transaction such as the gas estimate.
+
+```tsx
+import { usePrepareContractWrite } from 'wagmi'
+```
+
+## Usage
+
+`usePrepareContractWrite` gives back a "prepared config" to be sent through to `useContractWrite`.
+
+```tsx {4-8}
+import { usePrepareContractWrite, useContractWrite } from 'wagmi'
+
+function App() {
+ const { config, error } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ })
+ const { write } = useContractWrite(config)
+
+ return (
+ <>
+
+ {error && (
+
An error occurred preparing the transaction: {error.message}
+ )}
+ >
+ )
+}
+```
+
+
+ Note: The `write` function will be undefined if the config has not been
+ prepared (still in-flight or errored), or the end-user is not connected to a
+ wallet.
+
+
+## Return value
+
+```tsx
+{
+ data?: PrepareWriteContractResult
+ error?: Error
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ refetch: (options: {
+ throwOnError: boolean
+ cancelRefetch: boolean
+ }) => Promise
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### address (optional)
+
+Contract address. If `address` is not defined, hook will not run.
+
+```tsx {5}
+import { usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ })
+}
+```
+
+### abi (optional)
+
+Contract ABI. If `abi` is not defined, hook will not run.
+
+By defining inline or adding a [const assertion](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) to `abi`, TypeScript will infer the correct types for `functionName` and `args`. See the wagmi [TypeScript docs](/react/typescript) for more information.
+
+```tsx {6}
+import { usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ })
+}
+```
+
+### functionName (optional)
+
+Name of function to call. If `functionName` is not defined, hook will not run.
+
+```tsx {7}
+import { usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ })
+}
+```
+
+### args (optional)
+
+Arguments to pass to function call.
+
+```tsx {16}
+import { usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
+ abi: [
+ {
+ name: 'mint',
+ type: 'function',
+ stateMutability: 'nonpayable',
+ inputs: [{ internalType: 'uint32', name: 'tokenId', type: 'uint32' }],
+ outputs: [],
+ },
+ ],
+ functionName: 'mint',
+ args: [69],
+ })
+}
+```
+
+### chainId (optional)
+
+Chain ID used to validate if the user is connected to the target chain.
+
+```tsx {9}
+import { usePrepareContractWrite } from 'wagmi'
+import { optimism } from 'wagmi/chains'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ chainId: optimism.id,
+ })
+}
+```
+
+### overrides (optional)
+
+Overrides to pass to function call. If the function is payable, you can pass a `value` here.
+
+```tsx {8-11}
+import { usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ overrides: {
+ from: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ value: ethers.utils.parseEther('0.01'),
+ },
+ })
+}
+```
+
+### cacheTime (optional)
+
+Time (in ms) which the prepared config should remain in the cache.
+
+```tsx {8}
+import { usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ cacheTime: 2_000,
+ })
+}
+```
+
+### enabled (optional)
+
+Set this to `false` to disable this query from automatically running. Defaults to `true`.
+
+```tsx {8}
+import { usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ enabled: false,
+ })
+}
+```
+
+### scopeKey (optional)
+
+Scopes the cache to a given context. Hooks that have identical context will share the same cache.
+
+```tsx {7}
+import { usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ scopeKey: 'wagmi'
+ functionName: 'feed',
+ })
+}
+```
+
+### staleTime (optional)
+
+Time (in ms) after prepared config is considered stale. If set to `Infinity` the data will never be considered stale.
+
+```tsx {8}
+import { usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ staleTime: 2_000,
+ })
+}
+```
+
+### suspense (optional)
+
+Set this to `true` to enable suspense mode.
+
+```tsx {8}
+import { usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ suspense: true,
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching is successful.
+
+```tsx {8-10}
+import { usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {8-10}
+import { usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {8-10}
+import { usePrepareContractWrite } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareContractWrite({
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: wagmigotchiABI,
+ functionName: 'feed',
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
diff --git a/docs/pages/react/prepare-hooks/usePrepareSendTransaction.en-US.mdx b/docs/pages/react/prepare-hooks/usePrepareSendTransaction.en-US.mdx
new file mode 100644
index 0000000000..94aef26a8c
--- /dev/null
+++ b/docs/pages/react/prepare-hooks/usePrepareSendTransaction.en-US.mdx
@@ -0,0 +1,261 @@
+---
+title: 'usePrepareSendTransaction'
+description: 'Hook for preparing a transaction to be sent.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# usePrepareSendTransaction
+
+Hook for preparing a transaction to be sent via [`useSendTransaction`](/react/hooks/useSendTransaction).
+
+Eagerly fetches the parameters required for sending a transaction such as the gas estimate and resolving an ENS address (if required).
+
+```tsx
+import { usePrepareSendTransaction } from 'wagmi'
+```
+
+## Usage
+
+`usePrepareSendTransaction` gives back a "prepared config" to be sent through to `useSendTransaction`.
+
+```tsx {4-9}
+import { usePrepareSendTransaction, useSendTransaction } from 'wagmi'
+
+function App() {
+ const { config, error } = usePrepareSendTransaction({
+ request: {
+ to: 'moxey.eth',
+ value: parseEther('1'),
+ },
+ })
+ const { sendTransaction } = useSendTransaction(config)
+
+ return (
+ <>
+
+ {error && (
+
An error occurred preparing the transaction: {error.message}
+ )}
+ >
+ )
+}
+```
+
+
+ Note: The `sendTransaction` function will be undefined if the request has not
+ been prepared (still in-flight or errored), or the end-user is not connected
+ to a wallet.
+
+
+## Return value
+
+```tsx
+{
+ data?: PrepareSendTransactionResult
+ error?: Error
+ isIdle: boolean
+ isLoading: boolean
+ isFetching: boolean
+ isSuccess: boolean
+ isError: boolean
+ isFetched: boolean
+ isFetchedAfterMount: boolean
+ isRefetching: boolean
+ refetch: (options: {
+ throwOnError: boolean
+ cancelRefetch: boolean
+ }) => Promise
+ status: 'idle' | 'error' | 'loading' | 'success'
+}
+```
+
+## Configuration
+
+### request (optional)
+
+Request data to prepare the transaction. See [TransactionRequest](https://docs.ethers.io/v5/api/providers/types/#providers-TransactionRequest) for more info. If `request` and `request.to` are not defined, hook will not run.
+
+```tsx {5-8}
+import { usePrepareSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({
+ request: {
+ to: 'awkweb.eth',
+ value: parseEther('1'), // 1 ETH
+ },
+ })
+}
+```
+
+### chainId (optional)
+
+Chain ID used to validate if the user is connected to the target chain.
+
+```tsx {10}
+import { usePrepareSendTransaction } from 'wagmi'
+import { optimism } from 'wagmi/chains'
+
+function App() {
+ const { config } = usePrepareSendTransaction({
+ request: {
+ to: 'awkweb.eth',
+ value: parseEther('1'), // 1 ETH
+ },
+ chainId: optimism.id,
+ })
+}
+```
+
+### cacheTime (optional)
+
+Time (in ms) which the data should remain in the cache.
+
+```tsx {9}
+import { usePrepareSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({
+ request: {
+ to: 'awkweb.eth',
+ value: parseEther('1'), // 1 ETH
+ },
+ cacheTime: 2_000,
+ })
+}
+```
+
+### enabled (optional)
+
+Set this to `false` to disable this query from automatically running. Defaults to `true`.
+
+```tsx {9}
+import { usePrepareSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({
+ request: {
+ to: 'awkweb.eth',
+ value: parseEther('1'), // 1 ETH
+ },
+ enabled: false,
+ })
+}
+```
+
+### scopeKey (optional)
+
+Scopes the cache to a given context. Hooks that have identical context will share the same cache.
+
+```tsx {9}
+import { usePrepareSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({
+ request: {
+ to: 'awkweb.eth',
+ value: parseEther('1'), // 1 ETH
+ },
+ scopeKey: 'wagmi',
+ })
+}
+```
+
+### staleTime (optional)
+
+Time (in ms) after data is considered stale. If set to `Infinity` the data will never be considered stale.
+
+```tsx {9}
+import { usePrepareSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({
+ request: {
+ to: 'awkweb.eth',
+ value: parseEther('1'), // 1 ETH
+ },
+ staleTime: 2_000,
+ })
+}
+```
+
+### suspense (optional)
+
+Set this to `true` to enable suspense mode.
+
+```tsx {9}
+import { usePrepareSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({
+ request: {
+ to: 'awkweb.eth',
+ value: parseEther('1'), // 1 ETH
+ },
+ suspense: true,
+ })
+}
+```
+
+### onSuccess (optional)
+
+Function to invoke when fetching new data is successful.
+
+```tsx {9-11}
+import { usePrepareSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({
+ request: {
+ to: 'awkweb.eth',
+ value: parseEther('1'), // 1 ETH
+ },
+ onSuccess(data) {
+ console.log('Success', data)
+ },
+ })
+}
+```
+
+### onError (optional)
+
+Function to invoke when an error is thrown while fetching new data.
+
+```tsx {9-11}
+import { usePrepareSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({
+ request: {
+ to: 'awkweb.eth',
+ value: parseEther('1'), // 1 ETH
+ },
+ onError(error) {
+ console.log('Error', error)
+ },
+ })
+}
+```
+
+### onSettled (optional)
+
+Function to invoke when fetching is settled (either successfully fetched, or an error has thrown).
+
+```tsx {9-11}
+import { usePrepareSendTransaction } from 'wagmi'
+
+function App() {
+ const { config } = usePrepareSendTransaction({
+ request: {
+ to: 'awkweb.eth',
+ value: parseEther('1'), // 1 ETH
+ },
+ onSettled(data, error) {
+ console.log('Settled', { data, error })
+ },
+ })
+}
+```
diff --git a/docs/pages/react/providers/_meta.en-US.json b/docs/pages/react/providers/_meta.en-US.json
new file mode 100644
index 0000000000..3655b28efe
--- /dev/null
+++ b/docs/pages/react/providers/_meta.en-US.json
@@ -0,0 +1,7 @@
+{
+ "configuring-chains": "Configuring Chains",
+ "alchemy": "Alchemy",
+ "infura": "Infura",
+ "public": "Public",
+ "jsonRpc": "JSON RPC"
+}
diff --git a/docs/pages/react/providers/_meta.zh-CN.json b/docs/pages/react/providers/_meta.zh-CN.json
new file mode 100644
index 0000000000..68ce93f132
--- /dev/null
+++ b/docs/pages/react/providers/_meta.zh-CN.json
@@ -0,0 +1,7 @@
+{
+ "configuring-chains": "configuring-chains",
+ "alchemy": "Alchemy",
+ "infura": "Infura",
+ "public": "公共 RPC",
+ "jsonRpc": "JSON RPC"
+}
diff --git a/docs/pages/react/providers/alchemy.en-US.mdx b/docs/pages/react/providers/alchemy.en-US.mdx
new file mode 100644
index 0000000000..81243df953
--- /dev/null
+++ b/docs/pages/react/providers/alchemy.en-US.mdx
@@ -0,0 +1,122 @@
+---
+title: 'Alchemy'
+description: 'Official wagmi Provider for Alchemy.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# Alchemy
+
+The `alchemyProvider` configures the chains with Alchemy RPC URLs and also provides an [ethers.js `AlchemyProvider`](https://docs.ethers.io/v5/api/providers/api-providers/#AlchemyProvider).
+
+```ts
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+```
+
+## Usage
+
+```ts
+import { mainnet, polygon } from 'wagmi/chains'
+import { configureChains } from 'wagmi'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [alchemyProvider({ apiKey: 'yourAlchemyApiKey' })],
+)
+```
+
+Note: The above example is using chains from the [`wagmi/chains` entrypoint](/react/chains#wagmichains)
+
+## Return Value
+
+```ts
+{
+ chains: Chain[],
+ provider: AlchemyProvider,
+ webSocketProvider: AlchemyWebSocketProvider
+}
+```
+
+## Configuration
+
+### apiKey
+
+Your Alchemy API key from the [Alchemy Dashboard](https://dashboard.alchemyapi.io/).
+
+```ts {7}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [alchemyProvider({ apiKey: 'yourAlchemyApiKey' })],
+)
+```
+
+### priority (optional)
+
+The priority used for the provider. Lower-value priorities are favoured over higher-value priorities. If multiple providers share the same priority, they are chosen at random.
+
+```ts {11,13}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [
+ alchemyProvider({
+ apiKey: 'yourAlchemyApiKey',
+ priority: 0,
+ }),
+ publicProvider({ priority: 1 }),
+ ],
+)
+```
+
+### stallTimeout (optional)
+
+The timeout in milliseconds after which another provider will be attempted.
+
+```ts {11}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [
+ alchemyProvider({
+ apiKey: 'yourAlchemyApiKey',
+ stallTimeout: 1_000,
+ }),
+ publicProvider(),
+ ],
+)
+```
+
+### weight (optional)
+
+The weight a response from this provider provides. This can be used if a given provider is more trusted.
+
+```ts {11,13}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [
+ alchemyProvider({
+ apiKey: 'yourAlchemyApiKey',
+ weight: 1,
+ }),
+ publicProvider({ weight: 2 }),
+ ],
+)
+```
diff --git a/docs/pages/react/providers/alchemy.zh-CN.mdx b/docs/pages/react/providers/alchemy.zh-CN.mdx
new file mode 100644
index 0000000000..ee353fa779
--- /dev/null
+++ b/docs/pages/react/providers/alchemy.zh-CN.mdx
@@ -0,0 +1,122 @@
+---
+title: 'Alchemy'
+description: 'Alchemy 的官方 wagmi Provider。'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# Alchemy
+
+`alchemyProvider` 用 Alchemy RPC URLs 配置 chain,也提供一个 [ethers.js `AlchemyProvider`](https://docs.ethers.io/v5/api/providers/api-providers/#AlchemyProvider)。
+
+```ts
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+```
+
+## 用法
+
+```ts
+import { mainnet, polygon } from 'wagmi/chains'
+import { configureChains } from 'wagmi'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [alchemyProvider({ apiKey: 'yourAlchemyApiKey' })],
+)
+```
+
+注意:上面的例子是使用来自 [`wagmi/chains`入口](/react/chains#wagmichains) 的 chain。
+
+## 返回值
+
+```ts
+{
+ chains: Chain[],
+ provider: AlchemyProvider,
+ webSocketProvider: AlchemyWebSocketProvider
+}
+```
+
+## 配置项
+
+### apiKey
+
+Alchemy API key,可以从 [Alchemy Dashboard](https://dashboard.alchemyapi.io/) 获取。
+
+```ts {7}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [alchemyProvider({ apiKey: 'yourAlchemyApiKey' })],
+)
+```
+
+### priority (可选)
+
+用于设置 Provider 的优先级,priority 数值小的 Provider 优先级更高。如果多个 Provider 有相同的 priority,则会随机选择它们。
+
+```ts {11,13}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [
+ alchemyProvider({
+ apiKey: 'yourAlchemyApiKey',
+ priority: 0,
+ }),
+ publicProvider({ priority: 1 }),
+ ],
+)
+```
+
+### stallTimeout (可选)
+
+请求超时时间,以毫秒为单位,超时后将尝试另一个 Provider。
+
+```ts {11}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [
+ alchemyProvider({
+ apiKey: 'yourAlchemyApiKey',
+ stallTimeout: 1_000,
+ }),
+ publicProvider(),
+ ],
+)
+```
+
+### weight (可选)
+
+设置来自该 Provider 的响应的权重。如果一个给定的 Provider 更受你信任,就可以使用这个。
+
+```ts {11,13}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [
+ alchemyProvider({
+ apiKey: 'yourAlchemyApiKey',
+ weight: 1,
+ }),
+ publicProvider({ weight: 2 }),
+ ],
+)
+```
diff --git a/docs/pages/react/providers/configuring-chains.en-US.mdx b/docs/pages/react/providers/configuring-chains.en-US.mdx
new file mode 100644
index 0000000000..68806b3911
--- /dev/null
+++ b/docs/pages/react/providers/configuring-chains.en-US.mdx
@@ -0,0 +1,209 @@
+---
+title: 'Configuring Chains'
+description: "The configureChains function allows you to configure your chains with providers such as: Alchemy, Infura, or something else. This means you don't need to worry about defining RPC URLs and chain configuration in your connector or provider. This is managed internally by wagmi."
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# Configuring Chains
+
+The `configureChains` function allows you to configure your chains with providers such as: Alchemy, Infura, or something else. This means you don't need to worry about defining RPC URLs and chain configuration in your [connector](/react/connectors/walletconnect#options) or [provider](/react/client#provider-optional). This is managed internally by wagmi.
+
+```ts
+import { configureChains } from 'wagmi'
+```
+
+## Usage
+
+`configureChains` accepts an array of chains and an array of providers. It returns:
+
+- `chains`: to pass to your connector(s)
+- `provider`: to pass to `createClient`
+- `webSocketProvider`: to optionally pass to `createClient`
+
+```ts
+import { configureChains, createClient } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+import { InjectedConnector } from 'wagmi/connectors/injected'
+
+const { chains, provider } = configureChains(
+ [mainnet, optimism],
+ [alchemyProvider({ apiKey: 'yourAlchemyApiKey' }), publicProvider()],
+)
+
+const wagmiClient = createClient({
+ autoConnect: true,
+ connectors: [new InjectedConnector({ chains })],
+ provider,
+})
+```
+
+Find a list of supported chains in wagmi [here](/core/chains).
+
+### Multiple providers
+
+The `configureChains` function accepts multiple providers. This is useful if not all your chains support a single provider. For example, you may want to use [Alchemy](https://alchemy.com) for Ethereum, and [avax.network](https://avax.network) for Avalanche.
+
+`configureChains` wraps the providers that you provide into an [ethers.js `FallbackProvider`](https://docs.ethers.io/v5/api/providers/other/#FallbackProvider), that comes with support for:
+
+- Falling back to another provider if a provider goes down (e.g. If Infura goes down, we can fall back to Alchemy)
+- Ensuring the responses are legitimate by setting a `targetQuorum`.
+
+```ts
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { infuraProvider } from 'wagmi/providers/infura'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { provider } = configureChains(
+ [mainnet, avalanche],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ infuraProvider({ apiKey: 'yourInfuraApiKey' }),
+ publicProvider(),
+ ],
+)
+```
+
+#### Quorum
+
+If the `targetQuorum` option is set to a value greater than `1`, it will dispatch interactions to multiple providers, in which the responses are verified by comparing them to each other. If the quorum is reached, then the result will be returned to the consumer.
+
+```tsx
+const { provider } = configureChains(
+ [mainnet, avalanche],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ infuraProvider({ apiKey: 'yourInfuraApiKey' }),
+ publicProvider(),
+ ],
+ { targetQuorum: 2 },
+)
+```
+
+By default, for a given chain, it will _attempt_ to set the quorum value, but if the `targetQuorum` value is greater than the number of providers for the chain, it will default to the number of providers.
+
+For instance, in the example provided above `targetQuorum = 2`, however there is only 1 available provider for Avalanche (`jsonRpcProvider`), so the quorum will get set to `1`.
+
+To guarantee a static quorum, you can provide a `minQuorum` as an config option.
+
+## Arguments
+
+### chains
+
+Chains that need to be configured.
+
+```ts {5}
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains } = configureChains([mainnet, optimism], [publicProvider()])
+```
+
+### providers
+
+The providers the app supports.
+
+If a provider does not support a chain, it will fall back onto the next one in the array. If no RPC URLs are found, `configureChains` will throw an error.
+
+```ts {7}
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains } = configureChains(
+ [mainnet, optimism],
+ [alchemyProvider({ apiKey: 'yourAlchemyApiKey' }), publicProvider()],
+)
+```
+
+### Configuration
+
+### pollingInterval (optional)
+
+The frequency in milliseconds at which the provider polls. Defaults to `4000`.
+
+```ts {13}
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains } = configureChains(
+ [mainnet, optimism],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ infuraProvider({ apiKey: 'yourInfuraApiKey' }),
+ publicProvider(),
+ ],
+ { pollingInterval: 10_000, targetQuorum: 3 },
+)
+```
+
+#### targetQuorum (optional)
+
+Sets the target quorum. Defaults to `1`.
+
+```ts {13}
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains } = configureChains(
+ [mainnet, optimism],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ infuraProvider({ apiKey: 'yourInfuraApiKey' }),
+ publicProvider(),
+ ],
+ { targetQuorum: 3 },
+)
+```
+
+#### minQuorum (optional)
+
+Sets the minimum quorum that must be accepted by the providers. Defaults to `1`.
+
+```ts {13}
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains } = configureChains(
+ [mainnet, optimism],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ infuraProvider({ apiKey: 'yourInfuraApiKey' }),
+ publicProvider(),
+ ],
+ { targetQuorum: 3, minQuorum: 2 },
+)
+```
+
+#### stallTimeout (optional)
+
+The timeout in milliseconds after which another provider will be attempted.
+
+```ts {13}
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains } = configureChains(
+ [mainnet, optimism],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ infuraProvider({ apiKey: 'yourInfuraApiKey' }),
+ publicProvider(),
+ ],
+ { stallTimeout: 5000 },
+)
+```
diff --git a/docs/pages/react/providers/configuring-chains.zh-CN.mdx b/docs/pages/react/providers/configuring-chains.zh-CN.mdx
new file mode 100644
index 0000000000..9fd421e121
--- /dev/null
+++ b/docs/pages/react/providers/configuring-chains.zh-CN.mdx
@@ -0,0 +1,209 @@
+---
+title: 'Configuring Chains'
+description: 'configureChains 允许使用特定的 provider 来配置你的 chain,例如:Alchemy、Infura 或其他。这意味着你不需要担心在你的 connector 或 provider 中定义 RPC URLs 和 chain 的配置,这是由 wagmi 内部管理的。'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# Configuring Chains
+
+`configureChains` 方法允许使用特定的 provider 来配置你的 chain ,例如:Alchemy、Infura 或其他。这意味着你不需要担心在你的 [connector](/react/connectors/walletConnect#options) 或 [provider](/react/client#provider-optional) 中定义 RPC URLs 和 chain 的配置,这是由 wagmi 内部管理的。
+
+```ts
+import { configureChains } from 'wagmi'
+```
+
+## 用法
+
+`configureChains` 接受一个 chain 的数组和 provider 的数组,然后返回:
+
+- `chains`: 传递给你的 connector
+- `provider`: 传递给 `createClient`
+- `webSocketProvider`: 也传递给 `createClient`,不过是可选的
+
+```ts
+import { configureChains, createClient } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+import { InjectedConnector } from 'wagmi/connectors/injected'
+
+const { chains, provider } = configureChains(
+ [mainnet, optimism],
+ [alchemyProvider({ apiKey: 'yourAlchemyApiKey' }), publicProvider()],
+)
+
+const wagmiClient = createClient({
+ autoConnect: true,
+ connectors: [new InjectedConnector({ chains })],
+ provider,
+})
+```
+
+可以在[这里](/core/chains)找到 wagmi 里支持的 chain 列表。
+
+### 多个 Provider
+
+`configureChains` 方法可以接受多个 Provider. 如果你的 Provider 不能支持所有的 chain 的时候,这会是很有用的。 例如,你可能想用 [Alchemy](https://alchemy.com) 作为 Etheruem 的 Provider, 用 [avax.network](https://avax.network) 作为 Avalanche 的 Provider
+
+`configureChains` 将你配置的 Provider 配置成一个 [ethers.js `FallbackProvider`](https://docs.ethers.io/v5/api/providers/other/#FallbackProvider), 这样就直接支持了:
+
+- 如果一个 Provider 宕机了,可以自动转跳到另一个(例如,如果 Infura 宕机了,会将请求打到 Alchemy)。
+- 通过设置 targetQuorum 确保响应是合法的。
+
+```ts
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { infuraProvider } from 'wagmi/providers/infura'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { provider } = configureChains(
+ [mainnet, avalanche],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ infuraProvider({ apiKey: 'yourInfuraApiKey' }),
+ publicProvider(),
+ ],
+)
+```
+
+### Quorum
+
+如果 targetQuorum 选项被设置为大于 1 值,它将向多个 Provider 进行请求,通过相互比较验证 Provider 的响应。如果结果相同并且达到设定的数量,那么结果才被返回。
+
+```tsx
+const { provider } = configureChains(
+ [mainnet, avalanche],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ infuraProvider({ apiKey: 'yourInfuraApiKey' }),
+ publicProvider(),
+ ],
+ { targetQuorum: 2 },
+)
+```
+
+默认情况下,对于一个给定的 chain,它将 _尝试_ 设置`targetQuorum`,但如果 `targetQuorum` 值大于该 chain 的 Provider 数量,它将默认为提供者的数量。
+
+例如,在上面提供的例子中,`targetQuorum = 2`,然而 Avalanche 只有一个可用的 Provider (`jsonRpcProvider`),所以`targetQuorum`将被设置为 1。
+
+为了保证一个静态的 quorum,你可以提供一个`minQuorum`作为配置选项。
+
+## 参数
+
+### chains
+
+需要配置的 chain。
+
+```ts {5}
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains } = configureChains([mainnet, optimism], [publicProvider()])
+```
+
+### providers
+
+该 app 支持的 Provider。
+
+如果一个 Provider 不支持一个 chain,它将退回到数组中的下一个。如果没有找到 RPC URL,`configureChains`将抛出一个错误。
+
+```ts {7}
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains } = configureChains(
+ [mainnet, optimism],
+ [alchemyProvider({ apiKey: 'yourAlchemyApiKey' }), publicProvider()],
+)
+```
+
+## 配置项
+
+### pollingInterval (可选)
+
+Provider 轮询的频率,以毫秒为单位,默认为 `4000`。
+
+```ts {13}
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains } = configureChains(
+ [mainnet, optimism],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ infuraProvider({ apiKey: 'yourInfuraApiKey' }),
+ publicProvider(),
+ ],
+ { pollingInterval: 10_000, targetQuorum: 3 },
+)
+```
+
+### targetQuorum (可选)
+
+设置目标 quorum,默认为 1。
+
+```ts {13}
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains } = configureChains(
+ [mainnet, optimism],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ infuraProvider({ apiKey: 'yourInfuraApiKey' }),
+ publicProvider(),
+ ],
+ { targetQuorum: 3 },
+)
+```
+
+### minQuorum (可选)
+
+设置 Provider 必须接受的最小 Quorum,默认为 1。
+
+```ts {13}
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains } = configureChains(
+ [mainnet, optimism],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ infuraProvider({ apiKey: 'yourInfuraApiKey' }),
+ publicProvider(),
+ ],
+ { targetQuorum: 3, minQuorum: 2 },
+)
+```
+
+### stallTimeout (可选)
+
+请求超时时间,以毫秒为单位,超时后将尝试另一个 Provider。
+
+```ts {13}
+import { configureChains } from 'wagmi'
+import { mainnet, optimism } from 'wagmi/chains'
+import { alchemyProvider } from 'wagmi/providers/alchemy'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains } = configureChains(
+ [mainnet, optimism],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ infuraProvider({ apiKey: 'yourInfuraApiKey' }),
+ publicProvider(),
+ ],
+ { stallTimeout: 5000 },
+)
+```
diff --git a/docs/pages/react/providers/infura.en-US.mdx b/docs/pages/react/providers/infura.en-US.mdx
new file mode 100644
index 0000000000..c2711eb7da
--- /dev/null
+++ b/docs/pages/react/providers/infura.en-US.mdx
@@ -0,0 +1,122 @@
+---
+title: 'Infura'
+description: 'Official wagmi Provider for Infura.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# Infura
+
+The `infuraProvider` configures the chains with Infura RPC URLs and also provides an [ethers.js `InfuraProvider`](https://docs.ethers.io/v5/api/providers/api-providers/#InfuraProvider).
+
+```ts
+import { infuraProvider } from 'wagmi/providers/infura'
+```
+
+## Usage
+
+```ts
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { infuraProvider } from 'wagmi/providers/infura'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [infuraProvider({ apiKey: 'yourInfuraApiKey' })],
+)
+```
+
+Note: The above example is using chains from the [`wagmi/chains` entrypoint](/react/chains#wagmichains).
+
+## Return Value
+
+```ts
+{
+ chains: Chain[],
+ provider: InfuraProvider,
+ webSocketProvider: InfuraWebSocketProvider
+}
+```
+
+## Configuration
+
+### apiKey
+
+Your Infura API key from the [Infura Dashboard](https://infura.io/login).
+
+```ts {7}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { infuraProvider } from 'wagmi/providers/infura'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [infuraProvider({ apiKey: 'yourInfuraApiKey' })],
+)
+```
+
+### priority (optional)
+
+The priority used for the provider. Lower-value priorities are favoured over higher-value priorities. If multiple providers share the same priority, they are chosen at random.
+
+```ts {11,13}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { infuraProvider } from 'wagmi/providers/infura'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [
+ infuraProvider({
+ apiKey: 'yourInfuraApiKey',
+ priority: 0,
+ }),
+ publicProvider({ priority: 1 }),
+ ],
+)
+```
+
+### stallTimeout (optional)
+
+The timeout in milliseconds after which another provider will be attempted.
+
+```ts {11}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { infuraProvider } from 'wagmi/providers/infura'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [
+ infuraProvider({
+ apiKey: 'yourInfuraApiKey',
+ stallTimeout: 1_000,
+ }),
+ publicProvider(),
+ ],
+)
+```
+
+### weight (optional)
+
+The weight a response from this provider provides. This can be used if a given provider is more trusted.
+
+```ts {11,13}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { infuraProvider } from 'wagmi/providers/infura'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [
+ infuraProvider({
+ apiKey: 'yourInfuraApiKey',
+ weight: 1,
+ }),
+ publicProvider({ weight: 2 }),
+ ],
+)
+```
diff --git a/docs/pages/react/providers/infura.zh-CN.mdx b/docs/pages/react/providers/infura.zh-CN.mdx
new file mode 100644
index 0000000000..6b42253fc9
--- /dev/null
+++ b/docs/pages/react/providers/infura.zh-CN.mdx
@@ -0,0 +1,122 @@
+---
+title: 'Infura'
+description: 'Infura 的官方 wagmi Provider。'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# Infura
+
+`infuraProvider`用 Infura RPC URLs 来配置 chain ,还提供一个[ethers.js `InfuraProvider`](https://docs.ethers.io/v5/api/providers/api-providers/#InfuraProvider)。
+
+```ts
+import { infuraProvider } from 'wagmi/providers/infura'
+```
+
+## 用法
+
+```ts
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { infuraProvider } from 'wagmi/providers/infura'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [infuraProvider({ apiKey: 'yourInfuraApiKey' })],
+)
+```
+
+注意:上面的例子是使用来自 [`wagmi/chains`入口](/react/chains#wagmichains) 的 chain 。
+
+## 返回值
+
+```ts
+{
+ chains: Chain[],
+ provider: InfuraProvider,
+ webSocketProvider: InfuraWebSocketProvider
+}
+```
+
+## 配置项
+
+### apiKey
+
+Infura API key,可以从 [Infura Dashboard](https://infura.io/login) 获取。
+
+```ts {7}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { infuraProvider } from 'wagmi/providers/infura'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [infuraProvider({ apiKey: 'yourInfuraApiKey' })],
+)
+```
+
+### priority (可选)
+
+用于设置 Provider 的优先级,priority 数值小的 Provider 优先级更高。如果多个 Provider 有相同的 priority,则会随机选择它们。
+
+```ts {11,13}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { infuraProvider } from 'wagmi/providers/infura'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [
+ infuraProvider({
+ apiKey: 'yourInfuraApiKey',
+ priority: 0,
+ }),
+ publicProvider({ priority: 1 }),
+ ],
+)
+```
+
+### stallTimeout (可选)
+
+请求超时时间,以毫秒为单位,超时后将尝试另一个 Provider。
+
+```ts {11}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { infuraProvider } from 'wagmi/providers/infura'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [
+ infuraProvider({
+ apiKey: 'yourInfuraApiKey',
+ stallTimeout: 1_000,
+ }),
+ publicProvider(),
+ ],
+)
+```
+
+### weight (可选)
+
+设置来自该 Provider 的响应的权重。如果一个给定的 Provider 更受你信任,就可以使用这个。
+
+```ts {11,13}
+import { configureChains } from 'wagmi'
+import { mainnet, polygon } from 'wagmi/chains'
+import { infuraProvider } from 'wagmi/providers/infura'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [mainnet, polygon],
+ [
+ infuraProvider({
+ apiKey: 'yourInfuraApiKey',
+ weight: 1,
+ }),
+ publicProvider({ weight: 2 }),
+ ],
+)
+```
diff --git a/docs/pages/react/providers/jsonRpc.en-US.mdx b/docs/pages/react/providers/jsonRpc.en-US.mdx
new file mode 100644
index 0000000000..c3f1bf7158
--- /dev/null
+++ b/docs/pages/react/providers/jsonRpc.en-US.mdx
@@ -0,0 +1,156 @@
+---
+title: 'JSON RPC'
+description: 'Official wagmi Provider for JSON RPC providers.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# JSON RPC
+
+The `jsonRpcProvider` configures the chains with the RPC URLs that you specify and also provides an [ethers.js `StaticJsonRpcProvider`](https://docs.ethers.io/v5/api/providers/jsonrpc-provider/#StaticJsonRpcProvider).
+
+```ts
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+```
+
+## Usage
+
+```ts
+import { chain, configureChains } from 'wagmi'
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ jsonRpcProvider({
+ rpc: (chain) => ({
+ http: `https://${chain.id}.example.com`,
+ }),
+ }),
+ ],
+)
+```
+
+## Return Value
+
+```ts
+{
+ chains: Chain[],
+ provider: JsonRpcProvider,
+ webSocketProvider: WebSocketProvider
+}
+```
+
+## Configuration
+
+### rpc
+
+Accepts a function which provides the `chain` and expects to receive a `http` URL and optionally a `webSocket` URL.
+
+```tsx {8-11}
+import { chain, configureChains } from 'wagmi'
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ jsonRpcProvider({
+ rpc: (chain) => ({
+ http: `https://${chain.id}.example.com`,
+ webSocket: `wss://${chain.id}.example.com`,
+ }),
+ }),
+ ],
+)
+```
+
+### priority (optional)
+
+The priority used for the provider. Lower-value priorities are favoured over higher-value priorities. If multiple providers share the same priority, they are chosen at random.
+
+```ts {8}
+import { chain, configureChains } from 'wagmi'
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ jsonRpcProvider({
+ priority: 0,
+ rpc: (chain) => ({
+ http: `https://${chain.id}.example.com`,
+ webSocket: `wss://${chain.id}.example.com`,
+ }),
+ }),
+ alchemyProvider({ priority: 1 }),
+ ],
+)
+```
+
+### stallTimeout (optional)
+
+The timeout in milliseconds after which another provider will be attempted.
+
+```ts {12}
+import { chain, configureChains } from 'wagmi'
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ jsonRpcProvider({
+ rpc: (chain) => ({
+ http: `https://${chain.id}.example.com`,
+ webSocket: `wss://${chain.id}.example.com`,
+ }),
+ stallTimeout: 1000,
+ }),
+ alchemyProvider({ priority: 1, stallTimeout: 1000 }),
+ ],
+)
+```
+
+### static (optional)
+
+Flag to indicate if the provider should return a [`StaticJsonRpcProvider`](https://docs.ethers.io/v5/api/providers/jsonrpc-provider/#StaticJsonRpcProvider) or [`JsonRpcProvider`](https://docs.ethers.io/v5/api/providers/jsonrpc-provider/#JsonRpcProvider). Defaults to `true`.
+
+```tsx {12}
+import { chain, configureChains } from 'wagmi'
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ jsonRpcProvider({
+ rpc: (chain) => ({
+ http: `https://${chain.id}.example.com`,
+ webSocket: `wss://${chain.id}.example.com`,
+ }),
+ static: false,
+ }),
+ ],
+)
+```
+
+### weight (optional)
+
+The weight a response from this provider provides. This can be used if a given provider is more trusted.
+
+```ts {12}
+import { chain, configureChains } from 'wagmi'
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ jsonRpcProvider({
+ rpc: (chain) => ({
+ http: `https://${chain.id}.example.com`,
+ webSocket: `wss://${chain.id}.example.com`,
+ }),
+ weight: 1,
+ }),
+ alchemyProvider({ priority: 1, weight: 2 }),
+ ],
+)
+```
diff --git a/docs/pages/react/providers/jsonRpc.zh-CN.mdx b/docs/pages/react/providers/jsonRpc.zh-CN.mdx
new file mode 100644
index 0000000000..e3dae82393
--- /dev/null
+++ b/docs/pages/react/providers/jsonRpc.zh-CN.mdx
@@ -0,0 +1,156 @@
+---
+title: 'JSON RPC'
+description: 'JSON RPC providers 的 wagmi 官方Provider。'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# JSON RPC
+
+`jsonRpcProvider`用你指定的 RPC URL 配置 chain ,也提供一个 [ethers.js `StaticJsonRpcProvider`](https://docs.ethers.io/v5/api/providers/jsonrpc-provider/#StaticJsonRpcProvider)。
+
+```ts
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+```
+
+## 用法
+
+```ts
+import { chain, configureChains } from 'wagmi'
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ jsonRpcProvider({
+ rpc: (chain) => ({
+ http: `https://${chain.id}.example.com`,
+ }),
+ }),
+ ],
+)
+```
+
+## 返回值
+
+```ts
+{
+ chains: Chain[],
+ provider: JsonRpcProvider,
+ webSocketProvider: WebSocketProvider
+}
+```
+
+## 配置项
+
+### rpc
+
+需要填入一个函数,这个函数的接受 `chain` 作为输入并返回一个 `http` URL 和 `webSocket` URL,`webSocket` URL 不是必须的。
+
+```tsx {8-11}
+import { chain, configureChains } from 'wagmi'
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ jsonRpcProvider({
+ rpc: (chain) => ({
+ http: `https://${chain.id}.example.com`,
+ webSocket: `wss://${chain.id}.example.com`,
+ }),
+ }),
+ ],
+)
+```
+
+### priority (可选)
+
+用于设置 Provider 的优先级,priority 数值小的 Provider 优先级更高。如果多个 Provider 有相同的 priority,则会随机选择它们。
+
+```ts {8}
+import { chain, configureChains } from 'wagmi'
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ jsonRpcProvider({
+ priority: 0,
+ rpc: (chain) => ({
+ http: `https://${chain.id}.example.com`,
+ webSocket: `wss://${chain.id}.example.com`,
+ }),
+ }),
+ alchemyProvider({ priority: 1 }),
+ ],
+)
+```
+
+### stallTimeout (可选)
+
+请求超时时间,以毫秒为单位,超时后将尝试另一个 Provider。
+
+```ts {12}
+import { chain, configureChains } from 'wagmi'
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ jsonRpcProvider({
+ rpc: (chain) => ({
+ http: `https://${chain.id}.example.com`,
+ webSocket: `wss://${chain.id}.example.com`,
+ }),
+ stallTimeout: 1000,
+ }),
+ alchemyProvider({ priority: 1, stallTimeout: 1000 }),
+ ],
+)
+```
+
+### static (可选)
+
+设置表示 Provider 返回一个[`StaticJsonRpcProvider`](https://docs.ethers.io/v5/api/providers/jsonrpc-provider/#StaticJsonRpcProvider) 还是 [`JsonRpcProvider`](https://docs.ethers.io/v5/api/providers/jsonrpc-provider/#JsonRpcProvider)。默认为`true`,返回 `StaticJsonRpcProvider` 。
+
+```tsx {12}
+import { chain, configureChains } from 'wagmi'
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ jsonRpcProvider({
+ rpc: (chain) => ({
+ http: `https://${chain.id}.example.com`,
+ webSocket: `wss://${chain.id}.example.com`,
+ }),
+ static: false,
+ }),
+ ],
+)
+```
+
+### weight (可选)
+
+设置来自该 Provider 的响应的权重。如果一个给定的 Provider 更受你信任,就可以使用这个。
+
+```ts {12}
+import { chain, configureChains } from 'wagmi'
+import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ jsonRpcProvider({
+ rpc: (chain) => ({
+ http: `https://${chain.id}.example.com`,
+ webSocket: `wss://${chain.id}.example.com`,
+ }),
+ weight: 1,
+ }),
+ alchemyProvider({ priority: 1, weight: 2 }),
+ ],
+)
+```
diff --git a/docs/pages/react/providers/public.en-US.mdx b/docs/pages/react/providers/public.en-US.mdx
new file mode 100644
index 0000000000..92faa9205d
--- /dev/null
+++ b/docs/pages/react/providers/public.en-US.mdx
@@ -0,0 +1,96 @@
+---
+title: 'Public'
+description: 'Official wagmi Provider for public RPC providers.'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# Public
+
+The `publicProvider` configures the chains with a public RPC URL and also provides an [ethers.js `getpublicProvider`](https://docs.ethers.io/v5/api/providers/#providers-getpublicProvider).
+
+```ts
+import { publicProvider } from 'wagmi/providers/public'
+```
+
+## Usage
+
+```ts
+import { chain, configureChains } from 'wagmi'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [publicProvider()],
+)
+```
+
+
+ Only having `publicProvider` in your providers will make the chain use the
+ public RPC URL which could lead to rate-limiting. It is recommended to also
+ include another provider in your list (such as: `alchemyProvider`,
+ `infuraProvider` or `jsonRpcProvider`).
+
+
+## Return Value
+
+```ts
+{
+ chains: Chain[],
+ provider: BaseProvider,
+ webSocketProvider: WebSocketProvider
+}
+```
+
+## Configuration
+
+### priority (optional)
+
+The priority used for the provider. Lower-value priorities are favoured over higher-value priorities. If multiple providers share the same priority, they are chosen at random.
+
+```ts {7-8}
+import { chain, configureChains } from 'wagmi'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey', priority: 0 }),
+ publicProvider({ priority: 1 }),
+ ],
+)
+```
+
+### stallTimeout (optional)
+
+The timeout in milliseconds after which another provider will be attempted.
+
+```ts {8}
+import { chain, configureChains } from 'wagmi'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ publicProvider({ stallTimeout: 1_000 }),
+ ],
+)
+```
+
+### weight (optional)
+
+The weight a response from this provider provides. This can be used if a given provider is more trusted.
+
+```ts {7-8}
+import { chain, configureChains } from 'wagmi'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey', weight: 1 }),
+ publicProvider({ weight: 2 }),
+ ],
+)
+```
diff --git a/docs/pages/react/providers/public.zh-CN.mdx b/docs/pages/react/providers/public.zh-CN.mdx
new file mode 100644
index 0000000000..f19537490b
--- /dev/null
+++ b/docs/pages/react/providers/public.zh-CN.mdx
@@ -0,0 +1,95 @@
+---
+title: 'Public'
+description: '公共 RPC providers 的 wagmi 官方 Provider。'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# Public
+
+`publicProvider`用公共 RPC URL 配置 chain ,同时提供 [ethers.js `getpublicProvider`](https://docs.ethers.io/v5/api/providers/#providers-getpublicProvider)。
+
+```ts
+import { publicProvider } from 'wagmi/providers/public'
+```
+
+## 用法
+
+```ts
+import { chain, configureChains } from 'wagmi'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [publicProvider()],
+)
+```
+
+
+ 在你的提供者中只有 `publicProvider` 会使请求特定的 chain 时只使用公共 RPC
+ URL,这可能会导致速率限制。我们建议在你的列表中还应该包括另一个
+ Provider(例如:`alchemyProvider`,`infuraProvider` 或 `jsonRpcProvider`)。
+
+
+## 返回值
+
+```ts
+{
+ chains: Chain[],
+ provider: BaseProvider,
+ webSocketProvider: WebSocketProvider
+}
+```
+
+## 配置项
+
+### priority (可选)
+
+用于设置 Provider 的优先级,priority 数值小的 Provider 优先级更高。如果多个 Provider 有相同的 priority,则会随机选择它们。
+
+```ts {7-8}
+import { chain, configureChains } from 'wagmi'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey', priority: 0 }),
+ publicProvider({ priority: 1 }),
+ ],
+)
+```
+
+### stallTimeout (可选)
+
+请求超时时间,以毫秒为单位,超时后将尝试另一个 Provider。
+
+```ts {8}
+import { chain, configureChains } from 'wagmi'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey' }),
+ publicProvider({ stallTimeout: 1_000 }),
+ ],
+)
+```
+
+### weight (可选)
+
+设置来自该 Provider 的响应的权重。如果一个给定的 Provider 更受你信任,就可以使用这个。
+
+```ts {7-8}
+import { chain, configureChains } from 'wagmi'
+import { publicProvider } from 'wagmi/providers/public'
+
+const { chains, provider } = configureChains(
+ [chain.mainnet, chain.polygon],
+ [
+ alchemyProvider({ apiKey: 'yourAlchemyApiKey', weight: 1 }),
+ publicProvider({ weight: 2 }),
+ ],
+)
+```
diff --git a/docs/pages/react/typescript.en-US.mdx b/docs/pages/react/typescript.en-US.mdx
new file mode 100644
index 0000000000..fcf8aa3823
--- /dev/null
+++ b/docs/pages/react/typescript.en-US.mdx
@@ -0,0 +1,169 @@
+---
+title: 'TypeScript'
+description: 'Full end-to-end type-safety for contract interactions, EIP-712 typed data, and more!'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# TypeScript
+
+wagmi is designed to be as type-safe as possible! Things to keep in mind:
+
+- Types currently require using TypeScript v4.7.4 or greater.
+- Changes to types in this repository are considered non-breaking and are usually released as patch semver changes (otherwise every type enhancement would be a major version!).
+- It is highly recommended that you lock your `wagmi` package version to a specific patch release 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 that your `tsconfig.json` has [`strict`](https://www.typescriptlang.org/tsconfig#strict) mode set to true:
+
+```json filename="tsconfig.json"
+{
+ "compilerOptions": {
+ "strict": true
+ }
+}
+```
+
+## Type Inference
+
+wagmi can infer types based on [ABI](https://docs.soliditylang.org/en/v0.8.15/abi-spec.html#json) and [EIP-712](https://eips.ethereum.org/EIPS/eip-712) Typed Data definitions (powered by [ABIType](https://github.com/wagmi-dev/abitype)), giving you full end-to-end type-safety from your contracts to your frontend and incredible developer experience (e.g. autocomplete ABI function names and catch misspellings, type ABI function arguments, etc.).
+
+For this to work, you must either add [const assertions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) to specific configuration parameters (more info on those below) or define them inline. For example, `useContractRead`'s `abi` configuration parameter:
+
+```ts
+const { data } = useContractRead({
+ abi: […], // <--- defined inline
+})
+```
+
+```ts
+const abi = […] as const // <--- const assertion
+const { data } = useContractRead({ abi })
+```
+
+If type inference isn't working, it's likely you forgot to add a `const` assertion or define the configuration parameter inline.
+
+
+ Unfortunately [TypeScript doesn't support importing JSON as
+ const](https://github.com/microsoft/TypeScript/issues/32063). Check out
+ [`@wagmi/cli`](/cli) to help with this! It can automatically fetch ABIs from
+ Etherscan, resolve ABIs from your Foundry/Hardhat projects, generate React
+ Hooks, and much more.
+
+
+### Contract ABIs
+
+The following hooks support type inference when you add a const assertion to `abi`:
+
+- [useContract](/react/hooks/useContract)
+- [useContractEvent](/react/hooks/useContractEvent)
+- [useContractRead](/react/hooks/useContractRead)
+- [useContractReads](/react/hooks/useContractReads)
+- [useContractWrite](/react/hooks/useContractWrite)
+- [usePrepareContractWrite](/react/prepare-hooks/usePrepareContractWrite)
+- [useContractInfiniteReads](/react/hooks/useContractInfiniteReads) (must also add const assertion to `args` since `abi` is in the return type)
+
+For example, `useContractRead`:
+
+```ts
+import { useContractRead } from 'wagmi'
+
+const { data } = useContractRead({
+ // ^? const data: BigNumber | undefined
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: [
+ {
+ name: 'getUncleanliness',
+ inputs: [],
+ outputs: [{ name: '', type: 'uint256' }],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ name: 'love',
+ inputs: [{ name: '', type: 'address' }],
+ outputs: [{ name: '', type: 'uint256' }],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ name: 'play',
+ inputs: [],
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ ],
+
+ functionName: 'love',
+ // ^? (property) functionName?: "getUncleanliness" | "love" | undefined
+ // Notice how "play" is not included since it is not a "read" function
+
+ args: ['0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c'],
+ // ^? (property) args?: readonly [`0x${string}`] | undefined
+
+ onSuccess(data) {
+ // ^? (parameter) data: BigNumber
+ },
+ // Type inference flows to other configuration parameters as well:
+ // - select?: ((data: BigNumber) => BigNumber) | undefined
+ // - onSettled?: ((data: BigNumber | undefined, error: Error | null) => void) | undefined
+ // - …
+})
+```
+
+### EIP-712 Typed Data
+
+Adding a const assertion to `types` adds type inference to `useSignTypedData`'s `value` configuration parameter:
+
+```ts
+import { useSignTypedData } from 'wagmi'
+
+const result = useSignTypedData({
+ domain: {
+ name: 'Ether Mail',
+ version: '1',
+ chainId: 1,
+ verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
+ },
+
+ types: {
+ Person: [
+ { name: 'name', type: 'string' },
+ { name: 'wallet', type: 'address' },
+ ],
+ Mail: [
+ { name: 'from', type: 'Person' },
+ { name: 'to', type: 'Person' },
+ { name: 'contents', type: 'string' },
+ ],
+ },
+
+ value: {
+ // ^? (parameter) value?: { name: string; wallet: `0x${string}` } | {
+ // from: {
+ // name: string;
+ // wallet: `0x${string}`;
+ // };
+ // to: {
+ // name: string;
+ // wallet: `0x${string}`;
+ // };
+ // contents: string;
+ // } | undefined
+ from: {
+ name: 'Cow',
+ wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
+ },
+ to: {
+ name: 'Bob',
+ wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
+ },
+ contents: 'Hello, Bob!',
+ },
+})
+```
+
+## Configuring 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/wagmi-dev/abitype). See ABIType's [documentation](https://github.com/wagmi-dev/abitype#configuration) for more info on how to configure types.
diff --git a/docs/pages/react/typescript.zh-CN.mdx b/docs/pages/react/typescript.zh-CN.mdx
new file mode 100644
index 0000000000..136a3947b3
--- /dev/null
+++ b/docs/pages/react/typescript.zh-CN.mdx
@@ -0,0 +1,168 @@
+---
+title: 'TypeScript'
+description: '为合约交互、EIP-712类型化数据等提供完全的端到端类型安全!'
+---
+
+import { Callout } from 'nextra-theme-docs'
+
+# TypeScript
+
+wagmi 被设计成尽可能的类型安全! 需要记住的事情:
+
+- 目前需要使用 TypeScript v4.7.4 或更高版本。
+- 在这个资源库中对类型的修改被认为是非破坏性的,通常作为补丁 semver 的修改发布(否则每一个类型的增强都将是一个主要版本!)。
+- 强烈建议你将 `wagmi` 包的版本锁定在特定的补丁版本上,以便在任何版本上都可以修复或升级类型。
+- wagmi 的非类型相关公共 API 仍然非常严格地遵循 semver 规范。
+
+为确保一切正常,请确保将 `tsconfig.json` 中的 [`strict`](https://www.typescriptlang.org/tsconfig#strict) 设置为 true:
+
+```json filename="tsconfig.json"
+{
+ "compilerOptions": {
+ "strict": true
+ }
+}
+```
+
+## 类型推断
+
+wagmi 可以根据 [ABI](https://docs.soliditylang.org/en/v0.8.15/abi-spec.html#json) 和 [EIP-712](https://eips.ethereum.org/EIPS/eip-712) 类型数据定义(由 [ABIType](https://github.com/wagmi-dev/abitype) 提供)来推断类型,为你提供从合约到前端完整的端到端类型安全和难以置信的开发者体验(例如,自动完成 ABI 函数名称并捕捉拼写错误、推断 ABI 函数参数类型等等)。
+
+为此,你必须将 [const 断言](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) 添加到特定的配置参数中(关于这些参数的更多信息见下文),或者在行内定义它们。例如,`useContractRead` 的 `abi` 配置参数:
+
+```ts
+const { data } = useContractRead({
+ abi: […], // <--- 内联定义
+})
+```
+
+```ts
+const abi = […] as const // <--- const 断言
+const { data } = useContractRead({ abi })
+```
+
+如果类型推断不生效,很可能是你忘记了添加 `const` 断言或内联定义配置参数。
+
+
+ 不幸的是 [TypeScript 不支持将 JSON 导入为
+ const](https://github.com/microsoft/TypeScript/issues/32063)。请查看
+ [ `@wagmi/cli`](/cli) 来帮助解决这个问题! 它可以自动从 Etherscan 中获取 ABI,从你的 Foundry/Hardhat 项目中解析 ABI、生成 React
+ Hooks 等等。
+
+
+### 合约 ABIs
+
+当你向 `abi` 添加 const 断言时,以下 hooks 支持类型推断。
+
+- [useContract](/react/hooks/useContract)
+- [useContractEvent](/react/hooks/useContractEvent)
+- [useContractRead](/react/hooks/useContractRead)
+- [useContractReads](/react/hooks/useContractReads)
+- [useContractWrite](/react/hooks/useContractWrite)
+- [usePrepareContractWrite](/react/prepare-hooks/usePrepareContractWrite)
+- [useContractInfiniteReads](/react/hooks/useContractInfiniteReads) (还必须给 `args` 添加 const 断言,因为 `abi` 是在返回类型中)
+
+例如 `useContractRead`:
+
+```ts
+import { useContractRead } from 'wagmi'
+
+const { data } = useContractRead({
+ // ^? const data: BigNumber | undefined
+ address: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
+ abi: [
+ {
+ name: 'getUncleanliness',
+ inputs: [],
+ outputs: [{ name: '', type: 'uint256' }],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ name: 'love',
+ inputs: [{ name: '', type: 'address' }],
+ outputs: [{ name: '', type: 'uint256' }],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ name: 'play',
+ inputs: [],
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ ],
+
+ functionName: 'love',
+ // ^? (property) functionName?: "getUncleanliness" | "love" | undefined
+ // 需要注意 "play" 没有被包括在内,因为它不是一个 "read" 的函数
+
+ args: ['0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c'],
+ // ^? (property) args?: readonly [`0x${string}`] | undefined
+
+ onSuccess(data) {
+ // ^? (parameter) data: BigNumber
+ },
+ // 类型推断也将流向其他配置参数:
+ // - select?: ((data: BigNumber) => BigNumber) | undefined
+ // - onSettled?: ((data: BigNumber | undefined, error: Error | null) => void) | undefined
+ // - …
+})
+```
+
+### EIP-712 类型数据
+
+在 `types` 中添加一个 const 断言,为 `useSignTypedData` 的 `value` 配置参数添加类型推断。
+
+```ts
+import { useSignTypedData } from 'wagmi'
+
+const result = useSignTypedData({
+ domain: {
+ name: 'Ether Mail',
+ version: '1',
+ chainId: 1,
+ verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
+ },
+
+ types: {
+ Person: [
+ { name: 'name', type: 'string' },
+ { name: 'wallet', type: 'address' },
+ ],
+ Mail: [
+ { name: 'from', type: 'Person' },
+ { name: 'to', type: 'Person' },
+ { name: 'contents', type: 'string' },
+ ],
+ },
+
+ value: {
+ // ^? (parameter) value?: { name: string; wallet: `0x${string}` } | {
+ // from: {
+ // name: string;
+ // wallet: `0x${string}`;
+ // };
+ // to: {
+ // name: string;
+ // wallet: `0x${string}`;
+ // };
+ // contents: string;
+ // } | undefined
+ from: {
+ name: 'Cow',
+ wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
+ },
+ to: {
+ name: 'Bob',
+ wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
+ },
+ contents: 'Hello, Bob!',
+ },
+})
+```
+
+## 配置内部类型
+
+对于高级使用情况,你可能想配置 wagmi 的内部类型。大多数与 ABI 和 EIP-712 类型数据相关的 wagmi 类型是由 [ABIType](https://github.com/wagmi-dev/abitype) 提供的。关于如何配置类型的更多信息,请参阅 ABIType 的 [文档](https://github.com/wagmi-dev/abitype#configuration)。
diff --git a/docs/postcss.config.js b/docs/postcss.config.js
new file mode 100644
index 0000000000..33ad091d26
--- /dev/null
+++ b/docs/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/docs/public/assets/cli-generate.gif b/docs/public/assets/cli-generate.gif
new file mode 100644
index 0000000000..9e5071dd44
Binary files /dev/null and b/docs/public/assets/cli-generate.gif differ
diff --git a/docs/public/assets/cli-generate.mp4 b/docs/public/assets/cli-generate.mp4
new file mode 100644
index 0000000000..22fde5950a
Binary files /dev/null and b/docs/public/assets/cli-generate.mp4 differ
diff --git a/docs/public/assets/cli-init.gif b/docs/public/assets/cli-init.gif
new file mode 100644
index 0000000000..193acf5155
Binary files /dev/null and b/docs/public/assets/cli-init.gif differ
diff --git a/docs/public/assets/cli-init.mp4 b/docs/public/assets/cli-init.mp4
new file mode 100644
index 0000000000..cc82c1ec82
Binary files /dev/null and b/docs/public/assets/cli-init.mp4 differ
diff --git a/docs/public/assets/eager-mint.mp4 b/docs/public/assets/eager-mint.mp4
new file mode 100644
index 0000000000..2417076165
Binary files /dev/null and b/docs/public/assets/eager-mint.mp4 differ
diff --git a/docs/public/assets/lazy-mint.mp4 b/docs/public/assets/lazy-mint.mp4
new file mode 100644
index 0000000000..27f09c2f8e
Binary files /dev/null and b/docs/public/assets/lazy-mint.mp4 differ
diff --git a/docs/public/assets/ttow-comparison.mp4 b/docs/public/assets/ttow-comparison.mp4
new file mode 100644
index 0000000000..834e0f17d0
Binary files /dev/null and b/docs/public/assets/ttow-comparison.mp4 differ
diff --git a/docs/public/favicons/apple-touch-icon.png b/docs/public/favicons/apple-touch-icon.png
new file mode 100644
index 0000000000..e8e75e8c54
Binary files /dev/null and b/docs/public/favicons/apple-touch-icon.png differ
diff --git a/docs/public/favicons/dark.png b/docs/public/favicons/dark.png
new file mode 100644
index 0000000000..b47f4bc9ad
Binary files /dev/null and b/docs/public/favicons/dark.png differ
diff --git a/site/public/favicon.svg b/docs/public/favicons/favicon.svg
similarity index 87%
rename from site/public/favicon.svg
rename to docs/public/favicons/favicon.svg
index 48c440d660..cd8ae06047 100644
--- a/site/public/favicon.svg
+++ b/docs/public/favicons/favicon.svg
@@ -1,4 +1,4 @@
-
diff --git a/docs/public/favicons/light.png b/docs/public/favicons/light.png
new file mode 100644
index 0000000000..99df341c45
Binary files /dev/null and b/docs/public/favicons/light.png differ
diff --git a/docs/public/og.png b/docs/public/og.png
new file mode 100644
index 0000000000..c95262c44b
Binary files /dev/null and b/docs/public/og.png differ
diff --git a/docs/public/paradigm-wagmi.png b/docs/public/paradigm-wagmi.png
new file mode 100644
index 0000000000..8b05cebe12
Binary files /dev/null and b/docs/public/paradigm-wagmi.png differ
diff --git a/docs/style.css b/docs/style.css
new file mode 100644
index 0000000000..acdf793669
--- /dev/null
+++ b/docs/style.css
@@ -0,0 +1,53 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+body {
+ font-feature-settings: 'rlig' 1, 'calt' 1;
+}
+
+[data-reach-skip-link] {
+ @apply sr-only;
+}
+
+[data-reach-skip-link]:focus {
+ @apply not-sr-only fixed ml-6 top-0 bg-white text-lg px-6 py-2 mt-2 outline-none focus:ring z-50;
+}
+
+.dark .invert-on-dark {
+ filter: invert(1) brightness(1.8);
+}
+
+.nextra-callout a,
+ul a,
+ol a {
+ @apply text-current;
+}
+
+@media (min-width: 768px) {
+ .nextra-sidebar-container {
+ width: 18rem;
+ }
+}
+
+sup a {
+ @apply text-current;
+ text-decoration: none;
+}
+
+code.text-\[\.9em\] {
+ font-size: 14px;
+}
+
+.footnotes {
+ @apply text-sm;
+}
+
+.install [role='tablist'] {
+ justify-content: center;
+}
+
+table {
+ @apply table-auto w-full;
+ display: table !important;
+}
\ No newline at end of file
diff --git a/docs/tailwind.config.js b/docs/tailwind.config.js
new file mode 100644
index 0000000000..32f2591be6
--- /dev/null
+++ b/docs/tailwind.config.js
@@ -0,0 +1,8 @@
+module.exports = {
+ darkMode: 'class',
+ content: [
+ './pages/**/*.{js,ts,jsx,tsx,md,mdx}',
+ './components/**/*.{js,ts,jsx,tsx,md,mdx}',
+ './theme.config.tsx',
+ ],
+}
diff --git a/docs/theme.config.tsx b/docs/theme.config.tsx
new file mode 100644
index 0000000000..f1b152164f
--- /dev/null
+++ b/docs/theme.config.tsx
@@ -0,0 +1,219 @@
+import { useRouter } from 'next/router'
+import type { DocsThemeConfig } from 'nextra-theme-docs'
+import { useConfig } from 'nextra-theme-docs'
+
+const github = 'https://github.com/wagmi-dev/wagmi'
+
+const translations = {
+ 'en-US': {
+ editLink: 'Edit this page on GitHub →',
+ feedbackLink: 'Question? Give us feedback →',
+ gitcoinBanner:
+ 'wagmi is in the Gitcoin Grants Beta Round. Click here to support development. Thank you 🙏',
+ poweredBy: 'Powered by',
+ tagline: {
+ core: 'VanillaJS for Ethereum',
+ cli: 'CLI tools for Ethereum',
+ react: 'React Hooks for Ethereum',
+ },
+ },
+ 'zh-CN': {
+ editLink: '在 GitHub 上编辑此页面 →',
+ feedbackLink: '有疑问? 点击给我们反馈 →',
+ gitcoinBanner:
+ 'wagmi is in the Gitcoin Grants Beta Round. Click here to support development. Thank you 🙏',
+ poweredBy: 'Powered by',
+ tagline: {
+ core: 'VanillaJS for Ethereum',
+ cli: 'CLI tools for Ethereum',
+ react: 'React Hooks for Ethereum',
+ },
+ },
+} as const
+type Language = keyof typeof translations
+
+function useLocale() {
+ return useRouter().locale as Language
+}
+
+const config: DocsThemeConfig = {
+ banner: {
+ key: 'gitcoin-2',
+ text() {
+ return (
+
+ {/* eslint-disable-next-line react-hooks/rules-of-hooks */}
+ {translations[useLocale()].gitcoinBanner}
+
+ )
+ },
+ },
+ chat: {
+ icon: null,
+ },
+ darkMode: true,
+ docsRepositoryBase: `${github}/tree/main/docs`,
+ editLink: {
+ text() {
+ // eslint-disable-next-line react-hooks/rules-of-hooks
+ return <>{translations[useLocale()].editLink}>
+ },
+ },
+ feedback: {
+ content() {
+ // eslint-disable-next-line react-hooks/rules-of-hooks
+ return <>{translations[useLocale()].feedbackLink}>
+ },
+ labels: 'feedback',
+ },
+ footer: {
+ text() {
+ return (
+