Overview
Interacting with Ethereum and EVM-compatible blockchain networks from application code requires a library that abstracts the low-level JSON-RPC protocol into usable developer interfaces — querying on-chain data, constructing and signing transactions, interacting with smart contracts, and monitoring blockchain events. ethers.js and web3.js are the two dominant JavaScript/TypeScript libraries that provide this abstraction, with ethers.js now the preferred choice for most new development due to its cleaner API design, better TypeScript support, and more maintainable codebase.
The practical applications of ethers.js and web3.js in the systems we build span several distinct use cases. Portfolio tracking systems that need to read on-chain wallet balances and token positions across Ethereum mainnet and EVM sidechains. DeFi integrations that interact with DEX contracts to read prices, liquidity pools, and routing data. Trading systems that monitor on-chain activity as alternative data signals. NFT and token management systems that need to read, transfer, and monitor ERC-20 and ERC-721 tokens. And the wallet connectivity that web3 applications use to authenticate users and request transaction signatures from browser wallets like MetaMask.
These are not blockchain development projects in the sense of smart contract development — we use ethers.js and web3.js as the connectivity layer that reads from and writes to existing deployed contracts and chain infrastructure, integrating blockchain data into traditional application architecture rather than building on-chain logic.
We build ethers.js and web3.js integrations for portfolio tracking systems, trading data infrastructure, DeFi analytics, and web3 application frontends that need reliable, well-structured blockchain connectivity.
What ethers.js and web3.js Development Covers
Provider configuration and connection management. The entry point for all ethers.js and web3.js operations is the provider — the connection to the blockchain node that serves RPC requests. Provider selection and configuration determines the reliability, latency, and rate limits of all blockchain data access.
JSON-RPC provider configuration: connecting to node infrastructure — Infura, Alchemy, QuickNode, or self-hosted nodes — with the appropriate API key management, request timeout configuration, and error handling. Provider failover: configuring multiple provider endpoints and failing over to backup providers when the primary is unavailable or rate-limited. The FallbackProvider in ethers.js that queries multiple providers and returns the result from the first that responds, or the QuorumProvider that requires agreement from multiple providers before returning a result — used in systems where data accuracy is critical and provider disagreements need to be detected.
WebSocket providers for real-time event subscription: the persistent WebSocket connection that receives push notifications for new blocks and contract events rather than requiring polling. WebSocket reconnection logic that re-establishes the connection and re-subscribes to events when the WebSocket drops — essential for long-running applications that cannot afford to miss events during connectivity gaps.
Network configuration for non-mainnet chains: configuring providers for Polygon, Arbitrum, Optimism, Base, BSC, Avalanche, and other EVM-compatible chains with the correct chain IDs, RPC endpoints, and native token configurations. Multi-chain provider management for applications that need to query multiple chains simultaneously.
Reading on-chain data. The ethers.js and web3.js operations that query the current state of the blockchain — balances, token holdings, contract state — without creating transactions.
Native token balance queries: reading ETH and other native token balances for wallet addresses. ERC-20 token balance queries using the standard ERC-20 ABI's balanceOf function: the balance of any ERC-20 token for any address, retrieved directly from the token contract. Multi-token balance aggregation for portfolio tracking systems that need to read positions across dozens of tokens simultaneously — batched using Multicall contracts that aggregate multiple balance queries into a single RPC call to reduce latency and API rate limit consumption.
Contract state reading: calling view and pure functions on deployed smart contracts through the ethers.js Contract interface with the contract's ABI. DEX price reads from Uniswap V2 and V3 pair contracts — the current price, the pool reserves, the tick data that determines price at specific amounts. Liquidity pool state: total value locked, current APY, reward rates. NFT ownership queries. Governance contract state.
Block and transaction data: reading block headers, transaction receipts, and transaction data for monitoring and analysis. Historical data queries for specific block ranges — the block-by-block analysis that trading data infrastructure uses to reconstruct on-chain activity over time.
ENS resolution: resolving Ethereum Name Service names to addresses and reverse-resolving addresses to ENS names — the human-readable name system that portfolio and analytics applications use to display wallet identities.
Event monitoring and indexing. On-chain events are the primary mechanism through which smart contracts communicate state changes. Monitoring events in real time and querying historical events is essential for applications that need to track on-chain activity.
Event subscription with WebSocket providers: subscribing to contract event topics and receiving push notifications when matching events are emitted. ERC-20 Transfer event monitoring for tracking token movements. DEX swap events for price and volume data. Lending protocol events for interest rate and liquidation monitoring.
Historical event queries with getLogs: querying the blockchain's event log for historical events matching specific contract addresses, event topics, and block ranges. Paginated historical event retrieval for large block ranges that exceed single RPC call limits. Block range chunking that retrieves historical events in manageable chunks while assembling the complete event history.
Event decoding: parsing the raw event log data — the indexed topics and the non-indexed data field — into the structured objects that application code works with. ethers.js's ABI-based event decoding that automatically parses event data using the contract's ABI definition.
Transaction construction and signing. For applications that need to write to the blockchain — not just read from it — ethers.js and web3.js provide the transaction construction and signing infrastructure.
Transaction parameter construction: building the transaction object with the correct recipient address, value, calldata, gas limit estimation, and gas price or EIP-1559 priority fee configuration. Gas estimation using estimateGas to determine the gas limit for contract interactions, with the safety margin that prevents out-of-gas failures.
EIP-1559 fee management: configuring maxFeePerGas and maxPriorityFeePerGas for EIP-1559 transactions on chains that support it, using current base fee data and priority fee estimates to construct transactions that are competitive without overpaying. Dynamic fee adjustment based on current network congestion.
Wallet integration for browser applications: the ethers.js BrowserProvider that wraps MetaMask and other injected wallet providers (EIP-1193), requesting account access, reading the connected account address, and requesting transaction signatures from the user's wallet without exposing private keys to the application. WalletConnect integration for mobile wallet connectivity.
Server-side transaction signing: the ethers.js Wallet class for applications that sign transactions server-side using stored private keys — the portfolio rebalancing system that executes on-chain trades, the automated DeFi strategy that interacts with protocols without user involvement. Private key security for server-side signing: environment variable storage, KMS integration, hardware security module connectivity.
Smart contract interaction. The ethers.js Contract and web3.js Contract objects that provide the typed interface for interacting with deployed smart contracts.
ABI-based contract instantiation: creating a contract interface from the ABI JSON that defines the contract's functions and events. TypeChain for generating TypeScript types from ABI definitions — the type-safe contract interface that prevents calling contract functions with incorrect argument types. ABI management for systems that interact with many contracts.
Multi-call batching: using Multicall2 and similar aggregator contracts to batch multiple contract read calls into a single RPC call — reducing the number of API calls required to read complex on-chain state, dramatically improving performance for portfolio tracking and analytics systems that read data from many contracts simultaneously.
Contract event filtering: creating event filters for specific contracts and event signatures, used for both historical queries and real-time subscriptions. Indexed event parameter filtering that narrows event queries to specific addresses or values.
On-chain data for trading systems. Blockchain data as an input to trading analysis and signal generation.
DEX price monitoring: reading prices from Uniswap, Curve, Balancer, and other DEX protocols as an alternative to centralised exchange price feeds. On-chain price data for tokens that primarily trade on DEXs rather than on centralised exchanges.
On-chain volume and flow analysis: tracking large transfers, DEX trade volumes, and the movement of significant on-chain capital as trading signals. Whale wallet monitoring for addresses with historically significant market-moving activity.
DeFi protocol analytics: TVL tracking, borrowing rates, liquidation monitoring — the on-chain data that DeFi analytics applications aggregate and present.
ethers.js vs web3.js
ethers.js is our default choice for new development. Its API is cleaner and more intuitive than web3.js — the separation between Provider (read-only connection), Signer (transaction signing capability), and Contract (contract interaction) is architecturally sound. TypeScript support is first-class, with the full type system covering providers, signers, transactions, and contract interactions. The library is well-maintained, actively developed, and has comprehensive documentation. ethers.js v6 is the current major version with further improved TypeScript types and a cleaner API than v5.
web3.js is used where the existing codebase or the specific library ecosystem requires it — integrations with systems that were built on web3.js, or where a specific plugin or extension only supports web3.js. web3.js v4 has significantly improved compared to earlier versions, but ethers.js remains our preference for new development.
viem is an increasingly popular alternative to both libraries — a TypeScript-first low-level library with excellent type safety and performance characteristics. For projects with demanding TypeScript requirements or that interact heavily with Foundry-based development tooling, viem is a strong alternative to ethers.js.
Integration With the Broader Stack
Rust backend integration. For systems where ethers.js provides the blockchain connectivity layer in a TypeScript/Node.js service and Rust provides the high-performance data processing, the integration is a well-defined API boundary: the Node.js service reads on-chain data and publishes to a message queue or REST API that the Rust service consumes. The ethers-rs library is an alternative for Rust-native blockchain connectivity where the entire data processing pipeline runs in Rust — relevant for high-performance on-chain data indexing where Node.js throughput is a bottleneck.
Next.js and React frontends. Web3 application frontends built with Next.js and React use ethers.js or wagmi (a React hooks library built on viem) for wallet connectivity and on-chain data reading. The wallet connection flow — detecting injected providers, requesting account access, handling chain switching — implemented with the standard patterns that MetaMask and other wallets expect. Server-side rendering considerations for Next.js applications that mix server-rendered content with client-side wallet connectivity.
Portfolio tracking systems. ethers.js as the on-chain data layer in portfolio tracking systems that aggregate positions across wallets, tokens, chains, and protocols — alongside centralised exchange API connectivity (Binance, Coinbase) that handles CEX positions in the same portfolio view.
Technologies Used
- ethers.js v6 — primary Ethereum and EVM blockchain connectivity library
- web3.js v4 — legacy and compatibility blockchain connectivity
- viem — TypeScript-first EVM connectivity for demanding type-safety requirements
- wagmi — React hooks library for web3 frontend development
- TypeChain — TypeScript type generation from Solidity ABI definitions
- Multicall2 / Multicall3 — on-chain batching for efficient multi-contract reads
- Infura / Alchemy / QuickNode — hosted Ethereum node RPC providers
- WalletConnect — mobile and multi-wallet connection protocol
- ethers-rs — Rust-native Ethereum connectivity for high-performance applications
- Node.js / TypeScript — runtime environment for server-side blockchain connectivity
- React / Next.js — frontend framework for web3 application frontends
Blockchain Connectivity as a Data Source
For the systems we build, blockchain is primarily a data source — a distributed ledger that records asset ownership, protocol state, and on-chain activity in a form that ethers.js and web3.js make accessible to application code. The on-chain data that a portfolio tracker needs to show wallet positions, the DEX price data that a trading system uses as a signal, the token transfer events that a compliance system monitors — these are all queries against the blockchain's state, handled by the provider and contract interfaces that ethers.js provides.
Treating blockchain connectivity with the same engineering standards as any other data source integration — reliable connection management, correct error handling, appropriate caching, and monitoring for connectivity issues — produces blockchain data infrastructure that is dependable rather than fragile.
On-Chain Data, Integrated Into Your Application
ethers.js and web3.js connectivity built to production standards — with correct provider failover, efficient multi-call batching, robust event subscription with reconnection handling, and the TypeScript types that prevent contract interaction errors — provides the blockchain data layer that applications depending on on-chain data can rely on.