Migrating to Wallet Connect v2
Wallet Connect v2 introduces a number of breaking changes and improvements to version 1.
On June 28th version 1 of Wallet Connect will no longer be supported and the v1.0 protocol will be shut down. This means that any dApp or wallet hoping to continue offering its
users WalletConnect features will need to migrate to version 2. This guide is to help developers on Celo migrate their dApps to version 2.
In this guide we will cover migrating dApps that use either react-celo or RainbowKit to their newer WalletConnect 2 supporting versions.
The first thing anyone adding WalletConnect 2 support will need is a WalletConnect project ID. A WalletConnect project ID can be quickly made for free by anyone with a WalletConnect account.
If you don’t have an account already it’s easy and free to sign up.
- First either sign in or creat an account here.
- Once signed in and on the dashboard, click the New Project button at the top right.
- Enter in your dApp name and click Create.
- You will then be taken to a page displaying the
Project ID
to use for your dApp. - Keep this ID handy for the next steps.
Migrating with react-celo
react-celo version 5 upgraded the internal WalletConnect dependencies to v2. Luckily you will only need to make a single change when upgrading to version 5 from version 4.
When using the CeloProvider
imported from react-celo at the root of your application you will need to use the new project ID you’ve created as part of the dapp
prop.
See the example below.
<CeloProvider
dapp={{
name: 'WCv2 Demo App',
description: 'An example for version 5 of react-celo',
url: 'https://myappexample.com',
icon: 'https://myappexample.ico',
// The above fields are the same as before, and the next field is our new required project ID
walletConnectProjectId: 'the_id_for_your_WC_project',
}}
>
<YourApp />
</CeloProvider>
That’s it for react-celo! Everything else should work the same.
Migrating with RainbowKit and @celo/rainbowkit-celo
RainbowKit has WalletConnect v2 support in all its newest versions as well. We currently recommend using version 1 and above. The @celo/rainbowkit-celo package starting at version 1 has
a peer dependency for RainbowKit v1 as well (@rainbow-me/rainbowkit). This means you should upgrade both these packages (@celo/rainbowkit-celo, @rainbow-me/rainbowkit) to their latest
versions to add WalletConnect v2 support.
viem
We need to call out that RainbowKit v1 and up also has a peer dependency on wagmi
v1 and up. The biggest change here is that the newer versions of wagmi
use a library called viem
instead of ethers
. viem
is a great compact alternative to ethers
that supports Celo. However, if you still want to continue using ethers
in your dApp, or you want to migrate to
viem
incrementally, it’s not a problem and can be done with a small change, that we’ll cover in this guide, in how you use the React hooks provided by wagmi
.
Again you will need your WalletConnect project ID for this migration.
Code Changes
Again, the main updates you need to worry about are centered around the WC project ID.
First, we need to update the our the Celo connectors coming from rainbowkit-celo to use this.
// The importing from rainbowkit-celo hasn't changed
import celoGroups from "@celo/rainbowkit-celo/lists";
import { Alfajores, Celo, Cannoli } from "@celo/rainbowkit-celo/chains";
// Here is our project ID again
const walletConnectProjectId = "your_WC_project_id";
const connectors = celoGroups({
chains,
appName: (typeof document === "object" && document.title) || "Sample App",
// This is the only real change we need to make
projectId: walletConnectProjectId,
});
Then we give wagmi
our updated connectors with a few name changes in the wagmi
API.
The following example shows the wagmi
changes as well as how it works with RainbowKitProvider
.
import celoGroups from "@celo/rainbowkit-celo/lists";
import { Alfajores, Celo, Cannoli } from "@celo/rainbowkit-celo/chains";
// No changes to RainbowKitProvider
import { RainbowKitProvider } from "@rainbow-me/rainbowkit";
// Here createConfig was previously createClient
import { configureChains, createConfig, WagmiConfig } from "wagmi";
const walletConnectProjectId = "your_WC_project_id";
const connectors = celoGroups({
chains,
appName: (typeof document === "object" && document.title) || "Sample App",
projectId: walletConnectProjectId,
});
// Here publicClient was previously called provider
const { chains, publicClient } = configureChains(
[Alfajores, Celo, Cannoli],
[
jsonRpcProvider({
rpc: (chain) => ({ http: chain.rpcUrls.default.http[0] }),
}),
]
);
const wagmiConfig = createConfig({
autoConnect: true,
connectors,
// Using the new publicClient field and value instead of provider
publicClient: publicClient,
});
function MyApp() {
return (
<WagmiConfig config={wagmiConfig}>
<RainbowKitProvider chains={chains} coolMode={true}>
<YourMainAppComponent />
</RainbowKitProvider>
</WagmiConfig>
);
}
And those are all the changes you’ll need if you’re ready to start using viem
. If your dApp uses ethers
then continue on to the next section.
Keeping ethers
With the new version of wagmi
when you import and use useSigner
and useProvider
you’ll be getting the viem
signer and provider instead of ethers
.
However, we can remake these React hooks to return ethers
signers and providers instead.
First, create a file where we can put our new hooks. This file will likely be used all across your dApp so put it somewhere you can easily access it from anywhere.
Here’s what the file will contain, this comes from a guide posted by the wagmi
team.
(Note: This is for ethers v5. The wagmi
guide also includes an ethers v6 guide if needed.)
import * as React from 'react'
import { type PublicClient, usePublicClient, type WalletClient, useWalletClient } from 'wagmi'
import { providers } from 'ethers'
import { type HttpTransport } from 'viem'
function publicClientToProvider(publicClient: PublicClient) {
const { chain, transport } = publicClient
const network = {
chainId: chain.id,
name: chain.name,
ensAddress: chain.contracts?.ensRegistry?.address,
}
if (transport.type === 'fallback')
return new providers.FallbackProvider(
(transport.transports as ReturnType<HttpTransport>[]).map(
({ value }) => new providers.JsonRpcProvider(value?.url, network),
),
)
return new providers.JsonRpcProvider(transport.url, network)
}
/** Hook to convert a viem Public Client to an ethers.js Provider. */
export function useEthersProvider({ chainId }: { chainId?: number } = {}) {
const publicClient = usePublicClient({ chainId })
return React.useMemo(() => publicClientToProvider(publicClient), [publicClient])
}
function walletClientToSigner(walletClient: WalletClient) {
const { account, chain, transport } = walletClient
const network = {
chainId: chain.id,
name: chain.name,
ensAddress: chain.contracts?.ensRegistry?.address,
}
const provider = new providers.Web3Provider(transport, network)
const signer = provider.getSigner(account.address)
return signer
}
/** Hook to convert a viem Wallet Client to an ethers.js Signer. */
export function useEthersSigner({ chainId }: { chainId?: number } = {}) {
const { data: walletClient } = useWalletClient({ chainId })
return React.useMemo(
() => (walletClient ? walletClientToSigner(walletClient) : undefined),
[walletClient],
)
}
Now that you have this you can import these two hooks instead of the two from wagmi
see the following example.
// This is what would have been imported previously
// import { useProvider, useSigner } from 'wagmi'
// Now instead we import our custom hooks
import { useEthersProvider, useEthersSigner } from 'your-custom-hooks-file'
function Component() {
// This is the old way to get an ethers signer from wagmi
// const signer = useSigner()
// Now we use our custom useEthersSigner hook
const signer = useEthersSigner()
// This is the old way to get an ethers provider from wagmi
// const provider = useProvider()
// Now we use our custom useEthersProvider hook
const provider = useEthersProvider()
}
The signer
and provider
gotten from our hooks are the same signer
and provider
you would normally get from ethers
and can be used the same way.
We should note that an additional change to wagmi
version 1 is that both useSigner
and useProvider
have been replaced with their viem
counterparts.
If you choose to use viem
in your dApp then useSigner
will become useWalletClient
and useProvider
will become usePublicClient
.