Web3.js – How to Retrieve Past Events from a Contract

eventsweb3js

I use the following JS code to get notified of Solidity events and it works well for incoming new events:

myContract.myEvent().watch((error, result) => {
  if (error)
    console.log('Error in myEvent event handler: ' + error);
  else
    console.log('myEvent: ' + JSON.stringify(result.args));
});

I would like to use the same code for initializing the JS app on startup. e.g. I start the JS app on block 100 but there were already some events fired at block 20 and 30. These two past events are not being processed with the code above. As alternatives, I also tried via

myContract.myEvent((error, result) => {

and

myContract.myEvent({fromBlock: 0, toBlock: 'latest'}, (error, result) => {

Still these two options don't give me past events.

Best Answer

Seeing as there isn't a detailed updated answer:

As @pors mentioned, web3.js has a getPastEvents function. You can have it run at startup, using a syntax like:

myContract.getPastEvents('MyEvent');

The docs for this function are here. You can also filter by a specific topic, set a range of blocks to check, and more. Here's an expanded example, taken straight from the docs linked above:

myContract.getPastEvents('MyEvent', {
    filter: {myIndexedParam: [20,23], myOtherIndexedParam: '0x123456789...'}, // Using an array means OR: e.g. 20 or 23
    fromBlock: 0,
    toBlock: 'latest'
}, function(error, events){ console.log(events); })
.then(function(events){
    console.log(events) // same results as the optional callback above
});

This will not continue listening for events to the best of my knowledge. You could do this with events, however:

MyContract.events.MyEvent()

The function takes an object with parameters as an argument, much like getPastEvents(), see the docs here for more details. Based on the question, this would seem to be the best fit for the OP's particular use case.

(There is a similar function called allEvents for subscribing to all events from a particular contract - docs)

@pors also suggests using subscribe to get past events, and to continue to listen for new events. The docs are here. Note that you'll need to provide the topics you want to listen for. (Here's an explainer for event topics, you can get the topic for your event by hashing the event signature (eg Transfer(address,address,uint256) of the event with keccak256).