Внедрение тестов обратного вызова Oraclize с Truffle/Mocha

Я пытаюсь написать тесты в Mocha/JS с Truffle для функции Solidity, которая использует Oraclize. Я хочу проверить правильность результата обратного вызова моего запроса Oraclize. Поскольку Oraclize требуется некоторое время для обработки запроса, мне нужно дождаться ответа транзакции. Прямо сейчас я добиваюсь этого с помощью setTimeoutфункции ожидания транзакции обратного вызова. Установка тайм-аута может потребовать от меня ожидания дольше, чем необходимо, или даже привести к сбою теста, если тайм-аут установлен слишком мало. Есть ли лучший способ добиться этого?

Я использую Truffle 3.2.1 с TestRPC 3.0.5 и ethereum-bridge 0.4.21.

Вот фрагмент тестового кода JS:

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();
  });
});

Это функция обратного вызова Solidity с newResultсобытием:

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

Ответы (1)

Вы можете создать функцию, которая создает часы фильтра для новых tx-s с адреса CB Oraclize. Эта функция может разрешиться, когда новый tx от адреса cb Oraclize соответствует вашим критериям.

Вот пример, который я создал для немного другого требования (т. е. дождаться, пока временная метка блока достигнет определенной временной метки), но вы можете построить его.

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();
    });
});