1

The documentation is sparse, and the examples all mix async, arrow callbacks, and promises. One problem I've run into is while subscribing to an event, I can't seem use asynchronous syntax within or outside the method. There is also odd behavior in the way it returns data that could be affecting this. The method not only is used to lookup events, but also to listen to them in the future.

The documented way to subscribe to an event in Web3 1.0 (https://web3js.readthedocs.io/en/v1.2.0/web3-eth-contract.html#events):

myContract.events.MyEvent({
    filter: {myIndexedParam: [20,23], myOtherIndexedParam: '0x123456789...'}, // Using an array means OR: e.g. 20 or 23
    fromBlock: 0
}, function(error, event){ console.log(event); })
.on('data', function(event){
    console.log(event); // same results as the optional callback above
})
.on('changed', function(event){
    // remove event from local database
})
.on('error', console.error);

It works, but for production most people will probably want to do other things first. I need to listen to the current block to pass it into the event subscription so I can get the last ten blocks. After the data for the initial event query comes back, I need to fetch the current nonce of my wallet, and then iterate over the returned addresses to then sign them. After that, it becomes a passive listener, and so I set scriptHasBeenLoaded to true so that new events coming in take a different logical path.

Here is my current code:

getBlockNumber()

function getBlockNumber() {
    web3.eth.getBlockNumber().then((result) => {
        startingBlock = result
        console.log('*** Starting Block is', startingBlock, '***')
        startListening()
    })
}

function startListening() {
contract.events.Approval({
            fromBlock: startingBlock - 10,
            toBlock: 'latest'
        },
        (error, events) => {
            if (error) { console.log("*** Error Retrieving Addresses ***") }
            subscriberAddresses.push(events.returnValues.src)
            if (scriptHasBeenLoaded === true) {
                retrieveApprovals()
            }
        })
        getNonce()
}

function getNonce() {
    web3.eth.getTransactionCount(account, 'pending').then((result) => {
        console.log('*** Initial Nonce is', result, '***')
        nonceCounter = result
        console.log('*** Listening for Approvals ***')
        ...theBusinessEndFunctions()
    })
}

How can I wait for the events to come back, and then fire getNonce()?

Everything I do seems to bork the script. Currently, getNonce() is just in line. The only work around I have is setTimeout, which works, but it is the anti-solution. :-(

Edit: getPastEvents is not a solution or workaround after further testing.

  • 1
    It appears you want to do three things: 1. retrieve events from previous ten blocks, 2. call getNonce, 3. subscribe to new events. For the first you can use getpastevents. – Ismael Jul 29 at 19:26
  • I was hoping to use Contracts.events.MyEvent for speed and redundancy reasons, but this might be the only out using latest-latest. I had trouble with this method as well, but I definitely prefer the promise over the callback I can't seem to manager. – TrumpPaiPence Jul 29 at 19:39
  • After further testing, getPastEvents can't be parsed, and filters can't be used because it is not indexed what I'm looking for. There is some bug. You can log the results just fine, but you can't access them, at least in the expected manner. – TrumpPaiPence Jul 30 at 8:33
1

You could create an async function, put all you code inside and await for the individual requests results:

async function myLogic() {

    var startingBlock;
    await web3.eth.getBlockNumber()
        .then((number)=>{
            startingBlock = number;            
        });


    await  contract.getPastEvents('Approval',{
            fromBlock: startingBlock - 10,
            toBlock: 'latest'
            },
        (error, events) => {...})


    await  web3.eth.getTransactionCount(account, 'pending').then((result) => {...})
    // some other logic
}

myLogic()

Hope this helps

  • This works! getPastEvents is wonky when it comes to parsing. It works though in this context in terms of ordering. I went back to just subscribing. I suggest making a PR to the docs as an example for this. github.com/ethereum/web3.js/blob/v1.2.0/docs/… I heard that soon there will be comments available for examples and discussions of best practices. I will update this comment if I find something does not work as expected or it breaks. – TrumpPaiPence Jul 30 at 19:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.