Connect dApp to MetaMask Wallet using Ethers.js
Tags: web3, javascript, webdev, react
Published: 2022-09-05 11:12:26

# Introduction

A DApp, which stands for decentralized application, uses a smart contract to run on a peer-to-peer (P2P) blockchain network. To interact with a blockchain, users need to connect their crypto wallet to the dApp. 

MetaMask is the most popular crypto wallet out there. It runs as a browser extension on the popular browser. You can also download its mobile application for Android and iOS. It is one of the most secure and trusted wallets to use. Almost every popular dApp has support for MetaMask. So, having support for MetaMask for any dApp is a plus point.

Today, we are going to learn about the following things:
- Connecting dApp to MetaMask
- Extracting Accounts from MetaMask
- Switching between different Networks for instance from Polygon to Avalanche

You can follow me on Twitter([@surajondev](https://twitter.com/surajondev)) to get notified for such posts in the future. 

Let's get started to build the application with the above features.

# Environment Setup

We are going to use React for building our frontend. You can install React with the below command:

**command:**
```bat
npx create-react-app connect-metamask
```

After installing React, delete all the unnecessary files and code. 

As for the dependencies, we just need one library, ethers. Ethers will be helpful in interacting with our wallet. Install it with the below command:

**command:**
```bat
npm i ethers
```

*Note: To run the above commands, you need to have [node.js](https://nodejs.org/en/download/) pre-installed.*

Now, that everything is set up, let's write some code.

# App.js

We are going to implement all our features only in the `App.js` file. As it will be easy to understand the code in one place.

## Imports

At the top, we need to import the necessary file and library that we are going to use. As for imports, we have the following:

```jsx
import "./styles.css"; // styling the component using CSS
import { useState } from "react"; // storing data in the state
import { ethers } from "ethers"; // interacting with wallet
```

## Return Statement

In the file, we need to define a functional component, where all the magic will happen. At the top, we have to define all the states for storing data.

```jsx
export default function App() {
  const [publicKey, setPublickey] = useState();
  const [network, setNetwork] = useState();
  const [chainId, setChainId] = useState();
  const [msg, setMsg] = useState();

  return()
}
```

As for the UI, it will go into the return code block. 

```jsx
return (
    <div className="App">
      <h1>Connect MetaMask</h1>
      <button onClick={connectButton}>Connect Wallet</button>
      <br />
      <button className="btn" onClick={() => swithcNetwork(137)}>
        Connect Polygon
      </button>
      <br />
      <button className="btn" onClick={() => swithcNetwork(43114)}>
        Connect Avalanche
      </button>
      <p>Public Key: {publicKey}</p>
      <p>Network: {network}</p>
      <p>Chain ID : {chainId}</p>
      {msg && <p>{msg}</p>}
    </div>
  );
```
It will result in the below output:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1662365869802/rsUPjyLGm.png)

*Note: React will give errors as we haven't defined the function used for the onClick event for the buttons. The above screenshot is of complemented project.*

We are having the following components in the return section of the application:

- **Connect Wallet**: On clicking this button, `connectButton` function will invoke. This will connect our dApp to the MetaMask.

- **Connect Polygon/Avalanche**: This button will invoke the `switchNetwork()` function for changing the network to Polygon/Avalanche.

- **Network Details**: When the user successfully connects to the MetaMask. The Public key, Chain ID of the network, and name of the network will be displayed. 

- **Msg**: If any error occurs, such as MetaMask is not installed. This will display the error to the user.

The return statement has been implemented quite well. Let's write code for all the functions used above. 

## Connect Wallet Button

This function will make a request to the MetaMask for the connection. Before that, we will check whether MetaMask is installed or not. 

Here is the code for connect wallet button:

```jsx
  const connectButton = async () => {
    const { ethereum } = window;
    if (ethereum.isMetaMask) {
      const provider = new ethers.providers.Web3Provider(ethereum);
      const accounts = await provider.send("eth_requestAccounts", []);

      const { name, chainId } = await provider.getNetwork();

      setNetwork(name);
      setChainId(chainId);
      setPublickey(accounts[0]);
    } else {
      setMsg("Install MetaMask");
    }
  };
```

At the top, we have extracted the ethereum object from the window. This object has information related to blockchain interaction. When MetaMask is installed, it injects its data into this object. That's why, it become one of the important objects while dealing with MetaMask and blockchain.

With the object, `ethereum.isMetaMask`, we are checking for the MetaMask. It returns `true` if MetaMask is installed and `false` otherwise. We are running all the code only if MetaMask is installed otherwise, it will throw a message to `Install MetaMask`.

A Provider in ethers is a read-only abstraction to access the blockchain data. To access data we have used the `ethers.providers.Web3Provider()` function with extracted `ethereum` object from the window as the argument. With `provider.send()` function, we are requesting the account from the MetaMask and storing them in array format in the `accounts` variable. 

`provider.getNetwork` provides us with the network details. Form that we are extracting the name and chainId of the network. The network here will be the default from the MetaMask. After this, we are setting the state with the available data to display to the user.

## Switch Network Button

The second and third button is for switching between Polygon and Avalanche network. 

```jsx
  const swithcNetwork = async (chainId) => {
    try {
      await window.ethereum.request({
        method: "wallet_addEthereumChain",
        params: [avlNetwork[`${chainId}`]]
      });
      setNetwork(avlNetwork[`${chainId}`].chainName);
      setChainId(chainId);
    } catch (error) {
      setMsg(error);
    }
  };
```

`wallet_addEthereumChain` method will add the network to the MetaMask and switch to that network. This function takes an argument `chainId` to change the network to that matching network. Every network is associated with a chainId and it's unique for every network. We have try-catch block for setting `msg`, if any error occurs. 

The params contain information regarding the network such as chainId, rpcUrls, nativeCurrency, and others. I have stored the network information in an object format in the variable `avlNetwork`. 

```javascript

const avlNetwork = {
  137: {
    chainId: `0x${Number(137).toString(16)}`,
    rpcUrls: ["https://rpc-mainnet.matic.network/"],
    chainName: "Polygon Mainnet",
    nativeCurrency: {
      name: "MATIC",
      symbol: "MATIC",
      decimals: 18
    },
    blockExplorerUrls: ["https://polygonscan.com/"]
  },
  43114: {
    chainId: `0x${Number(43114).toString(16)}`,
    rpcUrls: ["https://api.avax.network/ext/bc/C/rpc"],
    chainName: "Avalanche C-Chain",
    nativeCurrency: {
      name: "Avalanche",
      symbol: "AVAX",
      decimals: 18
    },
    blockExplorerUrls: ["https://snowtrace.io/"]
  }
};
```
There is a lot of information regarding the network to which we are switching. You can get all these information for any network from [ChainList](https://chainlist.org/) and [ChainList - JSON](https://chainid.network/chains.json). I have used the chainId as the name for each object so that we can access the network information by just passing the chainId. 

MetaMask accepts chainId in Hexadecimal format with the prefix `0x`. We have converted the chainId of every network into the hexadecimal with the `toString(16)` function, 16 for hexadecimal. 

# Demo

Now the project has been completed. It's time to test the application. If you click on `Connect Wallet`, it will connect our dApp to the MetaMask and provide us with details. 

![Connect to MetaMasl](https://cdn.hashnode.com/res/hashnode/image/upload/v1662370628176/xhq4jYDfN.png)

Now, you are eligible to switch to a different network. Click on `Connect Polygon` to switch to the Polygon Mainnet. This will pop a message on the MetaMask wallet, requesting permission to switch to the Polygon Mainnet. 

![Switch Network Permission](https://cdn.hashnode.com/res/hashnode/image/upload/v1662370732652/5dA1xMo8i.png)


After clicking the `Switch Network`, you will be switched to the Polygon Mainnet. You will be able to see the details of the current network in the application.


![Connect Polygon](https://cdn.hashnode.com/res/hashnode/image/upload/v1662371143085/yXLgbKz2-.png)

I have created a codesandbox for these projects. You can see the code and the live working of the project here.

{% codesandbox connect-metamask-kyprkm %}


# Connect With Me

- [Twitter](https://twitter.com/surajondev)
- [LinkedIn](https://www.linkedin.com/in/surajondev/)

# Conclusion

Connecting your dApp to Wallet is an important step in building a blockchain-based application. There are various methods to achieve these features. I have explained one such here. In the future, I might discuss using other libraries to do it more effectively with less code. For that, you can follow me to get notified.

I hope, this article has helped you in connecting your dApp to the wallet. Thanks for reading the blog post.