Back to homepage

How to detect and switch Metamask chain in a web3 app

Published

In a previous article, I created a web3 template project which basically had a button to trigger Metamask authentication and retrieved the account. It's something very basic but you'll need to do in every single web3 app you're building so that's why I decided to create a template that I could use as a starting point for other projects.

Of course it was just a first version and had a few issues like, for example, not detecting if Metamask was connected to the correct chain. In this article I'm going to explain how I've improved my web3 template project to detect the network that Metamask is connected to and prompt a switch to the correct network.

How to detect Metamask network

One of the most important things to do to integrate Metamask authentication is making sure the client is connected to the same network (or blockchain) that our application is running on. If we deploy our application's smart contracts to the Ethereum main net but the client's Metamask is connected to Polygon, the app is not going to work.

To detect which chain the user's Metamask is connected to, we can use the eth_chainId method.

// targets Rinkeby chain, id 4
const targetNetworkId = '0x4';

// checks if current chain matches with the one we need
// and returns true/false
const checkNetwork = async () => {
  if (window.ethereum) {
    const currentChainId = await window.ethereum.request({
      method: 'eth_chainId',
    });

    // return true if network id is the same
    if (currentChainId == targetNetworkId) return true;
    // return false is network id is different
    return false;
  }
};

In the code above, we're declaring a variable targetNetworkId with the chainId that holds the application smart contracts. Then we're just checking if the currentChainId returned by MEtamask, matches with the one we want to target.

It's important to notice that Metamask returns the id in "0x format" which means they're prefixed with "0x". For example, Ethereum main net chain id is 1, so Metamsk will return "0x1" if it's connected to that network. In the example above, the target is Rinkeby (network 4) so the chain id would be "0x4".

You can find more info about Metamask default chains here or if you are using other EVM (Ethereum Virtual Machine) compatible chains, you can check their ids here.

How to swtich chain in Metamask

If we detect that Mrtamsk is not connected to the chain we want to, we can trigger a prompt to switch to a different network. To do that, we can use the wallet_switchEthereumChain method and pass it the chainId as a parameter:

// targets Rinkeby chain, id 4
const targetNetworkId = '0x4';

// switches network to the one provided
const switchNetwork = async () => {
  await window.ethereum.request({
    method: 'wallet_switchEthereumChain',
    params: [{ chainId: targetNetworkId }],
  });
  // refresh
  window.location.reload();
};

The wallet_switchEthereumChain will prompt a popup that will ask the user to connect to the chain we want to.

Again, we have to make sure that the chainId that we're passing as a parameter is in "0x prefixed" format. If were to just pass a number like 4, we'll get the following error:

MetaMask - RPC Error: Expected 0x-prefixed, unpadded, non-zero hexadecimal string 'chainId'.

To avoid it, just make sure that the chainId is using a "0x prefixed" format.

Conclusion

I've included these changes in my web3 template project, which you can find in this repo in GitHub. It also uses environment variables to load the target network id so it can be updated in different environments.

Feel free to clone the repo and use it in your projects 🤙

TAGS

If you enjoyed this article consider sharing it on social media or buying me a coffee ✌️

Buy Me A Coffee