Imagine building a website for a DeFi protocol. You connect a wallet via MetaMask, but balances don't load — an SSR hydration error because ethers.js accesses window, or an RPC node fails at the worst moment. From such cases, we've developed a workflow: use ethers.js v6 as the primary tool, web3.js v4 for legacy projects. Below, we break down typical patterns we apply in turnkey blockchain integration development. 5+ years of experience with EVM networks, 20+ integrations for startups and enterprise.
ethers.js v6 is 2-3 times better than web3.js v4 in bundle size and import speed: tree-shaking removes unused modules. Yes, web3.js v4 is rewritten in TypeScript, but ethers.js offers a cleaner API, native BigInt, and built-in ESM support. For a new project — definitely ethers.
How to choose between ethers.js and web3.js?
| Criteria | ethers.js v6 | web3.js v4 |
|---|---|---|
| Bundle size (min+gz) | ~80 KB | ~200 KB |
| Typing | TypeScript-first | TypeScript-native |
| BigInt | Native | Native |
| ESM/CJS | ESM only | Dual package |
| Community popularity | ~80% | ~20% |
| Event support | .on() + filters |
.events |
For new projects, we definitely recommend ethers.js v6: it's lighter, faster, has better typing. web3.js v4 remains relevant for migrating from older versions.
What does the integration work include?
We provide a full set:
- Requirements analysis and library selection.
- Designing the contract interaction layer (ABI, addresses, networks).
- Implementing data read/write, event subscription, error handling.
- Developing fallback providers for fault tolerance.
- Testing integration on test networks (Goerli, Sepolia).
- Documentation and access handover.
After completion, we guarantee stable operation — if issues arise within a month, we fix them free of charge.
How to ensure RPC fault tolerance?
Note: when one RPC node goes down, the application should instantly switch to another. We use FallbackProvider from ethers.js with weight and priority distribution. Configuration example:
import { FallbackProvider, JsonRpcProvider } from 'ethers'; const fallbackProvider = new FallbackProvider([ { provider: new JsonRpcProvider('https://rpc1.example.com'), priority: 1, weight: 2 }, { provider: new JsonRpcProvider('https://rpc2.example.com'), priority: 2, weight: 1 }, ]); We also handle errors via try-catch and log failures for monitoring.
Why is ethers.js v6 faster than web3.js v4?
Due to aggressive tree-shaking: ethers.js exports modules as separate ESM files, so the bundler removes unused parts. In web3.js v4, despite TypeScript, many functions are tied into a single module, increasing size.
ethers.js v6: key concepts
import { BrowserProvider, JsonRpcProvider, FallbackProvider, Contract, formatEther, parseEther, formatUnits, parseUnits, isAddress, getAddress, } from 'ethers'; // Server provider const serverProvider = new JsonRpcProvider(process.env.ETH_RPC_URL); // Client provider async function getWalletProvider() { if (!window.ethereum) throw new Error('Wallet not found'); const provider = new BrowserProvider(window.ethereum); const signer = await provider.getSigner(); return { provider, signer }; } // Fallback provider (multiple RPC) const fallbackProvider = new FallbackProvider([ { provider: new JsonRpcProvider('https://rpc1.example.com'), priority: 1, weight: 2 }, { provider: new JsonRpcProvider('https://rpc2.example.com'), priority: 2, weight: 1 }, ]); Working with contracts and events
const ERC20_ABI = [ 'function balanceOf(address owner) view returns (uint256)', 'function transfer(address to, uint256 amount) returns (bool)', 'function approve(address spender, uint256 amount) returns (bool)', 'function allowance(address owner, address spender) view returns (uint256)', 'event Transfer(address indexed from, address indexed to, uint256 value)', ]; // Read-only const tokenRead = new Contract(TOKEN_ADDRESS, ERC20_ABI, serverProvider); const balance = await tokenRead.balanceOf(walletAddress); // Write with signature const { signer } = await getWalletProvider(); const tokenWrite = new Contract(TOKEN_ADDRESS, ERC20_ABI, signer); const tx = await tokenWrite.transfer(recipientAddress, parseUnits('10', 18)); const receipt = await tx.wait(); // Event subscription const filter = tokenRead.filters.Transfer(null, walletAddress); tokenRead.on(filter, (from, to, value) => { console.log(`Received ${formatUnits(value, 18)} from ${from}`); }); // Historical events const events = await tokenRead.queryFilter(filter, fromBlock, 'latest'); web3.js v4
import { Web3 } from 'web3'; const web3 = new Web3(window.ethereum); const erc20Contract = new web3.eth.Contract(ERC20_ABI, TOKEN_ADDRESS); // Read const balance = await erc20Contract.methods.balanceOf(walletAddress).call(); // Write const accounts = await web3.eth.getAccounts(); const receipt = await erc20Contract.methods .transfer(recipient, web3.utils.toWei('10', 'ether')) .send({ from: accounts[0] }); BigInt and utilities
// BigInt serialization (JSON.stringify doesn't support it) const replacer = (_: string, value: unknown) => typeof value === 'bigint' ? value.toString() : value; // Address shortening function shortenAddress(address: string): string { return `${address.slice(0, 6)}…${address.slice(-4)}`; } // Block timestamp conversion async function blockToDate(blockNumber: number): Promise<Date> { const block = await serverProvider.getBlock(blockNumber); return new Date(Number(block!.timestamp) * 1000); } Common errors and solutions
- BigInt not serializable: use replacer for JSON.stringify.
- Wrong chainId: always check it matches the expected one on connection.
- RPC failure: set up FallbackProvider with multiple nodes.
- Nonce error: reconnect the wallet or manually increase nonce.
Integration timelines: basic (read + one event) — 1-2 days, full layer with multiple contracts, fallback, and history — 3-4 days. Cost is determined after analysis based on complexity. For an accurate estimate, contact us — we'll discuss your project and suggest the optimal solution.
When to order blockchain integration development?
If you are building a Web3 application — DeFi protocol, NFT marketplace, or corporate blockchain solution — it's important to properly organize the network interaction layer from the start. Errors in ABI, incorrect BigInt handling, lack of fallback providers lead to production failures and user dissatisfaction.
We take over the entire development cycle: from library selection and provider setup to implementing event subscriptions and testing on test networks (Sepolia, Mumbai). We work with EVM-compatible networks: Ethereum, Polygon, BNB Chain, Arbitrum, Optimism. Clients receive clean TypeScript code, documentation, and one month of technical support. Reach out to us — we'll evaluate your project and find the optimal solution within 1 business day.
Source: ethers.js v6 Documentation







