Tutorial: Connect to MetaMask using vanilla JavaScript
Tags: metamask, web3, javascript, tutorial
Published: 2022-05-04 20:58:27

In this post, you’ll learn how simply connect your frontend application to a [MetaMask Wallet](https://metamask.io/) using simple JavaScript code.

The intention is to demonstrate how simple it is without all the noise of libraries like React in the way.

Let’s get started.

### Create a new Vanilla JavaScript Sandbox

First, we start by opening [https://codesandbox.io/](https://codesandbox.io/) and creating a new Sandbox for VanillaJS.

You can delete all the content within `index.js` file, so we have a fresh start.

Now we are ready to go!

### Understanding `window.ethereum`

In order to connect to the MetaMask wallet, we need to programmatically check to make sure that the user has the MetaMask extension installed in the browser. To do that, we can simply paste this code into our `index.js` file:

```js
if (typeof window.ethereum !== "undefined") {
  console.log("MetaMask is installed!");
} else {
  console.log("MetaMask is NOT installed!");
}
```

After pasting it, check the **Console** tab on your Sandbox, you should be able to the `console.log` message. If you don’t have MetaMask installed, make your you do by visiting the [official website](https://metamask.io/download/) and selecting the correct version for your browser.

Continuing, what is `window.ethereum` anyway? Without going too much into detail, the browser extension injects this object into your browser. This `ethereum` object is more formally called Ethereum Provider, which as the name says, provides you an API to access Ethereum-based networks.

If you are more curious about Ethereum Provider API, read more [here](https://docs.metamask.io/guide/ethereum-provider.html#ethereum-provider-api).

### Check if the user’s browser has access to the MetaMask wallet

Let’s now create a button that will tell us if we are ready to connect to MetaMask or not based if `window.ethereum` is available or not.

```html
<!-- index.html -->

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <button id="connect-btn">Connect Wallet</button>

    <script src="src/index.js"></script>
  </body>
</html>
```

```js
// index.js

function isEthereumAvailable() {
  return window.ethereum !== "undefined"
}

const connectButton = document.getElementById('connect-btn')

function init() {
  if (isEthereumAvailable()) {
    connectButton.textContent = 'Connect Wallet'
    connectButton.removeAttribute('disabled')
  } else {
    connectButton.textContent = 'Ethereum not available. Please install MetaMask!'
    connectButton.setAttribute('disabled', true)
  }
}

init()
```

Great, now we have a button that will be disabled and tell the user to go and install MetaMask in the case is not available. Otherwise, it will display “Connect Wallet”.

### Display the MetaMask popup to ask for permissions to view user accounts

Now that we have our button, we need to make sure when it’s clicked, it will popup MetaMask for the user.

```html
<!-- index.html -->

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <button id="connect-btn">Connect Wallet</button>

		<-- Add this line so we can display the connected account -->
    <div id="account">Account not connected</div>
		
		<-- Add this line so we can display errors -->
		<div id="error"></div>

    <script src="src/index.js"></script>
  </body>
</html>
```

```js
function isEthereumAvailable() {
  return window.ethereum !== "undefined";
}

const connectButton = document.getElementById("connect-btn");

// + Add this two elements to give feedback to the user
const accountElement = document.getElementById("account");
const errorElement = document.getElementById("error");

// + Add this function to request the user accounts
//   This will display the MetaMask popup to the user
async function getAccounts() {
  return window.ethereum.request({
    method: "eth_requestAccounts"
  });
}

// + Add the connect function that will be triggered by the connectButton
function connect() {
  connectButton.textContent = "Loading...";
  errorElement.textContent = "";
  return getAccounts().then(showAccount).catch(showError);
}

// + Display the selected wallet address
function showAccount(accounts) {
  if (accounts.length > 0) {
    accountElement.textContent = 'Account: ' + accounts[0];
    connectButton.textContent = "Connected";
  }
}

// + Displays an error to the user when trying to connect the wallet
function showError(err) {
  connectButton.textContent = "Connect Wallet";
  errorElement.textContent = err.message;
}

function init() {
  if (isEthereumAvailable()) {
    connectButton.textContent = "Connect Wallet";
    connectButton.removeAttribute("disabled");

    // + Add this line to add the connect function to the button
    connectButton.addEventListener("click", connect);
  } else {
    connectButton.textContent = "Ethereum not available";
    connectButton.setAttribute("disabled", true);
  }
}

init();
```

### Detect and display the current network

Let’s add a new element to our `index.html`

```html
... same as before
<body>
  <button id="connect-btn">Connect Wallet</button>
  <div id="account">Account not connected</div>
  <div id="error"></div>

	<!-- Add this line so we can display the connected network --> 
	<div id="chain"></div>

	<script src="src/index.js"></script>
</body>
```

In our `index.js` file, we will add a couple of new functions:

```jsx
... same as before
// Add this after errorElement variable
const chainElement = document.getElementById("chain");

async function getChainId() {
  const chainId = await window.ethereum.request({ method: "eth_chainId" });
  return chainId;
}

// We will use this to display a friendly name for the chain,
// as the getChainId method will give us the chainId.
function getChainName(chainId) {
  switch (chainId) {
    case "0x1":
      return "Ethereum Main Network";
    case "0x3":
      return "Ropsten Test Network";
    case "0x4":
      return "Rinkeby Test Network";
    case "0x5":
      return "Goerli Test Network";
    case "0x2a":
      return "Kovan Test Network";
    default:
      default: "Chain not supported"
  }
}

function showChain(chainId) {
  chainElement.textContent = getChainName(chainId);
}
```

And in our `connect` function, let’s update so it will look like this:

```jsx
function connect() {
  connectButton.textContent = "Loading...";
	chainElement.textContent = "";
  errorElement.textContent = "";
  return getAccounts()
    .then(showAccount)
    .then(getChainId)
    .then(showChain)
    .catch(showError);
}
```

And there you have it, the final result should look like this:

![Connect to metamask wallet demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h1nw4tnkz6ddt8m4ia8f.png)