Skip to content
Docs
Migration Guide

Migration Guide

If you are coming from an earlier version of wagmi, you will need to make sure to update the following hooks & API's listed below.

0.5.x Breaking changes

💡

Not ready to migrate yet? You can find the 0.4.x docs here.

WagmiConfig

The client prop is now required on WagmiConfig.

```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 (
    <WagmiConfig
+     client={client}
    >
      <YourRoutes />
    </WagmiConfig>
  )
}

createClient

provider is now required

The provider config option is now required on createClient. It is recommended to pass the provider given from configureChains.

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:

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.

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.

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

{
- 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:

{
+ 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.

{
- 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.

{
- 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.

const account = useAccount({
  onConnect({ address, connector, isReconnected }) {
    console.log('Connected')
  },
})

onDisconnect has been added

The onDisconnect callback is invoked when the account disconnected.

const account = useAccount({
  onDisconnect() {
    console.log('Disconnected')
  },
})

suspense has been removed

The useAccount hook is a synchronous hook – so suspense never worked.

const account = useAccount({
-  suspense: true,
})

onError has been removed

The useAccount hook never had any error definitions – so onError was never invoked.

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.

const account = useAccount({
- onSettled(data) {
-   console.log('Settled', data)
- },
})

If you used onSettled, you can move the code beneath the useAccount hook:

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.

const account = useAccount({
- onSuccess(data) {
-   console.log('Success', data)
- },
})

If you used onSuccess, you can move the code beneath the useAccount hook:

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.

-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.

-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.

import { useConnect } from 'wagmi'

function App() {
  const { connect, connectors } = useConnect()

  return (
    <button
-     onClick={() => connect(connectors[0])}
+     onClick={() => connect({ connector: connectors[0] })}
    >
      Connect
    </button>
  )
}

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:

useContractRead(
  {
    addressOrName: wagmigotchiContractAddress,
    contractInterface: wagmigotchiABI,
  },
  'love',
  { args: '0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c' },
)

After:

useContractRead({
  addressOrName: wagmigotchiContractAddress,
  contractInterface: wagmigotchiABI,
  functionName: 'love',
  args: '0x27a69ffba1e939ddcfecc8c7e0f967b872bac65c',
})

useContractWrite

The useContractWrite hook parameters have been consolidated into a singular config parameter.

Before:

useContractWrite(
  {
    addressOrName: mlootContractAddress,
    contractInterface: mlootABI,
  },
  'claim',
)

After:

useContractWrite({
  addressOrName: mlootContractAddress,
  contractInterface: mlootABI,
  functionName: 'claim',
})

useContractEvent

The useContractEvent hook parameters have been consolidated into a singular config parameter.

Before:

useContractEvent(
  {
    addressOrName: uniContractAddress,
    contractInterface: erc20ABI,
  },
  'Transfer',
  listener,
),

After:

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.

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

Connectors 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.

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.

Before:

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:

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.

Provider

The Provider component no longer supports configuration directly as props. You will now need to create a wagmi Client via createClient, and then pass the client to Provider:

Before:

import { Provider } from 'wagmi'

function App() {
  return (
    <Provider autoConnect connectors={connectors} provider={provider}>
      <YourRoutes />
    </Provider>
  )
}

After:

import { Provider, createClient } from 'wagmi'

const client = createClient({
  autoConnect: true,
  connectors,
  provider,
})

function App() {
  return (
    <Provider client={client}>
      <YourRoutes />
    </Provider>
  )
}

Hooks now return a singular object

All hooks in wagmi now return a single object instead of an array pair.

Before:

const [{ data, loading, error }, disconnect] = useAccount()

After:

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:

import { useBalance } from 'wagmi'

function Example() {
  const [address, setAddress] = useState<string>('')

  const [{ data }, getBalance] = useBalance({
    skip: true,
  })

  return (
    <div>
      Get balance:
      <input onChange={(e) => setAddress(e.target.value)} value={address} />
      <button onClick={() => getBalance({ addressOrName: address })}>
        fetch
      </button>
    </div>
  )
}

After:

import { useContractRead } from 'wagmi'

function Example() {
  const [address, setAddress] = useState<string>('')

  const { data, refetch } = useBalance({
    addressOrName: address,
    enabled: Boolean(address),
  })

  const [value, setValue] = useState<string>('')

  return (
    <div>
      Get balance:
      <input onChange={(e) => setValue(e.target.value)} value={value} />
      <button
        onClick={() => (address === value ? refetch() : setAddress(value))}
      >
        fetch
      </button>
    </div>
  )
}

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 and useEnsAvatar instead.
  • disconnect was removed. Use useDisconnect instead.

Before:

const [{ data, loading, error }, disconnect] = useAccount({ fetchEns: true })

After:

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. Before:
const [{ data, loading, error }, getBalance] = useBalance({ skip: true })

After:

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. Before:
const [{ data, loading, error }, getBlockNumber] = useBlockNumber({
  skip: true,
})

After:

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:
const [{ data, loading, error }, connect] = useConnect()

After:

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. Before:
const [{ data, error, loading }, read] = useContractRead(
  {
    addressOrName: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
    contractInterface: wagmigotchiABI,
  },
  'getHunger',
  { skip: true },
)

After:

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:
const [{ data, error, loading }, write] = useContractWrite(
  {
    addressOrName: '0xecb504d39723b0be0e3a9aa33d646642d1051ee1',
    contractInterface: wagmigotchiABI,
  },
  'feed',
)

After:

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. Before:
const [{ data, error, loading }, getEnsAvatar] = useEnsAvatar({
  addressOrName: 'awkweb.eth',
  skip: true,
})

After:

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. Before:
const [{ data, error, loading }, lookupAddress] = useEnsLookup({
  address: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
  skip: true,
})

After:

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. Before:
const [{ data, error, loading }, resolveName] = useEnsResolveName({
  name: 'meagher.eth',
  skip: true,
})

After:

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. Before:
const [{ data, error, loading }, getEnsResolver] = useEnsResolver({
  name: 'awkweb.eth',
  skip: true,
})

After:

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. Before:
const [{ data, error, loading }, getFeeData] = useFeeData({ skip: true })

After:

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:
const [{ data, error, loading }, switchNetwork] = useNetwork()

After:

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:
const [{ data, error, loading }, getSigner] = useSigner()

After:

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:
const [{ data, error, loading }, signMessage] = useSignMessage({
  message: 'gm wagmi frens',
})

After:

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:
const [{ data, error, loading }, signTypedData] = useSignTypedData({
  domain,
  types,
  value,
})

After:

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. Before:
const [{ data, error, loading }, getToken] = useToken({
  address: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984',
  skip: true,
})

After:

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:
const [{ data, error, loading }, sendTransaction] = useTransaction({
  request: {
    to: 'awkweb.eth',
    value: BigNumber.from('1000000000000000000'), // 1 ETH
  },
})

After:

const { data, error, isLoading, sendTransactionAsync } = useSendTransaction({
  request: {
    to: 'awkweb.eth',
    value: BigNumber.from('1000000000000000000'), // 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. Before:
const [{ data, error, loading }, wait] = useWaitForTransaction({
  hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
  skip: true,
})

After:

const { data, error, isLoading, refetch } = useWaitForTransaction({
  hash: '0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060',
  enabled: false,
})

connector.getProvider

connector.getProvider is now asynchronous

Before:

const { connector } = useConnect()

const provider = connector.getProvider()

After:

const { connector } = useConnect()

const provider = await connector.getProvider()

WalletLinkConnector

The WalletLink connector was replaced with the Coinbase Wallet SDK.

Before:

import { WalletLinkConnector } from 'wagmi/connectors/walletLink'

const connector = new WalletLinkConnector({
  options: {
    appName: 'Mirror.xyz',
    jsonRpcUrl: 'https://mainnet.infura.io/v3',
  },
})

After:

import { CoinbaseWalletConnector } from 'wagmi/connectors/coinbaseWallet'

const connector = new CoinbaseWalletConnector({
  options: {
    appName: 'Mirror.xyz',
    jsonRpcUrl: 'https://mainnet.infura.io/v3',
  },
})
Last updated on July 4, 2022