Smart Contracts are like a closed box, the code inside it cannot communicate with the external world on their own. However, it is really important for business applications that its smart contract should communicate with external APIs and data to complete the execution of the business logics.
One option for allowing your smart contract to communicate with external APIs is by using services such as Oraclize. It acts as a data carrier and a reliable connection between Web APIs and your Dapp. The need for Oraclize arose from the fact that the blockchain applications have no authority in fetching external resources when required.
Oraclize is the only source that helps the blockchain applications to access data from the external world. In this article, we focus on the use of Oraclize with testrpc, truffle, and ethereum-bridge. It will also explain the smart contract code which calls multiple APIs using the Oraclize service.
Before jumping into the topic, I assume you are familiar with the DApp development using the testrpc and truffle. To use Oraclize on testrpc and truffle you will need to install this tool called ‘ethereum-bridge’ which is one essential requirement for the service.
Download and install from here. Solidity contract is another requirement for using Oraclize service, which you can download from here.
How to update channel config to include anchor peer?
Keep this in mind, you have to download the contract to the truffle contracts folder of your working directory, and rename the file to using Oraclize.sol and import the above contract in your contract:
import "./usingOraclize.sol";
Start your testrpc and after that start the ethereum bridge in the active mode by using the following commands:
node bridge -H localhost:8545 -a 1
The tag -a defines an account which is used to deploy oraclize smart contract. It will return you an OAR (Oraclize Address Resolver) address. Please add this line to your constructor.
OAR=OraclizeAddrResolverI(0x5049063e4a7704ac155e4f1f42a4954bbef5bbde);
Update the oraclize smart contract constructor with the generated new resolver address.
pragma solidity ^0.4.11; import "./usingOraclize.sol"; //Importing Oraclize contract TestOraclizeCall is usingOraclize { //Constructor function TestOraclizeCall() { OAR= OraclizeAddrResolverI(0x5049063e4a7704ac155e4f1f42a4954bbef5bbde); // rest of your constructor code } // your code }
You have to send a query to the Oraclize smart contract.
Oralize receives your query and makes the corresponding request. Once the service receives the data from the API, it will call callback a function in the smart contract where you’ll be able to access and process the requested data.
pragma solidity ^0.4.16; import "./usingOraclize.sol"; //Importing Oraclize contract TestOraclizeCall is usingOraclize { uint public price; event Log(string text); //Constructor function TestOraclizeCall() { OAR = OraclizeAddrResolverI(0x5049063e4a7704ac155e4f1f42a4954bbef5bbde); } function __callback(bytes32 _myid, string _result) { require (msg.sender == oraclize_cbAddress()); Log(_result); price = parseInt(_result, 2); } function update() payable { oraclize_query("URL","json(https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD).USD"); } }
The code above here is to receive the current USD price for 1 ETH.
The oraclize_query function is used to inform the Oraclize about the third party API. The query accepts the first string parameter as the type of request. The given example uses the ‘URL’ as the first string parameter. The second parameter should be the query we are requesting: external data.
FastFabric to scale Hyperledger transactions per second
Just like any other transactions, the miners are paid with certain fees. For that, you have to define the payable modifier in the function. The miner fee is paid with ether and it is calculated by taking the amount of gas which covers the execution costs of the transaction multiplied by the selected gas/ether price. After the query transaction is executed the miner fee for the transaction can be obtained from the contract balance.
Note: the first call to Oraclize from any smart contract address is absolutely free.
In the__callback function, the first parameter is the id of the request. The second parameter is the result of your request. Using truffle, compile and run the contract.
Oraclize can handle multiple requests. The first parameter ‘id’ in the __callback will handle the multiple requests. The following example shows how oraclize deals with multiple requests.
pragma solidity ^0.4.16; import "./usingOraclize.sol"; contract TestOraclizeCall is usingOraclize { // oraclize callback types: enum oraclizeState { ForUSD, ForDistance } //Events event LOG_OraclizeCallbackForDistance( string result, ); event LOG_OraclizeCallbackForWeatherCondition( string result, ); // the oraclize callback structure: we use several oraclize calls. // all oraclize calls will result in a common callback to __callback(...). // to keep track of the different querys we have to introduce this struct. struct oraclizeCallback { // for which purpose did we call? {ForUSD | ForDistance} oraclizeState oState; } // Lookup state from queryIds mapping (bytes32 => oraclizeCallback) public oraclizeCallbacks; // constructor function TestOraclizeCall() { OAR = OraclizeAddrResolverI(0x5049063e4a7704ac155e4f1f42a4954bbef5bbde); } //Function for distance retrieval function distanceRetrieve() payable returns(bool sufficient) { bytes32 queryId = oraclize_query(10,"URL",strConcat("json(http://www.distance24.org/route.json?stops=us).distance")); oraclizeCallbacks[queryId] = oraclizeCallback(oraclizeState.ForDistance); return true; } function update() payable returns(bool sufficient) { bytes32 queryId = oraclize_query("URL","json(https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD).USD"); oraclizeCallbacks[queryId] = oraclizeCallback(oraclizeState.ForUSD); return true; } //Function callback function __callback(bytes32 myid, string result) { if (msg.sender != oraclize_cbAddress()) throw; oraclizeCallback memory o = oraclizeCallbacks[myid]; if (o.oState == oraclizeState.ForDistance) { LOG_OraclizeCallbackForDistance(result); } else if(o.oState == oraclizeState.ForUSD) { LOG_OraclizeCallbackForUSD(result); } } } In order to keep the track of the different queries, we have used struct to hold and defined a mapping between the state of query and queryids.