[Ethereum] Duplicate events firing in a Web3 listener

eventssolidityweb3js

I'm experimenting with plugging Ethereum into a React web application, using this nice tutorial repo as a basis (thanks to uzyn): https://github.com/uzyn/ethereum-webpack-example-dapp

I'm connecting successfully to the local TestRPC 3.0.3 instance, have a Solidity 0.4.8 "MyToken" contract deployed and am mining a contract function called "transfer" successfully. I know the transfer is running just once from the updated account balances but I'm getting two instances of the "Transfer" event coming up in my browser console. If I take out the line emitting the event, I get nothing in the console.

Could anyone suggest why that is? Thanks!

I'm calling this contract function which emits an Event:

/* Send coins */
function transfer(address _to, uint256 _value) {

    if (balanceOf[msg.sender] < _value) throw;           // Check if the sender has enough
    if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
    balanceOf[msg.sender] -= _value;                     // Subtract from the sender
    balanceOf[_to] += _value;                            // Add the same to the recipient

    Transfer(msg.sender, _to, _value);                   // Notify anyone listening that this transfer took place
}

With this code block:

  MyTokenContract.transfer.sendTransaction(
    web3.eth.accounts[1],
    100,
    (error, result) => {
      if (error) {
        console.log(`Error occurred: ${error}`);
        return;
      }

      const accountOneBalance = MyTokenContract.balanceOf(web3.eth.accounts[0]);
      const accountTwoBalance = MyTokenContract.balanceOf(web3.eth.accounts[1]);

      console.log(`accountOneBalance: ${accountOneBalance}`);
      console.log(`accountTwoBalance: ${accountTwoBalance}`);
    }
  );

And I have this Web3 code listening for contract events:

MyTokenContract.allEvents((error, event) => {
if (error) {
  console.log(`Event error: ${error}`);
  return;
}

const eventName = event.event;
const accountFrom = event.args.from;
const accountTo = event.args.to;
const amount = event.args.value;
console.log(`Event '${eventName}' from account ${accountFrom} to ${accountTo} of ${amount}`);

});

When it runs, I get two events logged in my Chrome console:

accountOneBalance: 249900
accountTwoBalance: 100
Event 'Transfer' from account 0xdd0efd8df206cb598bda146ae567f5d398436226 to 0x7497ac386ae2e1eb58210d08e6c401b56417e04d of 100

Event 'Transfer' from account 0xdd0efd8df206cb598bda146ae567f5d398436226 to 0x7497ac386ae2e1eb58210d08e6c401b56417e04d of 100

Best Answer

I had the same issue and the above solution didn't work in the case that if the testrpc is running and having already triggered some events, then starting the Web3 code the watch returns the latest event that was triggered. What solved the problem and get only new events is:

var latestBlock = web3.eth.blockNumber; //get the latest blocknumber
contractInstance.MyEvent({fromBlock: latestBlock}, (error, event) => { 
    if (error) {
     console.log(error); return; 
    } else {
        if(event.blockNumber != latestBlock) {   //accept only new events
        console.log(event);
        latestBlock = latestBlock + 1;   //update the latest blockNumber
        }
    }

Hope that helps!

Related Topic