Transfer
event is used in a simple token smart contract to record and communicate token transfers between addresses:
transfer
function is called within the smart contract, the Transfer
event is emitted, generating the following Ethereum log entry:
address
— the address of the contract that generated this log.topics
— an array of topics associated with the log. Topics are indexed event parameters that can be used to filter logs.data
— the log data as a hexadecimal string. This contains the non-indexed event parameters.blockNumber
— the number of the block in which the log was created.transactionHash
— the hash of the transaction that generated this log.transactionIndex
— the index of the transaction within the block.blockHash
— the hash of the block that contains this log.logIndex
— the index of the log within the block. In this case, the log index is 531
.removed
— a boolean value that indicates whether the log was removed due to a chain reorganization.id
— a unique identifier for this log entry.Transfer(address,address,uint256)
).fetchLogs.js
, and add the following lines of code:
Web3
library, which is the primary library for interacting with Ethereum nodes. We then provide the Chainstack node endpoint, which is used to connect to the Ethereum Mainnet. The USDC token contract address and the Transfer
event signature are defined to be used in the log filter.
We create a filterOptions
object, which contains the necessary filter parameters, such as the starting and ending blocks (fromBlock
and toBlock
), the contract address, and the event signature. This object is used as input for the web3.eth.getPastLogs()
method, which fetches logs matching the filter options.
Upon successful retrieval of the logs, the function iterates through each log entry, decoding the log data using the Transfer
event ABI. The decoded log information is then printed to the console, showing the sender, recipient, and value of each USDC transfer.
web3.eth.getPastLogs()
to perform a one-time query to the Ethereum node to retrieve logs matching the given filters. The result is a collection of logs from the specified block range that match the filter criteria. This approach is useful for obtaining historical event data or performing a one-time analysis of contract events.
To monitor the logs in real time, we need to use the web3.eth.subscribe()
method. When we use the subscribe
method, we create an ongoing subscription to a specific event, such as logs, new block headers, or pending transactions. The Ethereum node pushes new data to the subscriber in real time whenever the subscribed event occurs.
This approach is useful for building event-driven applications that need to react to changes on the blockchain as they happen. To use the subscribe
function, we need to get the WSS endpoint of your Chainstack node.
subscribe
method available in the web3.js library to enable real-time monitoring of logs. The subscribe
method sets up a WebSocket connection with the Ethereum node, allowing for efficient and continuous updates on new events without the need for polling. In this specific example, the code creates a subscription to the ‘logs’ event, applying a filter to focus on the USDC token contract’s Transfer
events. Upon receiving a new log event matching the filter criteria, the callback function is triggered, processing and decoding the event data to extract valuable information about the USDC transfers occurring on the Ethereum network.
The code is also designed to automatically reconnect to the Ethereum node if the WebSocket connection is lost or interrupted. This is important to ensure that the script continues to monitor USDC transfers without manual intervention in case of connection issues.
The reconnection logic is implemented using the clientConfig
option when creating a new instance ofWeb3.providers.WebsocketProvider
. This option allows you to customize the behavior of the WebSocket client, allowing automatic reconnection attempts following the delay and maximum retries specified in the websocketOptions
.
lodash
to implement request throttling easily.fromBlock
parameter wisely. When retrieving historical event logs, be mindful of the fromBlock
parameter. It is often more efficient to start from a block that you know contains relevant events rather than querying from the genesis block.