Connect Metamask with Ethers.js

Aw Kai Shin
6 min readSep 27, 2022

--

The Ethers.js library enables us to easily interact with the Ethereum blockchain using Javascript. As such, it significantly speeds up the development process for web applications which have to interface with EVM blockchains. We had previously explored how to connect Metamask to our web app without the use of convenience libraries here:

This guide extends upon the above and describes how much more intuitive Ethers.js is through implementing a simple ETH transfer form running in your Express app. Through this transfer, you will be able to see how your web app is able to:

  • Run Ethers.js in the browser (using Browserify)
  • Expose the Metamask account as a Javascript object
  • Create and sign an Ethereum transaction request
  • Send the signed transaction request to the network
  • View the transaction receipt returned from the network

The Github repository for this guide can be found here. If you would like to configure Metamask, you can refer to a separate guide:

Further info on how to deploy and interact with smart contracts (tokens, NFTs, decentralised storage):

Create form to send ETH

As we will be building on top of the previous guide, we will first need to clone the Github repository and install the dependencies:

git clone https://github.com/0xKai27/ExpressMetamask.git
npm install

Once the installation is complete, you can run nodemon start and you should see the following when visiting localhost:3000 in the browser:

You can refer to this guide if you would like further details on how we managed to get the above connection with vanilla node.js. With the base application working, we can then start adding our form.

Navigate to the index.ejs file located in the /views directory and copy and paste the following code:

Our form will have two inputs:

  • addressTo: The recipient address
  • ETHAmount: The amount to send denominated in ETH

Also note that we have included an additional bundle.js script which will contain the logic for our form. Save the file and nodemon would have refreshed the page.

Now it’s time to link the form to our backend code.

Script to connect with Metamask

In the main project directory, create a provider.js file:

touch provider.js

This file will contain the required logic linking together Metamask and Ethers.js (we will get to the bundle.js file in the next section). As such, we first need to install the Ethers.js library:

npm install ethers

We can then copy and paste the following into the newly created provider.js:

Line 4 and 5 are actually the key lines of code which exposes the Metamask account for us to use in our application. It creates two objects:

  • provider: An abstraction of a connection to the Ethereum network (ie alchemy, infura, etc). In other words, which is the service provider that our application is using to connect to the Ethereum network.
  • signer: An abstraction of an Ethereum Account. This is the object which we can use to sign and send transactions.

To make the above more concrete, the rest of the code implements the required form logic to send an ETH transaction. The form components are first initialised and their respective values are stored in addressToValue and ETHAmountValue. Based on the ETHAmountValue, we also convert the amount in ETH to WEI using the Ethers.js utils, whereby 1 ETH is equal to 10^18 wei.

These 2 values then form part of the full transactionRequest. For the transactionRequest to be successful, there are a number of other variables which have to be filled prior to transacting (gas price, nonce, etc.). Note that you can view the complete transactionRequest structure on the Ethers.js docs.

Fortunately, Ethers.js provides a handy sendTransaction function which also conveniently populates the transaction based on the signer object. sendTransaction() forms the full transaction and submits the transaction to the network. A promise containing the transaction receipt hash is then returned and logged in the console.

Browserify: Running Ethers.js in the Browser

While we have written out the logic required to connect Metamask, we now run into an issue as we are unable to import the Ethers.js module into our browser where our script will run. Recall that this script will be hosted on the client’s browser and therefore needs to be served as a static file as opposed to running on our local server. This is the reason why our code also references window.ethereum which is a property of the browser’s window object.

Browserify provides just the tooling required enabling us to run Ethers.js (or any other require module) in the browser. We can install it globally by using the command below:

npm install -g browserify

Once installed, we can use browserify --help to access the list of options. For our purposes, we will be defining an output file path using the -o flag:

browserify app.js -o public/javascripts/bundle.js

The above will create the bundle.js file in the public directory which static assets are served from. Note that our index.ejs file also contains a script tag referencing this path. Once bundle.js has been generated, nodemon would have automatically refreshed our application and it should now be working.

Sending Test Ethers

In order to test the form, we will be connecting to our Hardhat test network which we setup previously here. Once connected, refresh the network bootstrap state by running:

npx hardhat node

With Metamask connected to our Hardhat network, we should be able to see 10,000 HARDHATETH in both our imported test accounts.

For this test, we will be transferring 32 HARDHATETH from Hardhat1 to Hardhat2. Copy the Hardhat2 address from Metamask and paste it into the “Send to:” box. For the “Amount in ETH:”, we can put in the ETH denominated amount which is 32.

Upon clicking the “Send ETH” function, Metamask should prompt you to confirm the transaction. Note that you might need to reset the account or enable a custom nonce if the account was previously used for testing on another network.

On clicking “Confirm”, you will then be able to see the transaction receipt being printed into the browser’s console.

Additionally, the Hardhat network console would have also logged the incoming transaction which is pending network confirmation. You can monitor the network console to see what other functions are called once the transaction has been “mined” by the network.

Upon transaction success, Metamask should then reflect the respective balances as well as the transaction status.

Congrats, you have successfully connected Ethers.js to Metamask and even implemented a send function!

Thanks for staying till the end. Would love to hear your thought/comments so do drop a comment. I’m active on twitter @AwKaiShin if you would like to receive more digestible tidbits of crypto-related info or visit my personal website if you would like my services :)

--

--

Aw Kai Shin

Web3, Crypto & Blockchain: Building a More Equitable Web | Technical Writer @FactorDAO | www.awkaishin.com