Ethereum JavaScript Libraries: web3.js vs. ethers.js (Part I)

https://blog.infura.io/ethereum-javascript-libraries-web3-js-vs-ethers-js-part-i/
Ethereum JavaScript Libraries: web3.js vs. ethers.js (Part I)

Ethereum JavaScript Libraries: web3.js vs. ethers.js (Part I)

Web3.js and ethers.js are JavaScript libraries that allow developers to interact with the Ethereum blockchain. They are both great libraries – either library will likely meet the needs of most Ethereum developers. This article is a comparison of web3.js and ethers.js, focusing on their similarities and differences, so that you can better understand the nuances of the libraries. It is written with the intent of educating developers to understand the tradeoffs between the two libraries to be able to make a decision of which library to use for their particular use case. This article includes resources that may be useful for those who are new to blockchain development or programming in general.

TL;DR: Both libraries work. For your use case, one library may be better for you.

Web3.js has a community of users and maintainers associated with the Ethereum Foundation. It has a good API reference. It has been around since 2015 and has seen extensive use by many projects. Due to this fact, the library has been the “go-to” in many “Build Your First dApp” tutorials.

Ethers.js is excellent because it is a small, compact library, with a large number of test cases. It has good “Getting Started” documentation, making it accessible to new users. “Simple” and “intuitive” are words that are often used by developers to describe their experience with ethers.js and the library has gained in popularity over the past two years, seeing increasing downloads and usage by projects.

What is web3.js?

Ethereum JavaScript Libraries: web3.js vs. ethers.js (Part I)

The web3.js library is an open source JavaScript library (GNU Lesser General Public License version 3) built by the Ethereum Foundation, and it includes functions to communicate with an Ethereum node via the JavaScript Object Notation – Remote Procedure Call (JSON-RPC) protocol. In other words, it is a JavaScript library that allows a developer to interact with the Ethereum blockchain. Web3.js is currently on version 1.2.9, which is the version referenced in this article. Web3.js is made up of four modules.

What is a module?

In JavaScript, a module is code that has specific functionality within a larger program. Modules should be self-contained, so that if you remove a module from a library, program, or application, the overall library, program, or application should not stop working. For those who are familiar with python or java, you might be familiar with “Classes”, which are analogous to modules. For those who are new to JavaScript, FreeCodeCamp has a great explanation of JavaScript modules.

What modules make up web3.js?

Web3.js has a main class called web3. The bulk of the functionality of the library are found within this class. The five additional modules that make up web3js are:

  1. web3-eth
  2. web3-shh
  3. web3-bzz
  4. web3-net
  5. web3-utils

What does web3-eth do?

The web3-eth module contains functions that allow a user of web3.js to interact with the Ethereum blockchain. Specifically, these functions are able to interact with smart contracts, externally-owned accounts, nodes, mined blocks, and transactions. Three illustrative examples are shown below:

  • web3.eth.getBalance allows you to get the ETH balance of an address at a given block
  • web3.eth.signTransaction allows you to sign a transaction
  • web3.eth.sendSignedTransaction allows you to send a signed transaction to the Ethereum blockchain.

What does web3-shh do?

The web3-shh module allows you to interact with the Whisper protocol. Whisper is a messaging protocol, designed to broadcast messages easily and for low-level asynchronous communication. Two illustrative examples are shown below:

  • web3.shh.post posts a whisper message to the network
  • web3.shh.subscribe creates a subscription to incoming whisper messages

What does web3-bzz do?

The web3-bzz module allows you to interact with Swarm. Swarm is a decentralized storage platform and content distribution service—it can serve as a place to store files like images or videos for your decentralized application (dapp). Two illustrative examples are shown below:

  • web3.bzz.upload allows you to upload files and folders to Swarm
  • Web3.bzz.download allows you to download files and folders from Swarm

What does web3-net do?

The web3-net module allows you to interact with the network properties of an Ethereum node. Using web3-net will allow you to find out information about the node, with the .net following the protocol you are interested in getting information about (designated here with a *, representing the choice of web.eth.net, web3.shh.net, or web3.bzz.net). Two illustrative examples are shown below:

  • web3.*.net.getID returns the network ID
  • web3.* .net.getPeerCount returns the number of peers that the node is connected to

What does web3-utils do?

The web3-utils module provides you with utility functions that you can use within an Ethereum dapp as well as with other web3.js modules. A utility function is a reusable function to make writing code easier—which is common in JavaScript and other programming languages (see JavaScript: The Definitive Guide, 6th Edition by Dave Flanagan for a description of utility functions existing in the JQuery library of JavaScript). Web3-utils includes utility functions that convert numbers, verify if a value meets a certain condition, and search datasets. Three illustrative examples are shown below:

  • web3.utils.toWei converts Ether to Wei
  • web3.utils.hexToNumberString converts a hexadecimal value to a stringweb3.utils.isAddress checks if a given string is a valid Ethereum address.

What is ethers.js?

Ethereum JavaScript Libraries: web3.js vs. ethers.js (Part I)

Ethers.js is a JavaScript library that allows developers to interact with the Ethereum blockchain. The library includes utility functions in JavaScript and TypeScript, and has all the capabilities of an Ethereum wallet. Ethers.js is currently on version 5.0.3. Ethers.js was created by Ethers and is open source via the MIT License.

Similar to web3.js, ethers.js has four modules which make up the application programming interface (API).

  1. Ethers.provider
  2. Ethers.contract
  3. Ethers.utils
  4. Ethers.wallets

What does ethers.provider do?

Ethers.provider allows you to abstract a connection to the Ethereum blockchain. It can be used for issuing queries and sending signed transactions that will change the state of the blockchain. Three illustrative examples are below:

  • ethers.providers.InfuraProvider allows you to connect to the Infura hosted network of Ethereum nodes
  • ethers.provider.getBalance will get you the ETH balance of an address or a block in the blockchain
  • ethers.provider.resolve will resolve an Ethereum Name Service (ENS) name passed in to an Ethereum address (via a Promise—if you are new to JavaScript, we would encourage you to read more about Promises, as they allow the return of data at some point in the future when it is computed).

A note: web3.js also has providers for this purpose – and they are in the web3 base module. Ethers.js and web3.js are organized quite differently, hence there is not always a clear mapping of module to module, even if the functionality of both libraries is very similar.

What does ethers.contract do?

Ethers.contract allows you to deploy and interact with smart contracts. Specifically, the functions in this module allow you to listen for events emitted from a smart contract, call functions provided by a smart contract, get information about smart contracts, and deploy smart contracts. Two illustrative examples are below:

  • ethers.ContractFactory.fromSolidity creates a “factory” for deployment of a smart contract from compiler output of the Solidity compiler or from the Truffle generated JSON fileethers.Contract allows you to interact with a smart contract once it has been deployed.

What does ethers.utils do?

Ethers.utils provides utility functions for formatting data and processing user inputs. Ethers.utils works like web3-utils and makes building decentralized applications easier. Three examples are below:

  • ethers.utils.getContractAddress retrieves a smart contract address from the transaction used to deploy the smart contract
  • ethers.utils.computeAddress computes an address by passing the function the public or private key associated with the addressethers.utils.formatEther will format a passed in amount of Wei into a decimal string of Ether

What does ethers.wallet do?

Ethers.wallet provides some functionality that is different than the other modules we have discussed up to this point. Ethers.wallet allows you to connect to an existing wallet (an Ethereum address), create a new wallet, and sign transactions. Three examples:

  • ethers.wallet.createRandom will create a random new account.
  • ethers.wallet.sign will sign a transaction and returns the signed transaction as a hex string (via a Promise—if you are new to JavaScript, we would encourage you to read more about Promises, as they allow the return of data at some point in the future when it is computed).
  • ethers.wallet.getBalance will give us the ETH balance of a wallet address.

Web3.js has a similar package within the web3.eth module called web3.eth.accounts. However, in the documentation for this package, it is called out: “This package has NOT been audited and might potentially be unsafe. Take precautions to clear memory properly, store the private keys safely, and test transaction receiving and sending functionality properly before using in production!”

How should I determine whether to use web3.js or ethers.js in my decentralized application? What is the difference between the two?

First off, if you are creating a boilerplate application or completing a tutorial, use whatever that boilerplate or tutorial recommends—whether that is web3.js or ethers.js. That will make your life easier and flow better with the tutorial. Be sure to use the version of web3.js or ethers.js specified in the tutorial. There are a lot of tutorials out there that have not been updated, so do not assume that you can use the most up to date version of the library unless the tutorial specifies that.

If you are building an application from scratch and determining which library you want to use, we have adapted a software evaluation process that Andres Canal used in his article “Using Quill,js to Build a WYSIWYG Editor for your Website” to evaluate which text editor to use.

The following is a series of nine questions that you, the reader, should ask yourself as part of determining which library might be best for you, with some context and information to help you answer it.

1.) How important is the popularity of the library?

To use Andres Canal’s definition,

“A popular project on Github means exactly what you expect it to. Namely, that there are lots of people questioning, contributing, and supporting it. This activity tends to result in more reliable software. You can check the popularity of any project by looking at how many stars it has, how many issues are opened, how many pull requests are pending, and how many contributors worked on the project.”

Web3.js has nearly 8,800 stars by the time of writing this blog, while ethers.js has almost 1,500. Web3.js is used by 51,300 repositories on GitHub, compared to 18,500 for ethers.js. Web3.js has been around longer, which is one of the reasons that web3.js is the more popular library.

2.) How important is the maintenance of the library?

We want to use libraries that are updated frequently, so that bugs are squashed and new features are added. Though it is not perfect, looking at a month (or two) of commits, closed issues, active issues, and the number of maintainers over that time period can give a sense of the strengths and weaknesses of an open source project. This also reveals patterns of maintenance, giving some insight to the user of a library when updates and bug fixes are generally addressed, which can be used as a proxy metric for maintenance of the library. Look at the monthly pulse for the libraries (web3.js / ethers.js) on GitHub to see the statistics.

Ethereum JavaScript Libraries: web3.js vs. ethers.js (Part I)

The number of commits and closed issues completed by the single maintainer of ethers.js, Richard Moore, is impressive and he should be applauded. Web3.js has 12 maintainers, and three individuals completed almost all of those commits. There is not a clear winner here, but in choosing the library, being aware of these statistics can help you determine what matters most to you in terms of maintenance, and prioritize the library that meets your needs.

3.) Who is responsible for the development of the library and how many projects use it?

Web3.js is a project of the Ethereum Foundation, which is a non-profit organization dedicated to research and organization of protocol level development. Ethers.js was created to create “a complete, simple, and tiny library – it is a replacement for web3 and ethereum.js”. Developed by Richard Moore, ethers.js is powered by his work in creating and maintaining the library.

While some projects have publicly stated which library they use, we felt that showing the data would allow us to show that both are very popular. Check out the web3.js and the ethers.js dependency graphs to explore which library the projects you trust use, or, if they use / support both libraries.

Ethereum JavaScript Libraries: web3.js vs. ethers.js (Part I)

4.) How important is it that the library has tests?

If having pre-written tests are important for your project, ethers.js historically has been the winner. At the time of writing, Ethers.js previously had clear documentation of their tests on their Github for version 3.0 release, but that documentation has not yet been updated with the version 5.0 release. Web3.js lacks comparable testing documentation. If the testing documentation is updated in the upcoming weeks, ethers.js will maintain its position as having better tests and testing documentation. The jury is out as of today because it appears that the ethers.js testing suite has not been updated as of yet.

5.) How important is the number of downloads of the library?

Because web3.js has been around longer, it has more downloads (14,703,432 as of May 20) than ethers.js (8,500,336 as of May 20), but when we look at weekly downloads, ethers.js (184,798 as of May 20) has surpassed web3.js (175,661 as of May 20) in downloads and is currently the more frequently downloaded library. Ethers.js has more downloads over the more recent timeframe, but web3.js has more downloads overall.

6.) How important is web performance?

If web performance is very important to you, the assumption is that ethers.js is the more performative library. The ethers.js library claims to be 284 kb uncompressed, while on NPM it is listed at 3.5 MB unpacked. Web3.js which is at least an order of magnitude larger, at 10.6 MB unpacked. Given that ethers.js is smaller than web3.js, the line of thinking is that for application using ethers.js will have faster load time than the same application that would use web3.js instead. This is because whichever library is used, it will have been loaded along with other assets that are part of the web application. We have not tested the load time of identical applications that are identical except for using web3.js or ethers.js, so take this point with some skepticism. If those extra MB do make a difference in your application, ethers.js is the smaller library.

7.) How important is the quality of the documentation?

Quality of documentation is a subjective measure, but one way to measure the quality of documentation is to read it and see how easily understandable the documentation is. Ideally, documentation is written so that a new user can grasp how to use the library. The documentation should also be organized to allow a more seasoned user to quickly find what they are looking for.

Web3.js has an extensive API reference that is incredibly useful. This is the strongest part of the documentation. The “Getting Started” material is short. An experienced user will likely enjoy this, but there is a lack of material for the new user of web3.js.

Ethers.js includes a “Getting Started” section, along with an expansive API reference. These are incredibly useful, and give ethers.js an advantage when compared to web3.js, particularly when it comes to newer developers in the Ethereum ecosystem. There are some incomplete sections within the documentation for ethers.js, which is not user friendly (parts of the Ethereum Basics section and the historically great “Cookbook” of common code samples that a developer would use is not up to date in 5.0 yet – you have to go back to the version 4.0 docs to find this incredibly useful section). Ethers.js also provides clear information about the advantages of using ethers.js.

Neither library has perfect documentation, so if documentation is important to you, spend some time exploring it to determine if there is enough information to allow you to implement the feature you are hoping to build.

8.) How important is the overall usage of the library?

While web3.js has been around longer and therefore has more downloads and GitHub stars, ethers.js is rising in popularity. Ultimately, it’s up to you to determine which aspects of each library matter most for your use case.

9.) How important is the license?

Depending on your specific use case, the open source software license may matter to you. Web3.js has an LGPLv3 license (as listed on NPM, but not on their GitHub repository) and ethers.js has an MIT license (as listed on their GitHub repository). More details on the licenses can be found by contacting a legal expert on this subject. However, Slava Todavchich provides an entertaining read on the subject in the article “Understanding open-source and free software licensing.”

Conclusion

As we mentioned at the beginning, both libraries are capable of getting the job done. Ethers.js has gained in popularity over the past two years, seeing increasing downloads and usage by projects. Web3.js has been the standard historically, and still owns a lot of developer-share.

Stay tuned for Part II where we will publish a follow-up tutorial to show you how to connect to the Infura API and send a translation using web3.js and ethers.js.

Huge thanks to Thomas Hay, Akua Nti, and Sean Brennan for their extensive contributions to this guide. For more Web3 tutorials, check out the Infura Blog and ConsenSys Academy.