How to Connect Web3.js to MetaMask in 2020

Image for post
Image for post

As of Q1 2020, MetaMask has officially stopped injecting Web3.js, and has updated the way you access the current provider. Here’s how to make sure your dApp doesn’t break, and how to make it more compatible with the rest of the ecosystem.

The Old(ish) Way

Prior to Q1 2020, MetaMask was injecting an outdated version of Web3.js, something like 0.20.x — and most people would just use the injected web3.currentProvider that MetaMask had exposed as the connection string to point their newer web3 version to.

The code would look something like this:

const Web3 = require("web3");

What this breaks down to is first checking if MetaMask is installed by checking if window.web3 was injected. If it was, then we replace the injected web3 with a newer version that we imported ourselves from somewhere like npm.

The important part to notice here is that we used the web3.currentProvider that MetaMask provided as our provider for the newer web3. This is what enabled the newer web3 version to talk to MetaMask and access the accounts and current network.

The window.ethereum.enable() line actually makes the popup UI request to connect your dApp to MetaMask, and window.web3 becomes the updated version.

Then, we could simply run the following on document load to initialize our dApp:

if (!ethEnabled()) {

This would prompt the user to install MetaMask if it was not detected, otherwise, the dApp connection to MetaMask would be initialized.

The New, More Compatible Way

According to this article:

The primary motivation for these changes is to implement EIP-1102 and EIP-1193. This is great for everyone in the dApp community, since now Ethereum providers like MetaMask, Status, and Ethereum-compatible browsers will all have a standard to conform to for exposing their APIs.

The gist of the changes is basically that providers like MetaMask and Status must continue to inject window.ethereum, but now the window.ethereum object itself is a provider type that supports the methods defined in EIP-1102 and EIP-1193. No more having to check window.web3 for its currentProvider — we can simply use window.ethereum as the provider itself!

The code:

const Web3 = require("web3");

Super clean! Essentially, we check if the window.ethereum exists, then create a window.web3 object with our own provided version of web3, using the window.ethereum object as the input provider .

Once again, the window.ethereum.enable() function calls the pop-up UI dialogue that asks the user’s permission to connect the dApp to MetaMask.

In this case, your dApp is now compatible with any EIP-1102 and EIP-1193 compliant Ethereum provider, making it accessible to many more potential users, and doesn’t lock your dApp into one provider.

Initializing the dApp can now output a slightly different message when you can’t detect a provider:

if (!ethEnabled()) {

In reality, you should be following a better UX flow than that though, rather than forcing users to install something before accessing your dApp. I recommend checking out the Rimble UX pattern guides, specifically, Connecting to a dApp for tips on how to handle new users that may not even know what a dApp is gracefully and only calling to MetaMask/other providers when absolutely necessary.

Hope that helps others, as the documentation regarding these changes is not as concise as it could be yet, as these changes are quite new. For more information about handling legacy browsers/providers, check out the Status Documentation for their implementation of EIP-1102 (the steps are the same for MetaMask, since both follow the standard).

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store