Tutorial: Connect to MetaMask using vanilla JavaScript

lnmunhoz

Lucas N. Munhoz

Posted on May 4, 2022

Tutorial: Connect to MetaMask using vanilla JavaScript

In this post, you’ll learn how simply connect your frontend application to a MetaMask Wallet 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/ 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:

if (typeof window.ethereum !== "undefined") {
  console.log("MetaMask is installed!");
} else {
  console.log("MetaMask is NOT installed!");
}
Enter fullscreen mode Exit fullscreen mode

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 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.

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.

<!-- 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>
Enter fullscreen mode Exit fullscreen mode
// 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()
Enter fullscreen mode Exit fullscreen mode

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.

<!-- 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>
Enter fullscreen mode Exit fullscreen mode
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();
Enter fullscreen mode Exit fullscreen mode

Detect and display the current network

Let’s add a new element to our index.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>
Enter fullscreen mode Exit fullscreen mode

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

... 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);
}
Enter fullscreen mode Exit fullscreen mode

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

function connect() {
  connectButton.textContent = "Loading...";
    chainElement.textContent = "";
  errorElement.textContent = "";
  return getAccounts()
    .then(showAccount)
    .then(getChainId)
    .then(showChain)
    .catch(showError);
}
Enter fullscreen mode Exit fullscreen mode

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

Connect to metamask wallet demo

💖 💪 🙅 🚩
lnmunhoz
Lucas N. Munhoz

Posted on May 4, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related