3

I'm trying to write tests in Mocha/JS with Truffle for a Solidity function that uses Oraclize. I want to test if the result in the callback of my Oraclize query is correct. As Oraclize needs some time to process the query I need to wait for the response of the transaction. Right now I'm achieving this with a setTimeout function to wait for the callback transaction. Setting a timeout might require me to wait longer then necessary or even make the test fail if the timeout is set too low. Is there a better way to achieve this?

I am using Truffle 3.2.1 with TestRPC 3.0.5 and ethereum-bridge 0.4.21.

Here is the JS test code snippet:

it("Request computation and send results to Arbiter", function(done) {
  this.timeout(250000);
  var computation;
  var result;
  ComputationService.deployed().then(function(instance) {
    computation = instance;
    return computation.compute("43543", "423543543", 0, 56347573485346, {from:accounts[0], gas: 500000, value: web3.toWei(0.01, "ether")});
  }).then(function(){
    return new Promise(resolve => setTimeout(resolve, 240000));
  }).then(function(){
    return computation.getResult(56347573485346);
  }).then(function(value){
    result = value;
    assert.equal(result, "18442356492849", "The result is wrong (should be 18442356492849)");
    done();
  });
});

This is the Solidity callback function with a newResult event:

function __callback(bytes32 _oraclizeID, string _result) {
  if (msg.sender != oraclize_cbAddress()) throw;
  newResult(_result);
  requestOraclize[_oraclizeID].result = _result;
}
2

You could create a function which creates a filter watch for new tx-s from Oraclize's CB address. That function could resolve when a new tx from Oraclize's cb address matches your criteria.

Here is an example which I created for a slightly different requirement (ie. wait for the block timestamp to reach a certain timestamp) but you could build from it.

var moment = require('moment');

function waitForTimeStamp(waitForTimeStamp) {
    var currentTimeStamp = moment().utc().unix();
    var wait =  waitForTimeStamp - currentTimeStamp;
    wait = wait < 0 ? 0 : wait;
    console.log("... waiting ", wait, "seconds then sending a dummy tx for blockTimeStamp to reach time required by test ...");

    return new Promise( resolve => {
            setTimeout(function () {
                var blockTimeStamp = web3.eth.getBlock( web3.eth.blockNumber).timestamp;
                if( blockTimeStamp < waitForTimeStamp ) {
                    web3.eth.sendTransaction({from: web3.eth.accounts[0]}, function(error, res) {
                        if (error) {
                            console.log("waitForTimeStamp() web3.eth.sendTransaction() error")
                            reject(error);
                        } else {
                            resolve();
                        }
                    });
                } else {
                    resolve();
                }
            }, wait * 1000);
    });

} // waitForTimeStamp()

it("should happen in the future", () => {
    //  your instance setup here...

    return myInstance.myTransaction()
    .then( res => {
        var waitLength = res; // in seconds
        var waitUntil = moment().utc().unix() + waitLength;
        return waitForTimeStamp(waitUntil);
    }).then( res => { 
        done();
    });
});

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.