Search code examples
javascriptmetamaskrsk

How to connect Metamask to Rootstock networks?


I am building a DApp which connects to Rootstock Testnet and Mainnet via MetaMask. Unfortunately, I didn't find Rootstock among the available networks out of the box in MetaMask. ​ In this tutorial I found the information on how to manually add Rootstock networks to MetaMask, however I don't want to bother users of my DApp by copying and pasting this information into MetaMask. ​ Is there a way to programmatically add this network config to Metamask and then immediately switch to that network, after a user initiates a wallet connection somewhere in this place: ​

document
  .getElementById('connect-to-metamask-button')
  .addEventListener('click', async () => {
    await window.ethereum.request({
      method: 'eth_requestAccounts',
    });
    // switch to the Rootstock network
  });

Solution

  • in addition to Petr's answer;

    In summary, yes you can, by using wallet_addEthereumChain and wallet_switchEthereumChain. Details below. ​ Adding a new network is described here in the Metamask docs. ​ To add the Rootstock networks to Metamask, first Create network configuration objects: ​ For the Rootstock Testnet: ​

    const rskTestnet = {
      chainName: 'Rootstock Testnet',
      chainId: '0x1f', // hex 31
      rpcUrls: ['https://public-node.testnet.rsk.co'],
      blockExplorerUrls: ['https://explorer.testnet.rsk.co/'],
      nativeCurrency: {
        symbol: 'tRBTC',
        decimals: 18,
      },
    };
    

    ​ For the Rootstock Mainnet: ​

    const rskMainnet = {
      chainName: 'Rootstock Mainnet',
      chainId: '0x1e', // hex 30
      rpcUrls: ['https://public-node.rsk.co'],
      blockExplorerUrls: ['https://explorer.rsk.co/'],
      nativeCurrency: {
        symbol: 'RBTC',
        decimals: 18,
      },
    };
    

    ​ When the user starts the DApp, the first thing to do is to attempt to switch to the target network using wallet_switchEthereumChain. Assuming you intend this to be the Rootstock Testnet: ​

    await window.ethereum.request({
        method: 'wallet_switchEthereumChain',
        params: [{ chainId: rskTestnet.chainId }],
    });
    

    ​ However if the network you are trying to switch has yet to be added to Metamask (your case), it will throw an error with a code 4902, which you need to catch in a try-catch block. ​ When this happens, you have detected that the user does not have this network configured in Metamask. If this is the case, use wallet_addEthereumChain to add its config. ​

    await window.ethereum.request({
        method: 'wallet_addEthereumChain',
        params: [rskTestnet],
    });
    

    ​ Thus, the switchToRskNetwork function, which you may want to call from the desired place in your DApp, could look like this: ​

    async function switchToNetwork(network) {
      try {
        // switching to a network
        await window.ethereum.request({
          method: 'wallet_switchEthereumChain',
          params: [{ chainId: network.chainId }],
        });
        // catching the error 4902
      } catch (error) {
        if (error.code === 4902) {
          // adding a new chain to Metamask
          await window.ethereum.request({
            method: 'wallet_addEthereumChain',
            params: [network],
          });
        }
      }
    }
    

    ​ You should call this function either when your DApp initialises (e.g. adjacent to eth_requestAccounts in your example code), or upon selection of the network by the user. To do so, pass in the network configuration object: ​

    await switchToNetwork(rskTestnet)