Listening to events lets your webpage know when something important happens on the blockchain. This helps your app update automatically without needing to refresh.
Listening to events (frontend) in Blockchain / Solidity
const contract = new ethers.Contract(contractAddress, contractABI, provider); contract.on('EventName', (param1, param2, event) => { // Your code here to handle the event console.log('Event received:', param1, param2); });
You need the contract address, ABI, and a provider (like MetaMask or Infura) to listen to events.
The callback function receives event parameters and an event object with extra info.
contract.on('Transfer', (from, to, amount, event) => { console.log(`Tokens moved from ${from} to ${to}: ${amount.toString()}`); });
contract.on('Approval', (owner, spender, value, event) => { console.log(`Approval: ${owner} allowed ${spender} to spend ${value.toString()}`); });
// Edge case: No events emitted yet // The listener will wait silently until an event happens. contract.on('NewItem', (itemId) => { console.log(`New item added with ID: ${itemId}`); });
once to listen only to the next event and then stop listening.// Edge case: Only one event emitted contract.once('Sold', (buyer, price) => { console.log(`Item sold to ${buyer} for ${price.toString()}`); });
This program connects to the Ethereum mainnet and listens for Transfer events on a token contract. When a transfer happens, it prints details about who sent tokens, who received them, the amount, and the block number.
import { ethers } from 'ethers'; // Example contract info (replace with real values) const contractAddress = '0x1234567890abcdef1234567890abcdef12345678'; const contractABI = [ 'event Transfer(address indexed from, address indexed to, uint256 value)' ]; async function main() { // Connect to Ethereum mainnet via default provider const provider = ethers.getDefaultProvider('homestead'); // Create contract instance const contract = new ethers.Contract(contractAddress, contractABI, provider); console.log('Listening for Transfer events...'); // Listen to Transfer events contract.on('Transfer', (from, to, value, event) => { console.log(`Transfer event detected:`); console.log(`From: ${from}`); console.log(`To: ${to}`); console.log(`Value: ${value.toString()}`); console.log('Event block number:', event.blockNumber); }); } main().catch(console.error);
Listening to events is fast and efficient because it waits for blockchain changes instead of checking repeatedly.
Time complexity is low since events are pushed to your app only when they happen.
Common mistake: forgetting to remove listeners when the component unmounts, which can cause memory leaks.
Use once if you only want to listen to a single event occurrence.
Listening to blockchain events lets your app react instantly to changes.
You need contract address, ABI, and a provider to listen to events.
Use contract.on for continuous listening and contract.once for a single event.
Practice
Solution
Step 1: Understand event listening in frontend
Listening to events means the app waits and reacts when blockchain data changes.Step 2: Identify the purpose of event listening
The main goal is to update the app instantly when something happens on the blockchain.Final Answer:
To react instantly when something changes on the blockchain -> Option CQuick Check:
Listening to events = instant reaction [OK]
- Confusing event listening with sending transactions
- Thinking event listening creates contracts
- Mixing event listening with mining blocks
Transfer using ethers.js?Solution
Step 1: Recall ethers.js event listening methods
Usecontract.onto listen continuously to events.Step 2: Match method to event name
For event 'Transfer', the syntax iscontract.on('Transfer', callback).Final Answer:
contract.on('Transfer', callback) -> Option DQuick Check:
Continuous listening = contract.on [OK]
- Using contract.once for continuous listening
- Using non-existent methods like listen or watch
- Confusing method names
contract.once('Approval', (owner, spender, value) => {
console.log(`Owner: ${owner}`);
console.log(`Spender: ${spender}`);
console.log(`Value: ${value}`);
});
// Event emitted: Approval('0xabc', '0xdef', 100)What will be printed to the console?
Solution
Step 1: Understand contract.once behavior
contract.once listens for the next single event and runs the callback once.Step 2: Match event parameters to callback
The event emits Approval('0xabc', '0xdef', 100), so owner='0xabc', spender='0xdef', value=100.Final Answer:
Owner: 0xabc\nSpender: 0xdef\nValue: 100 -> Option AQuick Check:
contract.once prints event data once [OK]
- Swapping owner and spender values
- Thinking contract.once never prints
- Missing the value parameter in output
Deposit event:contract.on('Deposit', (user, amount) => {
console.log(`User ${user} deposited ${amount}`);
});But your app never logs anything even though deposits happen. What is the most likely mistake?
Solution
Step 1: Check event name and ABI
If the event name is wrong or missing in ABI, the listener won't trigger.Step 2: Verify other common issues
Provider connection and import errors usually cause runtime errors, not silent no logs.Final Answer:
The event name 'Deposit' is misspelled or does not exist in ABI -> Option AQuick Check:
Correct event name in ABI = logs appear [OK]
- Assuming contract.once listens continuously
- Ignoring ABI event definitions
- Not connecting provider causes errors, not silent failure
Transfer event but only react to transfers where the from address is your wallet address 0x123. Which approach correctly filters these events using ethers.js?Solution
Step 1: Understand event filtering in ethers.js frontend
Direct filtering by event parameters incontract.onis not supported; filtering must be done inside the callback.Step 2: Choose correct method to filter by 'from'
Usecontract.on('Transfer', callback)and inside callback check iffrom === '0x123'.Final Answer:
contract.on('Transfer', (from, to, amount) => { if (from === '0x123') { /* react */ } }) -> Option BQuick Check:
Filter inside callback for specific addresses [OK]
- Trying to filter events by passing object to contract.on
- Using contract.once for continuous filtering
- Using non-existent filter chaining methods
Ready to prove it?
Pass the test and this pattern moves unknown
