Introduction
Trust me I have spent a lot of time trying to figure out how to listen/get events emitted by a smart contract. Now when I finally understand how to do this, I would like to share it with you.
In this article, we will understand how web3 can help us to read solidity smart contract events. Web3 provides various functions to get events from a smart contract. For understanding the functions easily, we will use the Transfer events emitted by the Tether USD contract.
To completely understand this article, you need to have some prior knowledge of smart contracts and web3.
Initial setup of Web3 Environment in Node.js
If you don’t wish to follow along you can skip this section.
Steps to setup-
- Create a new folder on your system
- Open this folder in your terminal
- Set up an empty node package manager by typing
npm init -y
in your terminal. - Create a file where all the code will be written,
web3EventInteraction.js
- Install web3 library using the command
npm i web3
in your terminal and then require it in our fileconst Web3 = require("web3")
- To interact with a contract you need its ABI and address. In this case, we need Tether USD’s ABI and address. To get this information, head over to this page, copy the ABI and address and assign it to a variable in web3EventInteraction.js
- We need one more essential thing to establish a connection with Ethereum Blockchain. For this, we will use Infura. Head over to Infura.io, create an account and then a project. Completing this you will have access to Infura Endpoints, which will allow web3 to communicate with Ethereum Blockchain. Now copy your Mainnet wss key and save it in a variable. Although it is recommended to store this in an environment file.
- Now create a web3 instance using
const web3 = new Web3(infuraWss)
- At last, create a contract instance by
const contractInstance = new web3.eth.Contract(tokenABI, tokenAddress)
And with this, we have completed our initial setup.
1. once
The once function of web3 subscribes for just one future event and unsubscribe after a successful event or error. Let us see how to use it.
This returns an output like
{
removed: false,
logIndex: 22,
transactionIndex: 7,
transactionHash: '0x29a5956703074b015e75e6a9d41b3278b8ade7608621be64685f62c18efdc510',
blockHash: '0x890ae8ebcee90ca580f4915068e0c4880a8296f38b5677d0a8ce9e7d2ed101d2',
blockNumber: 11398118,
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
id: 'log_76bb9576',
returnValues: Result {
'0': '0xea1c9b9799CF4ff42738F62a226DA590354A3F1e',
'1': '0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852',
'2': '600000000',
from: '0xea1c9b9799CF4ff42738F62a226DA590354A3F1e',
to: '0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852',
value: '600000000'
},
event: 'Transfer',
signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
raw: {
data: '0x0000000000000000000000000000000000000000000000000000000023c34600',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000ea1c9b9799cf4ff42738f62a226da590354a3f1e',
'0x0000000000000000000000000d4a11d5eeaac28ec3f61d100daf4d40471f1852'
]
}
}
2. events
The events function subscribes to an event, and as we know subscribe means listening to future events. Unlike once, events function keeps listening for events until stopped. Let us see how to use it.
This returns and keeps returning 😅, output like this
Listening Transfer events
{
removed: false,
logIndex: 6,
transactionIndex: 30,
transactionHash: '0xa523744218743ccf68a16cb2a571c4df351c7321fa365a07cd50fc738610bd26',
blockHash: '0xd05db5c802c0602d4c545f19c424b76eddd539a70126a1ccd4ade12b32d41fec',
blockNumber: 11398469,
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
id: 'log_308d6122',
returnValues: Result {
'0': '0xa7503F592FEa15F094069de68f38A08E36058d41',
'1': '0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852',
'2': '1982475198',
from: '0xa7503F592FEa15F094069de68f38A08E36058d41',
to: '0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852',
value: '1982475198'
},
event: 'Transfer',
signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
raw: {
data: '0x00000000000000000000000000000000000000000000000000000000762a2bbe',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000a7503f592fea15f094069de68f38a08e36058d41',
'0x0000000000000000000000000d4a11d5eeaac28ec3f61d100daf4d40471f1852'
]
}
}
...
3. getPastEvents
The getPastEvents function is very simple, unlike the previous functions which listen for future events, this returns all the previous events raised. Let us see how to use this.
This returns output like this
Returns all the past events
[
{
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
blockHash: '0x979197b08d5eb4bb69744abe32cb76bccf7a57480f23401dfd0d45283c54ae34',
blockNumber: 11398497,
logIndex: 29,
removed: false,
transactionHash: '0xdbff85e6be3759d6337238fe71c1d43f68b6fda1ae6340c05e8e338642c3db21',
transactionIndex: 29,
id: 'log_ea2d4591',
returnValues: Result {
'0': '0x0796c90B6813eD7F41a004729F3f6bD8774a20E1',
'1': '0xc19D0c4c7Ef8825d3d2A1610B93f33cBa0dCa959',
'2': '201000000',
from: '0x0796c90B6813eD7F41a004729F3f6bD8774a20E1',
to: '0xc19D0c4c7Ef8825d3d2A1610B93f33cBa0dCa959',
value: '201000000'
},
event: 'Transfer',
signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
raw: {
data: '0x000000000000000000000000000000000000000000000000000000000bfb0440',
topics: [Array]
}
},
{
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
blockHash: '0x979197b08d5eb4bb69744abe32cb76bccf7a57480f23401dfd0d45283c54ae34',
blockNumber: 11398497,
logIndex: 30,
removed: false,
transactionHash: '0x33118f0c63eda1fe6e2b47d6c07996492e3da4ea9ab3ad3d33ce94c357e95126',
transactionIndex: 30,
id: 'log_87ad0b0a',
returnValues: Result {
'0': '0x8874B9842178f15EB039Ddf5a861C9cD160A907C',
'1': '0x94c40659F1D2adb598cCE9100b0F7D384B11c152',
'2': '5000000000',
from: '0x8874B9842178f15EB039Ddf5a861C9cD160A907C',
to: '0x94c40659F1D2adb598cCE9100b0F7D384B11c152',
value: '5000000000'
},
event: 'Transfer',
signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
raw: {
data: '0x000000000000000000000000000000000000000000000000000000012a05f200',
topics: [Array]
}
}
...
Conclusion
To summarise, web3 offers three functions to interact with smart contract events- once, events, getPastEvents. The once function listens for just one future event. Similar to once, events listen to future events but does not stop automatically, it keeps listening. And getPastEvents unlike the previous two functions do not subscribe for future events but returns all the past events.
All the functions and setup used in this article can be found here.
Thanks for your time. Claps 👏🏻 are appreciated.