Contract-Design
使用“Truffle”框架開發的 dapp 出錯 - 從 Oraclize-Query 獲取結果時出現問題
我正在使用“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
如果您嘗試從日誌中獲取塊號,則可以通過對象 ( ) 中的參數訪問該塊號blockNumber
。evt``evt.blockNumber