2

Let's say this is my smartcontract:

  event NewUser(
    address userAddress,
    uint amount
  );
  function addUser() public payable{
    require(msg.value <= maxValue && msg.value > 0);
    require(allowedValues[msg.value]);
    require(accountAmount() < 5);

    if (users[msg.sender] > 0) {
        userPullout(); //Remove senders data
    }

    userAddresses.push(msg.sender);
    partAmounts.push(msg.value);// This value doesn't get pushed before the event is finished
    users[msg.sender] = msg.value;

    emit NewUser(msg.sender, msg.value);//This is called to soon
}

This is my nodeJS file:

app.contract.events.NewUser({}, function(error, event){})
.on('data', function(event){
  io.emit('new user', event.returnValues);
}).on('change', function(event){
  io.emit('new user', event.returnValues);
})
.on('error', console.error);

If I log the partAmount array in web3 with a .call function, the old values before the event still get returned. This tells me that the event is fired too soon.

Is there anyway to call an event after the data is set?

EDIT: some more code.

const socket = openSocket('http://localhost:3000'); // subscribed to the socket server firing the events from node back-end
socket.on('new user', (event) => {
  console.log(event) // returns for example 7 which is CORRECT
  this.props.contract.methods.getCertainArray().call(this.props.contractObject, (err, res) => {
    console.log(res); // old data from before the event so if the previous array was [0, 6 , 6], this would still be returned NOTICE: no 7 in the array yet.
  });
})

NOTE: If i put a set timeout around the call function like this:

setTimeout(() => {
    this.props.contract.methods.getCertainArray().call(this.props.contractObject, (err, res) => {
      console.log(res); // old data from before the event so if the previous array was [0, 6 , 6], this would still be returned NOTICE: no 7 in the array yet.
    });
}, 5000);

It does return the right array, but it is not the way I want the script to run.

1

The problem is you are not waiting for the transaction to be mined before you .call to check for a result.

It goes:

  1. Sign and send a transaction. Get a transaction receipt.
  2. Transaction gets mined and the contract executes the instructions, in order.
  3. Block arrives with the confirmed transaction.
  4. Now you can call a function to see the effect.

Or, watch for an event, as your example JS appears to. Events don't arrive until the transaction is included in a block.

Hope it helps.

  • See thats expected behaviour, maybe it has something to do with the fact that im using truffle and ganache? That because of this the event gets fired because its not on a real blockchain? – jasper May 28 '18 at 15:55
  • Yes, it's expected, but no, events are not fired before mining. It is very unlikely any other explanation. You're doing the call before the transaction is mined. The first callback gives a transaction hash. That's not a confirmation of "mined". It's just an ack of the request. It's common to mistake that for mining confirmation. Have a look here: gist.github.com/xavierlepretre/88682e871f4ad07be4534ae560692ee6 – Rob Hitchens - B9lab May 28 '18 at 16:19
  • Ok so I still haven't managed to fix the problem so let met try to explain some more.. The data that comes out of the event is RIGHT, the problem is that the call function (that gets triggered by the event) after that still retrieves the OLD data. Ill upload some more code – jasper May 28 '18 at 18:55
  • You understand the expected mechanics and I understand your frustration. I don't think truffle is the likely culprit but you may have discovered something about ganache reporting the event before it has fully digested the state, or maybe even a caveat related to passing arrays around. That's a relatively new feature and usually not a good idea given the redundancy. If you think about it, when clients are informed about the rows on a blow-by-blow basis, there's no reason to ask for the whole array in one gulp. It doesn't explain why it seems to fail but it might explain why the issue exists. – Rob Hitchens - B9lab May 28 '18 at 20:15
  • Maybe someone can chime in with some insight to confirm that you're guaranteed to get the latest dynamic array immediately, with ganache. I would consider setting up a private node with geth just to see if the behavior is more like expected. In cases of disagreement, geth wins. – Rob Hitchens - B9lab May 28 '18 at 20:19
1

Now that I'm connected to the Ropsten testnet it does work as expected (if the WebSocket server is up).

I don't know exactly what the issue is but I do know that the issue lies within Ganache which fired the events before the next block was actually finished mining and all the variables where updated.

Fix: Either work from your own local Geth server or upload your contract to one of the test nets.

  • Hi @jasper, looks like you have got your problem solved. It would be ideal if you can elaborate it in detailed manner, so that community will be benefited. If you any of the other answers helped you, it would be better you can accept it and edit it if you followed any extra step. – Achala Dissanayake May 29 '18 at 14:45
  • Hi Achala you are right! – jasper May 29 '18 at 14:59
  • Great, it would be nice to have an accepted answer, even your own answer :). – Achala Dissanayake May 29 '18 at 15:11
  • I will mark it as the correct answer when I'm able to in 23 hours :) – jasper May 29 '18 at 15:17
  • That's Great :) – Achala Dissanayake May 29 '18 at 15:21
0

As Rob pointed out , you most likely aren't waiting for the transaction to be completely mined before pulling data. I'm not sure about web3js, but Golang provides the ability to read pending state data before the transaction is mined. I personally much prefer golang for writing backend code that interacts with smart contrats, and would only use web3 if needed (ie frontend code)

Caution though, I would recommend against reading pending state data since that can change depending on whatever transactions are inserted into the mempool.

It is highly recommended to wait for a transaction to be mined before processing any data, and I would personally recommend golang over web3 for interacting with smart contracts, and would only use web3 if I needed to write frontend code.

I have a function that is called whenever a particular transaction is sent ot the blockchain, and will automatically finish processing and exit after receiving the event.

https://github.com/RTradeLtd/Temporal/blob/2dd19bd950e2864e2cbad904c3b7c94958499048/server/payments.go#L55

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.