Web3.js is an open source library of javascript built by the Ethereum foundation to allow end users to interact with an Ethereum node using HTTP, IPC, or WebSocket.
Events are like a notification generated by a smart contract to notify the client application of a specific occurrence. Events are logged into a data structure called log.
Events allow smart contracts to write data to logs which can be accessed later by the client application. This makes for cheaper storage as compared to storing data in smart contracts. Furthermore, it can be used in the front end to notify the user when a transaction is completed.
pragma solidity ^0.5.0;contract SaveName {event Save(address indexed _from, bytes32 indexed _name, uint _value);function saveName(bytes32 _name) public payable {emit Save(msg.sender, _name, msg.value);}}
As we can see in the code above, we create an event and then emit (fire) it during a function call. When this function is called, a transaction is initiated, and the event is fired. If the transaction hash is searched on Etherscan.io, we can see a log tab containing the data (msg.send
,_name
, and msg.value
) saved by the event into the log.
Note: To read more about events, click here.
Smart contracts emit events as mentioned above, but we first need to connect to a smart contract to listen to certain events. The web3.js library provides an eth
package to interact with smart contracts. This package further contains a contract object with the functions required to interact with a smart deployed on the Ethereum network.
The functions need some arguments to interact with the required smart contracts successfully. The required arguments are as follows:
Application binary interface (ABI): The ABI of a smart contract can be taken from Etherscan.io through the list of ERC 20 tokens and by selecting a token. Go into the detail of that token and select the contract tab. There, we can find the ABI.
Address: The address of the smart contract can be taken from the same page where we retrieved the ABI. Scroll up, and the address will be written under "Profile Summary" in front of the "Contract."
We use tokens because the tokens are basically smart contracts deployed on the Ethereum Virtual Machines (EVM).
Note: We also need to establish a connection to the Ethereum node. For that, we use Infura API. The API key is provided here for testing purposes only. To read how to get an Infura API key, click here.
The following code shows how we can fetch past events fired by a specific smart contract:
const Web3 = require('web3') const jsonRpcURL = 'https://mainnet.infura.io/v3/917c4f75f17a4e28b78263cddd8f1b46' const web3 = new Web3(jsonRpcURL) const abi = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_upgradedAddress","type":"address"}],"name":"deprecate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"deprecated","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_evilUser","type":"address"}],"name":"addBlackList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"upgradedAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maximumFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_maker","type":"address"}],"name":"getBlackListStatus","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowed","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"who","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newBasisPoints","type":"uint256"},{"name":"newMaxFee","type":"uint256"}],"name":"setParams","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"issue","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"redeem","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"basisPointsRate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isBlackListed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_clearedUser","type":"address"}],"name":"removeBlackList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MAX_UINT","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_blackListedUser","type":"address"}],"name":"destroyBlackFunds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_initialSupply","type":"uint256"},{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_decimals","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Issue","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newAddress","type":"address"}],"name":"Deprecate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"feeBasisPoints","type":"uint256"},{"indexed":false,"name":"maxFee","type":"uint256"}],"name":"Params","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_blackListedUser","type":"address"},{"indexed":false,"name":"_balance","type":"uint256"}],"name":"DestroyedBlackFunds","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_user","type":"address"}],"name":"AddedBlackList","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_user","type":"address"}],"name":"RemovedBlackList","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"}] const contractAddress = '0xdAC17F958D2ee523a2206206994597C13D831ec7' // Connecting to the smart contract const contract = new web3.eth.Contract(abi, contractAddress) async function GetLatestBlockNUmber() { currentBlock = await web3.eth.getBlock("latest"); return currentBlock.number } async function GetPastEvents() { var event = await contract.getPastEvents( 'AllEvents', // Feel free to change this to 'Transfer' to see only the transfer events { // We fetch the latest block number and subtract 100 to ensure that // we get the events from the last 100 blocks. fromBlock: await GetLatestBlockNUmber() - 100, toBlock: 'latest' } ) console.log('Total events: ', event.length) console.log(event[event.length - 1]) } GetPastEvents()
The explanation of the code above is as follows:
Line 13: We retrieve the status of the latest block in the currentBlock
using latest
tag. The await
keyword pauses the function execution until the Promise is fulfilled.
Line 19: We call getPastEvents()
to retrieve events of all types within the last 100 blocks of the token as specified by the range given by fromBlock
and toBlock
.
Line 30: We print an event
to the console containing the transaction hash, to and from addresses, and the log where the data is saved by the event that was fired during the transaction.
Free Resources