0

My smart contract should return the ETH rate from Coinbase api .. So i'm using Provable engine and i'm testing my smart contract locally using ganache and ethereum-bridge . It's expected that result should be returned using an event that will be fired whenever the provable call the __callback function of my contract. To test my contract i'm using mocha-js , but the problem is that my test always finish before the __callback function is called . In my test i tried to use callback function(done()), promises and async / await but no one of them solved the problem .

this is my contract code :

pragma solidity ^0.5.0;

import "./provableAPI_0.5.sol";

contract eth_rate is usingProvable {
  string public ETHUSD;
   event LogConstructorInitiated(string nextStep);
   event LogPriceUpdated(string price);
   event LogNewProvableQuery(string description);

   constructor() public {
       emit LogConstructorInitiated("Constructor was initiated. Call 'updatePrice()' to send the Provable Query.");
   }

   function __callback(bytes32  myid, string memory result) public {
       if (msg.sender != provable_cbAddress()) revert();
        ETHUSD = result;
        emit LogPriceUpdated(result);
   }

   function updatePrice()public  payable {
       if (provable_getPrice("URL") > msg.sender.balance) {
           emit LogNewProvableQuery("Provable query was NOT sent, please add some ETH to cover for the query fee");
       } else {
           emit LogNewProvableQuery("Provable query was sent, standing by for the answer..");
           provable_query("URL", "json(https://api.pro.coinbase.com/products/ETH-USD/ticker).price");
       }
   }
}

and this is my test code:

const eth_rate = artifacts.require("eth_rate");
const truffleAssert = require('truffle-assertions');
require('truffle-test-utils').init();

contract('eth_rate',  (accounts) => {
    let instance;

     beforeEach('should setup the contract instance', async () => {
         instance = await eth_rate.deployed();
    });

   it("should return the list of accounts", async ()=> {
    console.log(accounts);
  });


 it('ETH rate ', async function() {
  const result = await instance.updatePrice();
  truffleAssert.eventEmitted(result, 'LogPriceUpdated');

  })

});
  • The callback is not fired immediately, so you will have to wait until it is fired. – Ismael Aug 26 at 21:48
1

I used setTimeout function to wait for the callback transaction. However setting a timeout might require me to wait longer then necessary .. any way it works for me now and here is my test code :

const eth_rate = artifacts.require("eth_rate");
const truffleAssert = require('truffle-assertions');
require('truffle-test-utils').init();

contract('eth_rate',  (accounts) => {
    let instance;

     beforeEach('should setup the contract instance', async () => {
         instance = await eth_rate.deployed();
    });

   it("should return the list of accounts", async ()=> {
    console.log(accounts);
  });

  it("ETH rate", function(done) {
    var result;
    eth_rate.deployed().then(function(value) {
      instance = value;
      return instance.updatePrice();
    }).then(function(res){
      result = res;
      return new Promise(resolve => setTimeout(resolve, 15000));
    }).then(function(){
      return instance.ETHUSD();
    }).then(function(value){
      console.log(" Ethereum rate(USD) = " + value);
      done();
    });
  });

});
  • Another possibility is to subscribe to LogPriceUpdated event and wait for it to be fired. – Ismael Aug 27 at 14:45
  • 1
    i tried to do that but i think that since the event is fired by an other contract i couldn't catch it so i had to save the result in a var .. – Abir HAMZI Aug 27 at 15:08

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.