2

I currently am using Oraclize in my contract and I make a call to a contract function from my front-end and don't want to continue onto the next call until the Oraclize function has returned. So I decided to use an event with a filter, and it works perfectly the first time, then on the next calls it doesn't actually wait for the Oraclize function to return again, it just takes the return value from the previous Oraclize function and uses that because its using the old logged event, and not waiting for the newest one.

This leads me to question why my filter is listening/uses the event emitted from the smart contract in the last call, instead of waiting on the new event to be called. It later returns the new Oraclize value if I don't use myEvent.stopListening() so I know Oraclize is still working after the first call.

My question is how do you only listen/react to the last event? Right now it's taking whatever event was fired before and being triggered off that.

Here's my front-end code watching the event: code

I've tried also using various combinations for the filter such as: {fromBlock: 'latest', toBlock:'latest} or {fromBlock: 'latest'}

neither actually work at all, they don't ever fire the first time, then if I call the function again they have the same problem and instantly fire on the previous logged event.

Can someone explain to me what 'latest' does, for I seem to have a bad understanding. Also if this makes any difference my Event call in my smart contract takes place in the __callback() from Oraclize, and my front-end watching code is placed in a callback where the user clicks a button and enters a number and sends the transaction. Is the placement inside a callback function causing this weird error?

Thanks for any help or understanding, I have gone through the documentation on both contract events and web3.eth.filters but have been unable to figure this out. Sorry for the massive wall of text.

TL:DR How do you get your watch() to only look for new event logs, not react to past event logs that were triggered? Thank you!

1

2 Answers 2

0

Modify the code as follows:

 var num=contractInstance.Result({},{fromBlock: 0, toBlock: 'latest' });
     num.watch(function(error,result){
 });

Here we are retrieving the events from block 0 and that is done by adding a fromBlock parameter to the currentblock by adding the toBlock parameter to the event.

6
  • Oh shoot, I changed the variable names and contract variable for the screenshot to make them easier to understand and mistyped and put contractInstance.watch() rather than num.watch() In my current code that does not work I am using num.watch() and not the contractInstance. I've found that whats its doing does make sense, because I am specifying it to watch for any logs from Block 0 to the latest block, and it works perfect first time, then second time etc. it automatically returns whatever the previous Oraclize call was.
    – savard
    Mar 8, 2018 at 5:37
  • @savard try fromBlock as latest..and remove toBlock Mar 8, 2018 at 5:43
  • I don't understand why fromBlock: 'latest', toBlock:'latest' does not work for watching for only the newest/last response. When I use that it never recognizes the event log and runs forever until I run the function again. Then it returns the last Oraclize call as well. Thank you however for your response @cmr , that was my bad. I'll edit the question screenshot, do you have any idea why it wouldn't 'work' if I am using the syntax correctly? (Technically it works, just not to how I need it to work). Thanks in advance!
    – savard
    Mar 8, 2018 at 5:43
  • @savard any updation Mar 8, 2018 at 5:58
  • yes, I just finished testing the fromBlock: 'latest, toBlock: 'latest' + 1 and it worked ! I think because my event returns from Oraclize function which returns 1 - 2 blocks in the future, so fromBlock: 'latest' was not catching it. Thank you so much! I've been struggling on this for the past 3 days and you inspired me to try that configuration.
    – savard
    Mar 8, 2018 at 6:06
2

If you are going to fetch events from 0 to latest, you will always get all the events that have happened. If you have committed data previously, and just start the watch from the given to and from Blocks, you will see that soon you will get everything that was committed.

try this:

var event = conInst.YourEventName({},{
     fromBlock:'latest', 
     toBlock:'pending'}, 
   function(error, result) {
    if (!error)
        console.log(result.args);
   });

This will give you that data that is just about to get mined. Problem with this is you probably do not have all the logs all the time (depending on who is interacting with your smart contract). But it surely gives you the earliest thing that is about to go on the blockchain.

Another way to do this in a full proof way is to filter them internally. Let's say you have a mapping from an ID to a struct, now for an ID you altered some data, now you will get both the old and the new for that same ID. So what you can do is pass the "blockNumber" in the event, so when you get the records, you loop through it and just see if for the same ID you have multiple, you take the highest blockNumber.

It is just the way I do it, but it is slow. You can go through some other way, but you get the idea.

1
  • And how to get all the events here if fromBlock: 0, toBlock: "latest" returns only the latest event?
    – Ruham
    Jan 14, 2019 at 18:20

Your Answer

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

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