Contract-Design

使用“Truffle”框架開發的 dapp 出錯 - 從 Oraclize-Query 獲取結果時出現問題

  • March 1, 2017

我正在使用“testrpc”和“truffle”-3.1.1 開發一個 dapp。我還為 Oraclize 使用了 ethereum-bridge。我編寫了一個智能合約函式,它使用“OraclizeQuery”呼叫一個 url。

以下是合約程式碼:-

pragma solidity ^0.4.0;

import "./usingOraclize.sol";
contract WeatherApiCall is usingOraclize {
      string public weathercondition;
      event LOG_OraclizeCallback(
             bytes32 queryId,
             string result
      );
      function WeatherApiCall() {
           OAR = OraclizeAddrResolverI(0x44bc501f0d92a9583877636828f52abc9da5d585);//OAR address
     }
     function __callback(bytes32 myid, string result) {
             if (msg.sender != oraclize_cbAddress()) throw;
             weathercondition=result;
             LOG_OraclizeCallback(myid,result);
     }
     function update(string to,string datetime) payable returns(bool sufficient) {

             oraclize_query("URL", strConcat("json(http://api.openweathermap.org/data/2.5/forecast?q='", to ,"'&mode=json&APPID=d2e8279188c8649c17540f798c9cc972).list[?(@.dt_txt='", datetime, "')].weather[0].main"));
             return true;
 }
}

以下是 index.html 文件:-

<!DOCTYPE html>
<html>
<head>
     <title>Sample Truffle App</title>
     <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
     <script src="./app.js"></script>
</head>
<body>
       <h1>Airline</h1>
       <h2>Example Truffle Dapp</h2>
       <br>
      <h1>Form</h1>
              <br><label for="from">From:</label><input type="text" id="from" placeholder="--Residing Place--"></input>
              <br><label for="to">To:</label><input type="text" id="to" placeholder="--Travelling Place--"></input>
              <br><label for="persons">No. of Persons:</label><input type="text" id="persons" placeholder="--No. of Persons--"></input>
              <br><label for="date">Travel Date:</label><input type="text" id="date" placeholder="--Date of travel yyyy-MM-dd--"></input>
              <br><label for="time">Destination Time:</label><input type="text" id="time" placeholder="--HH:mm:ss--"></input>
              <br><br><button id="send" onclick="App.sendRequest()">Generate Quote</button> 
<br><br>
</body>
</html>

以下是 app.js 文件。

 // Import the page's CSS. Webpack will know what to do with it.
 import "../stylesheets/app.css";

// Import libraries we need.
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'

// Import our contract artifacts and turn them into usable abstractions.
import weatherapicall_artifacts from '../../build/contracts/WeatherApiCall.json'

// WeatherApiCall is our usable abstraction, which we'll use through the code below.
var WeatherApiCall = contract(weatherapicall_artifacts);

// The following code is simple to show off interacting with your contracts.
// As your needs grow you will likely need to change its form and structure.
// For application bootstrapping, check out window.addEventListener below.
var accounts;
var account;


 window.App = {
   start: function() {
   var self = this;

   // Bootstrap the WeatherApiCall abstraction for Use.
   WeatherApiCall.setProvider(web3.currentProvider);

  // Get the initial account balance so it can be displayed.
  web3.eth.getAccounts(function(err, accs) {
         if (err != null) {
            alert("There was an error fetching your accounts.");
            return;
         }

        if (accs.length == 0) {
              alert("Couldn't get any accounts! Make sure your Ethereum client is configured correctly.");
              return;
        }

         accounts = accs;
         account = accounts[0];
    });
 },

 sendRequest: function() {
        var queryRecheck = function(contract){

        var bn = web3.eth.blockNumber; // returns the current block number
        var logger = contract.LOG_OraclizeCallback(null, { fromBlock: bn });

       console.log('Waiting on Oraclize queries...');
       console.log(bn);
       console.log(logger);

                return new Promise(function (resolve, reject) {
                       var ctr = setInterval(function () {
                       logger.get(function (error, events) {
                       if (error)
                            reject(error);

                       try {
                             if (typeof events !== 'undefined') {
                                 events.forEach(function (evt) {
                                     if (evt.args.block.toNumber() > bn) {
                                      clearInterval(ctr);
                                      resolve();
                                   }
                             });
                     }
                     } catch (e) {
                        console.log('Error encountered during query wait: ' + e);
                        reject(e);
                    }
                });
                }, 50000);
               });
             }
             var self = this;
             var fromdata = document.getElementById("from").value;
             var to = document.getElementById("to").value;
             var persons = parseInt(document.getElementById("persons").value);
             var date = document.getElementById("date").value;
             var time = document.getElementById("time").value;
            //verifying at javascript console
             console.log(fromdata);
             console.log(to);
             console.log(persons);
             console.log(date);
             console.log(time);
             var timeperiod;
             if ((time >= '00:00:00') && (time < '03:00:00')) {
                       timeperiod = '00:00:00';
             } else if ((time >= '03:00:00') && (time < '06:00:00')) {
                       timeperiod = '03:00:00';
             } else if ((time >= '06:00:00') && (time < '09:00:00')) {
                       timeperiod = '06:00:00';
             } else if ((time >= '09:00:00') && (time < '12:00:00')) {
                       timeperiod = '09:00:00';
             } else if ((time >= '12:00:00') && (time < '15:00:00')) {
                       timeperiod = '12:00:00';
             } else if ((time >= '15:00:00') && (time < '18:00:00')) {
                       timeperiod = '15:00:00';
             } else if ((time >= '18:00:00') && (time < '21:00:00')) {
                       timeperiod = '18:00:00';
             } else if ((time >= '21:00:00') && (time < '24:00:00')) {
                       timeperiod = '21:00:00';
             }
             var datetime = date + ' ' + timeperiod;
             console.log(datetime);

              WeatherApiCall.deployed().then(function(instance) {

                         console.log("Initializing");
                         instance.update(to,datetime, {from: account, gas: 3000000, value: web3.toWei(1, 'ether')})
                              .then(function(v){
                                      console.log(v);
                                      console.log("Function Executed");
                                      return queryRecheck(instance);
                                }).then(function(events) {
                                      console.log(events);
                                });
                      }).then(function() {
                                             console.log("Testing");
                      }).catch(function(e) {
                                              console.log(e);
                      });
 }
};

window.addEventListener('load', function() {
     // Checking if Web3 has been injected by the browser (Mist/MetaMask)
     if (typeof web3 !== 'undefined') {
     console.warn("Using web3 detected from external source. If you find that your accounts don't appear or you have 0 MetaCoin, ensure you've configured that source properly. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask")
     // Use Mist/MetaMask's provider
     window.web3 = new Web3(web3.currentProvider);
     } else {
              console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
              // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
             window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
              }
             App.start();
});

以下是在 javascript 控制台生成的輸出:-

"No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask"    app.js:25575:5
india                     app.js:25520:4
chennai                   app.js:25521:4
2                         app.js:25522:4
2017-03-02                app.js:25523:4
12:00                     app.js:25524:4
2017-03-02 09:00:00       app.js:25544:4
Initializing              app.js:25549:27
Testing                   app.js:25561:50
 Object { tx: "0xcaf76e6444507c3fb48007c3e7307a8dc…", receipt: Object, logs: Array[0] }               app.js:25552:41
 Function Executed        app.js:25553:41
 Waiting on Oraclize queries... app.js:25486:8
 15                       app.js:25487:8
 Object { requestManager: Object, options: Object, implementation: Object, filterId: null, callbacks: Array[0], getLogsCallbacks: Array[0], pollFilters: Array[0], formatter: bound () }        app.js:25488:8
 Error encountered during query wait: TypeError: evt.args.block is undefined                       app.js:25506:24
 Error encountered during query wait: TypeError: evt.args.block is undefined                       app.js:25506:24
 Error encountered during query wait: TypeError: evt.args.block is undefined                       app.js:25506:24

我試圖在 javascript 控制台中列印 Oraclize-Query 的結果…但它返回的是錯誤…如何解決?

確保您的事件按預期工作並且不為空(events在處理之前添加一些 console.log)。如您所見block,對像中缺少evt,可能是因為您的LOG_OraclizeCallback事件(https://github.com/Kottackal-ET-Practice/Flight-Dapp/blob/d5f6e5a661517e00ff37f48052b5e3a1afa8558d/contracts/WeatherApiCall.sol#L8-L13)沒有block如果您嘗試從日誌中獲取塊號,則可以通過對象 ( ) 中的參數訪問該塊號blockNumberevt``evt.blockNumber

引用自:https://ethereum.stackexchange.com/questions/12605