Web3.js and ethers.js both offer developers the means to interact with Ethereum, enabling the deployment of smart contracts, interaction with the blockchain, and the creation of decentralized applications (dApps). But what sets web3.js and ethers.js apart? We compared web3.js and ethers.js so you don't have to.
Introduction: What is web3.js and ethers.js?
Web3.js and ethers.js are JavaScript libraries that play a pivotal role in Ethereum blockchain development. They enable developers to connect to the Ethereum blockchain, interact with smart contracts, and manage blockchain-related data. While web3.js has been around longer and is often considered the gold standard, ethers.js has shot up in popularity because of its simplicity, lightweight nature, and broader functionalities in specific areas.
Overview
Web3.js
Origins and Evolution: Developed by the Ethereum Foundation, web3.js has been the go-to library for Ethereum developers for several years. It serves as a wrapper for JSON RPC calls to Ethereum nodes, streamlining a wide range of blockchain operations.
Features and Capabilities: Web3.js provides a comprehensive set of modules, including web3.eth for interacting with Ethereum, web3.shh for the Whisper protocol, and web3.bzz for Swarm. It supports callbacks and promises, so asynchronous operations run smoothly from start to finish.
Ethers.js
Origins and Evolution: Richard Moore created ethers.js as a more user-friendly and modular alternative to web3.js. It prioritizes straightforwardness while maintaining robust functionality.
Features and Capabilities: Ethers.js offers a unified way to interact with the Ethereum blockchain, simplifying the interaction with smart contracts and wallets. It's built on promises and provides utilities for encoding/decoding information. So, that makes it highly efficient for modern JavaScript applications!
Web3.js vs ethers.js: Criteria
Installation and Setup
web3.js: Installation is done via npm. Setting up web3.js involves setting up a Web3 instance and connecting to an Ethereum node.
ethers.js: Likewise, it is installed via npm. It offers a somewhat easier setup, requiring only the creation of a provider to connect to Ethereum nodes.
API and Documentation
web3.js: Offers extensive documentation covering various modules. However, the API can be complex for beginners, with multiple ways to perform similar tasks.
ethers.js: Makes it easier for blockchain developers to understand and use. The documentation is well-organized, providing examples and explanations that are clear-cut.
Features and Functionality
Smart Contract Interaction: Both libraries allow for interacting with smart contracts. Web3.js uses the web3.eth.Contract class, while ethers.js utilizes the Contract class, providing a more streamlined interaction pattern.
Wallet Management: Ethers.js has an edge with its wallet management, allowing for easy creation, import, and management of Ethereum wallets.
Utilities: Ethers.js includes several utility functions for tasks like encoding/decoding data and handling BigNumbers, often with simpler interfaces than web3.js.
Performance and Size
web3.js: Known for being bulky, it can increase the bundle size of web applications, potentially affecting performance.
ethers.js: Designed to be lightweight, ethers.js has a smaller footprint, making it a preferred choice for performance-sensitive applications.
Community and Support
web3.js: With a longer history, web3.js has a larger community, offering extensive resources, tutorials, and support forums.
ethers.js: Despite being newer, ethers.js has a rapidly growing community. Its simplicity and ease of use have garnered a strong following.
Tatum makes building on Ethereum in JavaScript super easy.
For Beginners: ethers.js, with its simpler API and comprehensive documentation, is recommended for newcomers eager to start in Ethereum development.
For Complex Applications: web3.js may be preferred for projects requiring detailed control over blockchain interactions and those relying on specific Ethereum features not fully covered by ethers.js.
For Performance-Sensitive Applications: ethers.js, due to its lightweight nature, is ideal for web applications where performance is a critical factor.
Getting Started With web3.js & ethers.js
Installation and Basic Setup
Web3.js Installation:
Basic Setup: Initializing web3 with a provider (e.g., Tatum, local Ethereum node).
Ethers.js Installation:
Basic Setup: Creating a provider to connect to the Ethereum network and initializing ethers with it.
Popular API Endpoints in web3.js and ethers.js Libraries
Web3.js API
web3.eth.Contract: Used for deploying new smart contracts to the blockchain and interacting with existing ones. It enables calling and sending transactions to contract methods and listening for events.
web3.eth.accounts: Manages Ethereum account creation, import, and export. It includes functionalities for generating wallets, signing transactions, and encrypting account information for secure storage.
web3.eth.sendTransaction: Allows sending Ether from one account to another or to a contract. It supports specifying transaction details such as gas limit, gas price, and nonce.
web3.eth.subscribe: Allows subscribing to various events on the Ethereum blockchain, such as new block headers and pending transactions.
web3.utils: A collection of utility functions to aid with converting values, encoding data, and other common tasks.
web3.eth.accounts: The web3.eth.accounts contains functions to generate Ethereum accounts and sign transactions and data.
Ethers.js API
ethers.Contract: Provides a more straightforward approach to interacting with smart contracts, including reading contract state and executing transactions.
ethers.Wallet: Offers a simple interface for creating and managing Ethereum wallets, including signing transactions and connecting to a provider for sending transactions.
ethers.providers: Interfaces for connecting to Ethereum nodes through various providers (e.g., JsonRpcProvider, WebsocketProvider), enabling interaction with the Ethereum network.
ethers.utils: Contains utility functions for tasks such as encoding and decoding data, hashing, and handling big numbers.
ethers.provider.getBalance: Retrieves the balance of an account, similar to web3.js but often considered more user-friendly.
ethers.provider.getTransactionCount: Gets the number of transactions sent from an address, often used for nonce management in transaction sending.
ethers.Signer: Abstracts the concept of an Ethereum account/signer, providing methods to sign messages and transactions, and to send transactions.
ethers.provider.getGasPric : Fetches the current gas price, similar to web3.js, aiding in estimating transaction costs effectively.
ethers.provider.getNetwork: Returns the network information the provider is connected to, such as the network name and chain ID.
These API endpoints represent the core functionalities offered by web3.js and ethers.js. Whether you are managing accounts, deploying smart contracts, or querying blockchain data, these libraries equip you with the necessary tools to build robust and scalable decentralized applications.
[.c-box-wow_wrapper][.c-box-wow][.c-wow-heading]JavaScript Blockchain Development Made Easy with Tatum[.c-wow-heading][.c-text-center]Working on blockchain network interactions can be tedious and complicated. Our API interface is designed to make the whole process as simple as possible. Whether you are a blockchain pro or just getting started, Tatum offers a way to build Ethereum solutions fast without getting bogged down by the protocol's complexities.[.c-text-center][.c-box-wow][.c-box-wow_wrapper]
Working with Smart Contracts
Deployment and Interaction
web3.js: Use web3.eth.Contract for deploying and calling contract methods.
ethers.js: Utilize the Contract and ContractFactory classes for seamless smart contract interactions.
Wallet Interaction and Transaction Management
Creating and Managing Wallets
web3.js: Generating accounts and importing wallets using the web3.eth.accounts module.
ethers.js: Simplified wallet creation and management with the ethers.Wallet class.
Sending Transactions
Sending Transactions with web3.js
To send a transaction using web3.js, you typically need to specify the sender's address, the recipient's address (or contract address if interacting with a contract), the amount of Ether to send (if applicable), gas limit, gas price, and nonce. The nonce is a count of the number of transactions sent from the sender's address, which is required to prevent transaction replay attacks.
To send a transaction using Tatum with the code below, you will need your API key. If you are already using Tatum, you can find it here.
Sample Code:
In this example, web3.eth.getTransactionCount is used to fetch the current nonce for the sender's address. The transaction is then defined, including the gas limit and the max priority fee per gas (part of EIP-1559). The transaction is signed using the sender's private key and broadcasted to the network.
Sending Transactions with ethers.js
Ethers.js massively simplifies the process of sending transactions and handling gas prices and nonces, abstracting away some of the complexities and providing a more intuitive interface. You can copy your Tatum API key here.
Sample Code:
In this ethers.js example, the wallet.sendTransaction method is used, which automatically handles the nonce for the sender. The transaction includes the recipient's address, value, gas limit, and maxPriorityFeePerGas. Ethers.js takes care of signing the transaction with the wallet's private key and broadcasting it to the network.
Handling Blockchain Data
Both libraries provide functionalities to fetch blockchain data similarly. You can use specific functions like getBalance to retrieve particular data, such as the native ETH balance of the wallet. We will show you how to use these libraries for fetching chain data.
Fetching Ether Balance with web3.js
In web3.js, the web3.eth.getBalance function is used to retrieve the balance of an account, returned in wei. This balance can be converted to Ether or other denominations using web3.utils.fromWei. Again, you can find your Tatum API key here.
Sample Code:
This example demonstrates connecting to the Ethereum mainnet using Tatum as a provider, though you could substitute this with any Ethereum node provider URL. After fetching the balance in wei, it converts the balance to Ether for a more readable output.
Fetching Ether Balance with ethers.js
As mentioned earlier, ethers.js simplifies the process with a slightly more abstracted interface. The getBalance method is available on the provider object and returns the balance in wei. Ethers.js includes built-in utilities to convert this balance into Ether.
Similar to the web3.js example, this code connects to the Ethereum mainnet using Tatum. The getBalance method retrieves the account's balance in wei, and ethers.utils.formatEther is then used to convert this balance into Ether.
Build your Ethereum app with Tatum - SDKs, APIs and everything else you need to finish your app quickly.
Overall, ethers.js and web3.js provide robust functionalities for developers building web3 apps. Integrating advanced blockchain features into applications, such as fetching all ERC-20 tokens and other standard tokens across multiple chains, as well as querying all NFTs (Non-Fungible Tokens) even from UTXO (Unspent Transaction Output) based chains, necessitates versatile and powerful developer tools.Tatum is one of the developer platforms that stands out in this regard, offering an extensive suite of tools designed to simplify blockchain development. You can explore more about Tatum's developer tooling capabilities here at docs..
Network and Provider Configuration
Setting Up Providers in web3.js
In web3.js, a provider is an abstraction of a communication layer to the Ethereum blockchain. Providers can be HTTP, WebSocket, IPC, or others, providing flexibility in how applications connect to the network.
Example: Using Tatum with web3.js
This example demonstrates how to set up an HTTP provider using Tatum’s endpoint. Replace YOUR_TATUM_API_KEY with your actual Tatum API KEY.
Fallback Providers
For redundancy and reliability, web3.js allows configuring multiple providers and attempts to use them in order if one fails. However, web3.js does not provide built-in support for automatically switching between these providers, necessitating custom logic to handle fallbacks.
Setting Up Providers in ethers.js
Ethers.js abstracts the provider connection more comprehensively, offering easy-to-use interfaces for connecting to Ethereum networks. It supports a variety of providers and can also be configured using JSON-RPC providers.
Example: Using Tatum with ethers.js
This snippet shows how to connect to the Ethereum mainnet (homestead) using Tatum with ethers.js. Replace YOUR_TATUM_API_KEY' with your actual Tatum API key.
Fallback Providers
Ethers.js offers a straightforward way to set up fallback providers using the FallbackProvider. This allows the application to automatically switch between providers if one becomes unavailable, enhancing reliability.
In this example, the FallbackProvider takes an array of providers, attempting to connect through them in sequence. This ensures that your application remains connected even if one provider fails.
[.c-box-wrapper][.c-box][.c-text-center]If you need help with any of the terms, check out our Crypto Glossary.[.c-text-center][.c-box][.c-box-wrapper]
Security and Best Practices
Key Management
Best Practices
Use Environment Variables for Sensitive Data: Never hard-code private keys or sensitive information within your application code. Instead, use environment variables to store such data. This approach minimizes the risk of exposing keys in source code repositories or web application files.
Example: Using .env files for storing private keys and accessing them via process.env.
Leverage Secure Key Management Services: For production applications, consider using key management services provided by cloud providers (AWS KMS, Azure Key Vault, Google Cloud KMS) or specialized services like HashiCorp Vault. These services offer secure key storage, rotation, and access control mechanisms.
Multi-Signature Wallets for Critical Operations: Use multi-signature wallets for operations involving significant asset movements. This practice requires multiple parties to sign a transaction before execution, adding an extra layer of security.
Signing Transactions with Web3.js & Ethers.js
Best Practices
Offline Signing: Whenever possible, sign transactions offline, especially when dealing with high-value transactions. Sure, it can be annoying, but you will thank us in the future! This method involves generating the transaction payload in an online environment, transferring it to an offline environment (cold wallet) for signing, and then broadcasting the signed transaction back in the online environment.
Example Concept:
Generate the transaction payload online.
Transfer the payload to an offline environment securely.
Sign the transaction offline and transfer the signed transaction back online for broadcasting.
Use Hardware Wallets for Signing: Hardware wallets provide a secure environment for storing keys and signing transactions, isolating them from vulnerable online environments. They are particularly recommended for managing keys in production or for accounts holding significant assets.
Validate Transactions Before Signing: Always validate transaction details, such as the recipient address and amount, before signing. This precaution helps prevent man-in-the-middle attacks and malicious interactions with contracts.
Implement Rate Limiting and Monitoring: Implement rate limiting for transaction signing requests and monitor for unusual activity. This strategy can help detect and prevent abuse or compromise.
Example Integration with Hardware Wallets: Most hardware wallets come with their own libraries or are compatible with general-purpose libraries such as ethers.js or web3.js. Transactions are prepared within the application, sent to the hardware wallet for signing, and then the signed transaction is broadcast to the network.
Environmental Best Practices for Web3.js & Ethers.js
Regular Security Audits: Conduct regular security audits of your codebase and dependencies to identify and mitigate vulnerabilities.
Keep Dependencies Updated: Regularly update your project's dependencies to incorporate security patches and reduce the risk of exploits.
Performance, Size, and Optimization
When comparing the web3.js and ethers.js libraries for use in your web application, the bundle size and number of dependencies are crucial factors to consider for optimizing performance and maintainability. Here's a comparative look at Tatum, web3.js, and ethers.js based on these criteria:
Bundle Size
web3.js: With a bundle size of 622.7 KB, web3.js is the larger of the two. Despite its larger footprint, it's widely appreciated for its comprehensive coverage of Ethereum's functionalities.
ethers.js: Ethers.js sits at a middle ground with a size of 359.9 KB. It's preferred for its balance between a rich feature set and a more moderate impact on application size.
Dependencies
web3.js: With 16 dependencies, web3.js requires more external packages, reflecting its broad feature set and the complexity of its operations.
ethers.js: Ethers.js has 7 dependencies, indicating a leaner approach compared to web3.js but with sufficient functionality for most development needs.
Evaluation
Both web3.js and ethers.js are excellent choices for developers, each offering distinct advantages. Web3.js is particularly well-suited for developers seeking extensive Ethereum blockchain capabilities out of the box, despite its larger bundle size and higher number of dependencies. This makes it a go-to for projects where comprehensive blockchain interaction is a priority.
Ethers.js, on the other hand, strikes a balance between functionality and efficiency, offering a robust set of features with a smaller footprint. Its moderate bundle size and lower dependency count make it an appealing choice for projects aiming for performance without significantly compromising on capabilities.
But we have something even better for all blockchain devs!
Tatum Compared to Both web3.js and ethers.js!
At 155.6 KB, Tatum boasts the smallest bundle size among the three, making it an attractive option for developers looking to build lightweight applications without compromising functionality.
Tatum has the fewest dependencies, only 3, highlighting its streamlined nature and potentially simplifying integration and update management.
Advanced Features and Utilities
Utility Functions: Encoding/decoding data, BigNumber operations, and address validation.
Event Listeners: Setting up event listeners for smart contract events.
Tatum stands out as an intriguing option, especially for projects prioritizing efficiency and ease of maintenance. Its minimal bundle size and very low dependency count can significantly benefit applications where performance is critical and simplicity in managing updates and dependencies is valued.
In summary, the choice between Tatum, web3.js, and ethers.js should be guided by your project's specific requirements, including desired functionalities, performance considerations, and ease of maintenance. Each library offers unique strengths, making them well-suited to different use cases in the diverse landscape of blockchain application development.