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
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.
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. UsecreateClient
instead.useWagmiClient
alias was removed. UseuseClient
instead.WagmiClient
alias was removed. UseClient
instead.createWagmiStorage
alias was removed. UsecreateStorage
instead.Provider
was renamed andWagmiProvider
alias is now deprecated. UseWagmiConfig
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 keepinguseAccount
as lightweight as possible. UseuseEnsName
anduseEnsAvatar
instead.disconnect
was removed. UseuseDisconnect
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 toenabled
.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 toenabled
.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. UseconnectAsync
instead.data.connected
no longer exists. UseisConnected
instead.data.connectors
no longer exists. Useconnectors
instead.- Prefer
connector
overdata.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 toenabled
.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 toenabled
.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 touseEnsName
- Now returns a singular object, instead of an array pair
skip
is no longer supported. It was repurposed toenabled
.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 touseEnsAddress
- Now returns a singular object, instead of an array pair
skip
is no longer supported. It was repurposed toenabled
.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 toenabled
.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 toenabled
.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 nowactiveChain
data.chains
is nowchains
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 ofrefetch
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 toenabled
.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 touseSendTransaction
- 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 toenabled
.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',
},
})