4

On Web3.js/1.0 there is no watch() function for the contracts to retrieve events.

I have followed the following guide, web3.eth.Contract - Events - getPastEvents - example, and answer to retrieve emitted events.

  • event.watch(...) used to wait until a new event shows up and does not move on to the next instruction till watch is stopped.

In the following example if there is no event in between fromBlock and toBlock: 'latest' it returns [] and stops waiting for new events to show up right away, which was not case on when we are using watch().

Example-1 getPastEvents():

myContractInstance.getPastEvents('LogJob', {
    filter: {clusterAddress: [web3.eth.defaultAccount]},
    fromBlock: 1899162,
    toBlock: 'latest'
}, function(error, event){ console.log(event); });

Example-2 events.LogJob from web3.py guide: returns undefined

myContractInstance.events.LogJob({
    filter: {clusterAddress: [web3.eth.defaultAccount]},
fromBlock: 1899162
}, 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);

[Q] Is there any way to apply same approach like watch(); where if there is no event in between given fromBlock and toBlock: 'latest', then continue to watch and do not jump on to the next instruction.

Basically if an event returns []; I want the process keep watching new upcoming blocks and complete watching until the new event is emitted. Only solution comes to my mind is to make this call every 2 seconds until filter does not return [].

3

4 Answers 4

2

@Maxpeinas, that's correct, you have to use websocket provider in order to subscribe to events in web3.js 1.0 via myContract.events.MyEvent()

So, if you are using local TestRPC go with

const web3 = new Web3('ws://127.0.0.1:8545');

If you are using remote endpoint - change it to ws, for example - Infura already have working websocket endpoints for the main and the test networks, you can use them like this:

const web3 = new Web3('wss://ropsten.infura.io/ws');

I would guess that this will be the main 'problem' for developers which have used 0.2 with regular httpProvider and .watch(), since nowhere in the official web3.js 1.0 documentation for the event methods is not yet mentioned that you will need connect to websocket endpoint in order to subscribe for the EventEmitter.

If you are more experienced maybe you will be able to think of it, as the recommended provider in 1.0.0 docs is ws://127.0.0.1 instead of http://127.0.0.1, however there will be people that will wonder why their http event subscriber doesn't work.

Note: As opposed to myContract.events.myEvent(), you are able to use myContract.getPastEvents() with regular http provider with no problems, since it only fetches old logs and doesn't wait for new ones.

1

Edit: If you get undefined when you do contractInstance.events.YourEvent(.. then there is definitely a mistake in your code. Please double check you're using web3 1.0 and your contract is correctly instantiated. Beware: If your code runs within a browser and you ship it with web3 1.0 you might even have the 0.20.x version on your hands if it was injected by MetaMask. console.log(web3.version)

Original answer: contract.getPastEvents() looks only for - as the name tells us - past events. This means, it gives you all events from fromBlock to toBlock but after that, it stops watching.

If you want to continue watching like the .watch() from web3 0.20.x, then you need to do the following:

contractInstance.events.LogJob({
  filter: {clusterAddress: [web3.eth.defaultAccount]},
  fromBlock: 1899162,
  toBlock: 'latest'})
  .on('data', event => {
    console.log('new event:', event)
  })
  .on('changed', event => {
    console.log('event removed from blockchain:', event)
  })
  .on('error', error => {
   console.error(error)
  })

If you prefer the callback style, you can pass an optional callback parameter:

contractInstance.events.LogJob({
    filter: {clusterAddress: [web3.eth.defaultAccount]},
    fromBlock: 1899162,
    toBlock: 'latest'},
  (err, event) => {
    if (err) throw err
    console.log('new event:', event)
  }) 
  .on('changed', event => {
    console.log('event removed from blockchain:', event)
  })
  .on('error', error => {
   console.error(error)
  })

Official documentation

2
  • callback style gives following error: if (err) throw err | Error: The current provider doesn't support subscriptions: HttpProvider
    – alper
    Commented Sep 8, 2018 at 20:32
  • You need to use a WebsocketProvider instead: new Web3(new Web3.providers.WebsocketProvider('wss://...'))
    – haggis
    Commented Sep 8, 2018 at 22:40
0

was just checking the documentation, did you check this..http://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#contract-events

1
  • I have tried events.LogJob but it returns undefined. Please see my updated answer. @karts
    – alper
    Commented Jul 3, 2018 at 9:34
0

For events to work you need websocket provider i believe, http won't work with events, at least with catching new events, not sure about pastEvents. From your code i can't say if you are using one, so maybe it's worth checking. Do you get any errors?

2
  • I am not having any error related to http @Maxpeinas
    – alper
    Commented Jul 3, 2018 at 9:53
  • That's weird then, i was getting errors with events until i created new websocket provider instance just for events listening. If your contract is deployed on ethereum testnet (Ropsten, Rinkeby) you could still try infura ws provider to check it, wouldn't hurt i guess.
    – Maxpeinas
    Commented Jul 3, 2018 at 10:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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