iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

ethers.js

Ethers.js is the lightweight Ethereum library most dapps use to talk to wallets and smart contracts from the browser or Node. It abstracts JSON-RPC, ABI encoding, BigInts, signing, and event listening. Pair it with a wallet provider (MetaMask, WalletConnect) for in-browser dapps or a JSON-RPC URL for backend reads.

Connect a wallet, call a contract, listen for events

EXAMPLE
import { ethers } from 'ethers';

// 1) Get a provider
// Browser dapp via injected wallet (MetaMask / Coinbase Wallet)
const provider = new ethers.BrowserProvider(window.ethereum);
await window.ethereum.request({ method: 'eth_requestAccounts' });
const signer = await provider.getSigner();
const me     = await signer.getAddress();

// Backend / read-only
// const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);

console.log('connected as', me, 'on chain', (await provider.getNetwork()).chainId);

// 2) Build a contract instance from an ABI fragment
const erc20Abi = [
  'function balanceOf(address) view returns (uint256)',
  'function decimals() view returns (uint8)',
  'function transfer(address to, uint256 amount) returns (bool)',
  'event Transfer(address indexed from, address indexed to, uint256 value)',
];
const usdc = new ethers.Contract('0xA0b86991c6218B36c1d19D4a2e9Eb0cE3606eB48', erc20Abi, signer);

// 3) Read state — pure / view functions cost nothing
const [dec, bal] = await Promise.all([usdc.decimals(), usdc.balanceOf(me)]);
console.log('USDC balance:', ethers.formatUnits(bal, dec));

// 4) Write — sends a tx, prompts the wallet for signature
const recipient = '0x000000000000000000000000000000000000dEaD';
const amount    = ethers.parseUnits('1.50', dec);          // BigInt
const tx        = await usdc.transfer(recipient, amount);
console.log('submitted', tx.hash);
const receipt = await tx.wait(1);                          // wait for 1 confirmation
console.log('mined in block', receipt.blockNumber, 'gas used', receipt.gasUsed.toString());

// 5) Subscribe to events in real time
usdc.on('Transfer', (from, to, value, event) => {
  if (from === me || to === me) {
    console.log('Transfer involving me:',
      ethers.formatUnits(value, dec), 'tx', event.log.transactionHash);
  }
});

// 6) Historical events with a filter (last 10k blocks)
const fromBlock = (await provider.getBlockNumber()) - 10_000;
const sent = usdc.filters.Transfer(me, null);              // I am the sender
const logs = await usdc.queryFilter(sent, fromBlock);
console.log(\`sent ${logs.length} transfers in the last 10k blocks\`);

// 7) Sign a plain message (for sign-in / SIWE)
const msg = 'Sign-in to Shop @ 2026-06-11T09:30:00Z';
const sig = await signer.signMessage(msg);
const recovered = ethers.verifyMessage(msg, sig);
console.log('recovered =', recovered, '== me?', recovered === me);

// 8) Handle chain switches without reloading
window.ethereum.on('chainChanged', () => location.reload());
window.ethereum.on('accountsChanged', (a) => console.log('account changed:', a[0]));

Why it matters

Always await tx.wait() before assuming a state change happened — the transaction hash means "submitted", not "succeeded". On L1 a single confirmation is usually enough for UI; for high-value transfers prefer two or three confirmations, and bake reorg awareness into your back-end indexing.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
import { ethers } from 'ethers';
const provider = new ethers.JsonRpcProvider(rpcUrl);
const wallet = new ethers.Wallet(privateKey, provider);
const contract = new ethers.Contract(addr, abi, wallet);
console.log(await contract.balanceOf(wallet.address));
Try it Yourself »

Discussion

Loading…