[Ethereum] Can you filter and watch for a contracts state changing method in web3.js

ethernodejssolidityweb3js

Let's say I have a very simple contract:

 contract basicStorage {
     uint storedData;

     function set(uint x) {
        storedData = x;
     }

     function get() constant returns (uint) {
        return storedData;
     }
 }

I would like to watch for changes on set() which I believe changes the contracts state, is it possible using filter/watch in web3.js?

Best Answer

I would recommend to use events.

Smart-Contract - Log events

pragma solidity ^0.4.15;

contract basicStorage {
    uint storedData;

    event SetEvent(
        address indexed _from,
        uint _x
    );

    function set(uint x) {
        storedData = x;

        // Log event
        SetEvent(msg.sender, x);
    }

    function get() constant returns (uint) {
        return storedData;
    }
}

The code above logs an event each time the function set(x) is executed. The log contains the sender address and the argument x.

Web3 - Watch events

var Web3 = require('web3');
var abi = [...];
var address = '0xxxxxxxxxxxxxxxxxxxx'

var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
var basicStorageContract = web3.eth.contract(abi);
var basicStorageContractInstance = basicStorageContract.at(address);

// watch for changes
var myEvent = basicStorageContractInstance.SetEvent({}, {fromBlock: 0, toBlock: 'latest'});

console.log("Start watching events"); 
myEvent.watch(function(error, result){
    if (!error) {
        console.log(result);
    } else {
        console.log(error);  
    }
});



// Send a transaction to call Set
console.log("set(10)"); 
basicStorageContractInstance.set(10, {from: '0xxxxxxxxxxxxxxxxxxxx'});

console.log("set(20)"); 
basicStorageContractInstance.set(20, {from: '0xxxxxxxxxxxxxxxxxxxx'});

This code compiles the contract and retrieves an myEvent object which can be used to watch for an event (in our case that represents a state change).

Then sends two transactions and check if some logs are printed.

Result

{ logIndex: 0,
  transactionIndex: 0,
  transactionHash: '0x0dc9c421f4d15baa00249f8d1d55d75ea267bc4c82b9654e3c24daf69f9c529d',
  blockHash: '0x2814a29a8c3e32d66063472c6e1d9e5c8eee159f7d19d5da6ecc4bdeeeb9449c',
  blockNumber: 22,
  address: '0xa07ddaff6d8b7aabf91ac6f82bf89455eb9784f4',
  type: 'mined',
  event: 'SetEvent',
  args:
   { _from: '0x13a0674c16f6a5789bff26188c63422a764d9a39',
     _x: { [String: '20'] s: 1, e: 1, c: [Array] } } }

{ logIndex: 0,
  transactionIndex: 0,
  transactionHash: '0x62d888d67e4392b7d218cc7a678b7f3168bcdd2fd77b5a51507e2bf62948273d',
  blockHash: '0x737fce60e8a2012f25eca24d8e56a13eeb127641cc89938f5ec3d8764131f7c7',
  blockNumber: 23,
  address: '0xa07ddaff6d8b7aabf91ac6f82bf89455eb9784f4',
  type: 'mined',
  event: 'SetEvent',
  args:
   { _from: '0x13a0674c16f6a5789bff26188c63422a764d9a39',
     _x: { [String: '30'] s: 1, e: 1, c: [Array] } } }

You can find more info

Related Topic