├── .gitignore ├── .gitattributes ├── contracts ├── lib │ └── Oracle.sol ├── Migrations.sol ├── Consumer.sol ├── AlphaVantageConsumer.sol ├── WolframAlphaConsumer.sol ├── AssetPriceConsumer.sol ├── AliceAndBob.sol ├── APIAggregatorConsumer.sol └── RapidAPIWeatherConsumer.sol ├── migrations ├── 1_initial_migration.js ├── 2_asset_price_consumer.js ├── 3_alpha_vantage_consumer.js ├── 5_wolframalpha_consumer.js ├── 4_api_aggregator_consumer.js ├── 6_rapidapi_weather_consumer.js └── 7_alice_and_bob_consumer.js ├── scripts ├── helper.js ├── util │ └── new_oracle.js ├── apiaggregator │ ├── get.js │ └── request.js ├── wolfram │ ├── get.js │ └── request.js ├── alphavantage │ ├── get.js │ └── request.js ├── assetprice │ ├── get.js │ └── request.js ├── alice-and-bob │ └── request.js └── rapidapiweather │ ├── request.js │ └── get.js ├── specs ├── alpha_vantage.json ├── asset_price.json ├── wolfram_alpha.json ├── api_aggregator.json └── rapid_api_get_uint256.json ├── package.json ├── truffle.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity -------------------------------------------------------------------------------- /contracts/lib/Oracle.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.24; 2 | 3 | import "chainlink/contracts/Oracle.sol"; -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /scripts/helper.js: -------------------------------------------------------------------------------- 1 | const config = require('../truffle.js'); 2 | 3 | module.exports = { 4 | getNetwork: function(network) { 5 | if (network === "ropsten-fork") { 6 | return "ropsten" 7 | } else { 8 | return network 9 | } 10 | }, 11 | getLinkToken: function(network) { 12 | return config.networks[this.getNetwork(network)].linkToken; 13 | } 14 | }; -------------------------------------------------------------------------------- /scripts/util/new_oracle.js: -------------------------------------------------------------------------------- 1 | const Oracle = artifacts.require("Oracle"); 2 | 3 | module.exports = async(callback) => { 4 | try { 5 | console.log("Deploying Oracle.sol"); 6 | let oc = await Oracle.new(process.argv[4]); 7 | await oc.setFulfillmentPermission(process.argv[5], true); 8 | console.log("Oracle Address:", oc.address); 9 | } catch (e) { 10 | console.error(e); 11 | } 12 | return callback(); 13 | }; -------------------------------------------------------------------------------- /migrations/2_asset_price_consumer.js: -------------------------------------------------------------------------------- 1 | const AssetPriceConsumer = artifacts.require("AssetPriceConsumer"); 2 | 3 | const config = require('../truffle.js'); 4 | const helper = require('../scripts/helper'); 5 | 6 | module.exports = function(deployer, network) { 7 | let job = config.networks[helper.getNetwork(network)].assetPriceJob; 8 | if (!job.oracle) return; 9 | deployer.deploy( 10 | AssetPriceConsumer, 11 | helper.getLinkToken(network), 12 | job.oracle, 13 | web3.utils.utf8ToHex(job.id) 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /migrations/3_alpha_vantage_consumer.js: -------------------------------------------------------------------------------- 1 | const AlphaVantageConsumer = artifacts.require("AlphaVantageConsumer"); 2 | 3 | const config = require('../truffle.js'); 4 | const helper = require('../scripts/helper'); 5 | 6 | module.exports = function(deployer, network) { 7 | let job = config.networks[helper.getNetwork(network)].alphaVantageJob; 8 | if (!job.oracle) return; 9 | deployer.deploy( 10 | AlphaVantageConsumer, 11 | helper.getLinkToken(network), 12 | job.oracle, 13 | web3.utils.utf8ToHex(job.id) 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /migrations/5_wolframalpha_consumer.js: -------------------------------------------------------------------------------- 1 | const WolframAlphaConsumer = artifacts.require("WolframAlphaConsumer"); 2 | 3 | const config = require('../truffle.js'); 4 | const helper = require('../scripts/helper'); 5 | 6 | module.exports = function(deployer, network) { 7 | let job = config.networks[helper.getNetwork(network)].wolframAlphaJob; 8 | if (!job.oracle) return; 9 | deployer.deploy( 10 | WolframAlphaConsumer, 11 | helper.getLinkToken(network), 12 | job.oracle, 13 | web3.utils.utf8ToHex(job.id) 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /migrations/4_api_aggregator_consumer.js: -------------------------------------------------------------------------------- 1 | const APIAggregatorConsumer = artifacts.require("APIAggregatorConsumer"); 2 | 3 | const config = require('../truffle.js'); 4 | const helper = require('../scripts/helper'); 5 | 6 | module.exports = function(deployer, network) { 7 | let job = config.networks[helper.getNetwork(network)].apiAggregatorJob; 8 | if (!job.oracle) return; 9 | deployer.deploy( 10 | APIAggregatorConsumer, 11 | helper.getLinkToken(network), 12 | job.oracle, 13 | web3.utils.utf8ToHex(job.id) 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /scripts/apiaggregator/get.js: -------------------------------------------------------------------------------- 1 | const APIAggregatorConsumer = artifacts.require("APIAggregatorConsumer"); 2 | 3 | module.exports = async(callback) => { 4 | try { 5 | let aac = await APIAggregatorConsumer.deployed(); 6 | let price = await aac.prices.call(web3.utils.sha3("BTCUSD")); 7 | console.log("Pair hash: " + web3.utils.sha3("BTCUSD")); 8 | console.log("Latest price for BTC-USD: " + price.toNumber() / 100); 9 | } catch (e) { 10 | console.error(e); 11 | } 12 | 13 | return callback() 14 | }; -------------------------------------------------------------------------------- /migrations/6_rapidapi_weather_consumer.js: -------------------------------------------------------------------------------- 1 | const RapidAPIWeatherConsumer = artifacts.require("RapidAPIWeatherConsumer"); 2 | 3 | const config = require('../truffle.js'); 4 | const helper = require('../scripts/helper'); 5 | 6 | module.exports = function(deployer, network) { 7 | let job = config.networks[helper.getNetwork(network)].rapidApiWeather; 8 | if (!job.oracle) return; 9 | deployer.deploy( 10 | RapidAPIWeatherConsumer, 11 | helper.getLinkToken(network), 12 | job.oracle, 13 | web3.utils.utf8ToHex(job.id) 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /migrations/7_alice_and_bob_consumer.js: -------------------------------------------------------------------------------- 1 | const AliceAndBob = artifacts.require("AliceAndBob"); 2 | 3 | const config = require('../truffle.js'); 4 | const helper = require('../scripts/helper'); 5 | 6 | module.exports = async function(deployer, network, accounts) { 7 | let job = config.networks[helper.getNetwork(network)].httpGet; 8 | if (!job.oracle) return; 9 | return await deployer.deploy( 10 | AliceAndBob, 11 | helper.getLinkToken(network), 12 | job.oracle, 13 | web3.utils.fromAscii(job.id), 14 | accounts[0], 15 | accounts[1], 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /scripts/wolfram/get.js: -------------------------------------------------------------------------------- 1 | const WolframAlphaConsumer = artifacts.require("WolframAlphaConsumer"); 2 | 3 | module.exports = async(callback) => { 4 | try { 5 | let ph = web3.utils.soliditySha3(process.argv[4], process.argv[5]); 6 | let wa = await WolframAlphaConsumer.deployed(); 7 | let distance = await wa.distances.call(ph); 8 | console.log("Pair hash:", ph); 9 | console.log("Distance between", process.argv[4], "and", process.argv[5], "is", distance.toNumber(), "miles"); 10 | } catch (e) { 11 | console.error(e) 12 | } 13 | 14 | return callback() 15 | }; -------------------------------------------------------------------------------- /contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.23; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | constructor() public { 8 | owner = msg.sender; 9 | } 10 | 11 | modifier restricted() { 12 | if (msg.sender == owner) _; 13 | } 14 | 15 | function setCompleted(uint completed) public restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) public restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /scripts/alphavantage/get.js: -------------------------------------------------------------------------------- 1 | const AlphaVantageConsumer = artifacts.require("AlphaVantageConsumer"); 2 | 3 | module.exports = async(callback) => { 4 | let base = process.argv[4]; 5 | let quote = process.argv[5]; 6 | 7 | try { 8 | let avc = await AlphaVantageConsumer.deployed(); 9 | let price = await avc.prices.call(web3.utils.sha3(base + quote)); 10 | console.log("Pair hash:", web3.utils.sha3(base + quote)); 11 | console.log("Latest rate for", base, quote, "is", price.toNumber() / 100); 12 | } catch (e) { 13 | console.error(e); 14 | } 15 | 16 | return callback() 17 | } -------------------------------------------------------------------------------- /specs/alpha_vantage.json: -------------------------------------------------------------------------------- 1 | { 2 | "initiators": [ 3 | { 4 | "type": "runlog", 5 | "params": { 6 | "address": "0x0000000000000000000000000000000000000000" 7 | } 8 | } 9 | ], 10 | "tasks": [ 11 | { 12 | "type": "alphavantage", 13 | "confirmations": 0, 14 | "params": {} 15 | }, 16 | { 17 | "type": "copy", 18 | "confirmations": 0, 19 | "params": {} 20 | }, 21 | { 22 | "type": "multiply", 23 | "confirmations": 0, 24 | "params": {} 25 | }, 26 | { 27 | "type": "ethuint256", 28 | "confirmations": 0, 29 | "params": {} 30 | }, 31 | { 32 | "type": "ethtx", 33 | "confirmations": 0, 34 | "params": {} 35 | } 36 | ], 37 | "startAt": null, 38 | "endAt": null 39 | } -------------------------------------------------------------------------------- /specs/asset_price.json: -------------------------------------------------------------------------------- 1 | { 2 | "initiators": [ 3 | { 4 | "type": "runlog", 5 | "params": { 6 | "address": "0x0000000000000000000000000000000000000000" 7 | } 8 | } 9 | ], 10 | "tasks": [ 11 | { 12 | "type": "assetprice", 13 | "confirmations": 0, 14 | "params": {} 15 | }, 16 | { 17 | "type": "copy", 18 | "confirmations": 0, 19 | "params": {} 20 | }, 21 | { 22 | "type": "multiply", 23 | "confirmations": 0, 24 | "params": {} 25 | }, 26 | { 27 | "type": "ethuint256", 28 | "confirmations": 0, 29 | "params": {} 30 | }, 31 | { 32 | "type": "ethtx", 33 | "confirmations": 0, 34 | "params": {} 35 | } 36 | ], 37 | "startAt": null, 38 | "endAt": null 39 | } -------------------------------------------------------------------------------- /specs/wolfram_alpha.json: -------------------------------------------------------------------------------- 1 | { 2 | "initiators": [ 3 | { 4 | "type": "runlog", 5 | "params": { 6 | "address": "0x0000000000000000000000000000000000000000" 7 | } 8 | } 9 | ], 10 | "tasks": [ 11 | { 12 | "type": "wolframalpha", 13 | "confirmations": 0, 14 | "params": {} 15 | }, 16 | { 17 | "type": "copy", 18 | "confirmations": 0, 19 | "params": {} 20 | }, 21 | { 22 | "type": "multiply", 23 | "confirmations": 0, 24 | "params": {} 25 | }, 26 | { 27 | "type": "ethint256", 28 | "confirmations": 0, 29 | "params": {} 30 | }, 31 | { 32 | "type": "ethtx", 33 | "confirmations": 0, 34 | "params": {} 35 | } 36 | ], 37 | "startAt": null, 38 | "endAt": null 39 | } -------------------------------------------------------------------------------- /specs/api_aggregator.json: -------------------------------------------------------------------------------- 1 | { 2 | "initiators": [ 3 | { 4 | "type": "runlog", 5 | "params": { 6 | "address": "0x0000000000000000000000000000000000000000" 7 | } 8 | } 9 | ], 10 | "tasks": [ 11 | { 12 | "type": "apiaggregator", 13 | "confirmations": 0, 14 | "params": {} 15 | }, 16 | { 17 | "type": "copy", 18 | "confirmations": 0, 19 | "params": {} 20 | }, 21 | { 22 | "type": "multiply", 23 | "confirmations": 0, 24 | "params": {} 25 | }, 26 | { 27 | "type": "ethuint256", 28 | "confirmations": 0, 29 | "params": {} 30 | }, 31 | { 32 | "type": "ethtx", 33 | "confirmations": 0, 34 | "params": {} 35 | } 36 | ], 37 | "startAt": null, 38 | "endAt": null 39 | } -------------------------------------------------------------------------------- /specs/rapid_api_get_uint256.json: -------------------------------------------------------------------------------- 1 | { 2 | "initiators": [ 3 | { 4 | "type": "runlog", 5 | "params": { 6 | "address": "0x0000000000000000000000000000000000000000" 7 | } 8 | } 9 | ], 10 | "tasks": [ 11 | { 12 | "type": "rapidapiget", 13 | "confirmations": 0, 14 | "params": {} 15 | }, 16 | { 17 | "type": "copy", 18 | "confirmations": 0, 19 | "params": {} 20 | }, 21 | { 22 | "type": "multiply", 23 | "confirmations": 0, 24 | "params": {} 25 | }, 26 | { 27 | "type": "ethuint256", 28 | "confirmations": 0, 29 | "params": {} 30 | }, 31 | { 32 | "type": "ethtx", 33 | "confirmations": 0, 34 | "params": {} 35 | } 36 | ], 37 | "startAt": null, 38 | "endAt": null 39 | } -------------------------------------------------------------------------------- /scripts/apiaggregator/request.js: -------------------------------------------------------------------------------- 1 | const helper = require("../helper"); 2 | 3 | const APIAggregatorConsumer = artifacts.require("APIAggregatorConsumer"); 4 | const LinkToken = artifacts.require("LinkTokenInterface"); 5 | 6 | module.exports = async(callback) => { 7 | try { 8 | let network = await web3.eth.net.getNetworkType(); 9 | let linkToken = await LinkToken.at(helper.getLinkToken(network)); 10 | let aac = await APIAggregatorConsumer.deployed(); 11 | console.log("Sending 1 LINK to the consumer contract..."); 12 | await linkToken.transfer(aac.address, web3.utils.toWei("1")); 13 | console.log("Requesting BTCUSD Price using API Aggregator..."); 14 | await aac.requestBTCUSDPrice(); 15 | console.log("Done"); 16 | } catch (e) { 17 | console.error(e); 18 | } 19 | 20 | return callback(); 21 | }; -------------------------------------------------------------------------------- /scripts/alphavantage/request.js: -------------------------------------------------------------------------------- 1 | const helper = require("../helper") 2 | const AlphaVantageConsumer = artifacts.require("AlphaVantageConsumer"); 3 | const LinkToken = artifacts.require("LinkTokenInterface"); 4 | 5 | module.exports = async(callback) => { 6 | let from = process.argv[4]; 7 | let to = process.argv[5]; 8 | 9 | try { 10 | let network = await web3.eth.net.getNetworkType(); 11 | let linkToken = await LinkToken.at(helper.getLinkToken(network)); 12 | let avc = await AlphaVantageConsumer.deployed(); 13 | console.log("Sending 1 LINK to the consumer contract..."); 14 | await linkToken.transfer(avc.address, web3.utils.toWei("1")); 15 | console.log("Requesting exchange rate..."); 16 | await avc.requestExchangeRate(from, to); 17 | console.log("Done"); 18 | } catch (e) { 19 | console.error(e); 20 | } 21 | 22 | return callback(); 23 | } -------------------------------------------------------------------------------- /scripts/wolfram/request.js: -------------------------------------------------------------------------------- 1 | const helper = require("../helper.js"); 2 | 3 | const WolframAlphaConsumer = artifacts.require("WolframAlphaConsumer"); 4 | const LinkToken = artifacts.require("LinkTokenInterface"); 5 | 6 | module.exports = async(callback) => { 7 | let from = process.argv[4]; 8 | let to = process.argv[5]; 9 | 10 | try { 11 | let network = await web3.eth.net.getNetworkType(); 12 | let linkToken = await LinkToken.at(helper.getLinkToken(network)); 13 | let wa = await WolframAlphaConsumer.deployed(); 14 | console.log("Sending 1 LINK to the consumer contract..."); 15 | await linkToken.transfer(wa.address, web3.utils.toWei("1")); 16 | console.log("Requesting distance from WolframAlpha Short Answers..."); 17 | await wa.requestDistance(from, to); 18 | console.log("Done"); 19 | } catch (e) { 20 | console.error(e); 21 | } 22 | 23 | return callback(); 24 | }; 25 | -------------------------------------------------------------------------------- /scripts/assetprice/get.js: -------------------------------------------------------------------------------- 1 | const AssetPriceConsumer = artifacts.require("AssetPriceConsumer"); 2 | 3 | module.exports = async(callback) => { 4 | let base = process.argv[4]; 5 | let quote = process.argv[5]; 6 | 7 | try { 8 | let asp = await AssetPriceConsumer.deployed(); 9 | let price = await asp.prices.call(web3.utils.sha3(base + quote)); 10 | let formattedPrice; 11 | switch(quote) { 12 | case "USD": 13 | case "EUR": 14 | formattedPrice = price.toNumber() / 100; 15 | break; 16 | case "BTC": 17 | formattedPrice = price.toNumber() / 100000; 18 | break; 19 | case "ETH": 20 | formattedPrice = web3.fromWei(price); 21 | } 22 | console.log("Pair hash: " + web3.utils.sha3(base + quote)); 23 | console.log("Latest price for " + base + "-" + quote + ": " + formattedPrice); 24 | } catch (e) { 25 | console.log(e); 26 | } 27 | 28 | return callback() 29 | }; -------------------------------------------------------------------------------- /scripts/alice-and-bob/request.js: -------------------------------------------------------------------------------- 1 | const helper = require("../helper"); 2 | const AliceAndBob = artifacts.require("AliceAndBob"); 3 | const LinkToken = artifacts.require("LinkTokenInterface"); 4 | 5 | module.exports = async(callback) => { 6 | try { 7 | let accounts = await web3.eth.getAccounts(); 8 | let network = await web3.eth.net.getNetworkType(); 9 | let linkToken = await LinkToken.at(helper.getLinkToken(network)); 10 | let aab = await AliceAndBob.deployed(); 11 | 12 | console.log("Sending 2 LINK to the consumer contract..."); 13 | await linkToken.transfer(aab.address, web3.utils.toWei("2")); 14 | 15 | console.log("Depositing 1 ETH into the SEO contract..."); 16 | await web3.eth.sendTransaction({from: accounts[0], to: aab.address, value: web3.utils.toWei('1')}); 17 | 18 | console.log("Requesting the site listing for the SEO agreement..."); 19 | await aab.checkSiteListing({from: accounts[0]}); 20 | 21 | console.log("Done") 22 | } catch (e) { 23 | console.error(e); 24 | } 25 | 26 | return callback(); 27 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-chainlinks", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "truffle-config.js", 6 | "directories": {}, 7 | "scripts": { 8 | "migrate": "./node_modules/.bin/truffle migrate", 9 | "debug": "./node_modules/.bin/truffle debug", 10 | "compile": "./node_modules/.bin/truffle compile", 11 | "exec": "./node_modules/.bin/truffle exec", 12 | "test": "./node_modules/.bin/truffle test" 13 | }, 14 | "author": "Jonny Huxtable", 15 | "license": "ISC", 16 | "dependencies": { 17 | "chainlink": "^0.6.1", 18 | "openzeppelin-solidity": "^1.12.0" 19 | }, 20 | "devDependencies": { 21 | "bn.js": "^4.11.8", 22 | "eslint": "^5.14.1", 23 | "eslint-config-standard": "^12.0.0", 24 | "eslint-plugin-import": "^2.16.0", 25 | "eslint-plugin-node": "^8.0.1", 26 | "eslint-plugin-promise": "^4.0.1", 27 | "eslint-plugin-standard": "^4.0.0", 28 | "ethereumjs-abi": "^0.6.6", 29 | "ethereumjs-util": "^6.1.0", 30 | "solium": "^1.2.3", 31 | "solium-plugin-zeppelin": "^0.0.2", 32 | "truffle": "^5.0.4", 33 | "truffle-hdwallet-provider": "^1.0.0-web3one.5", 34 | "web3": "^1.0.0-beta.46" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /scripts/assetprice/request.js: -------------------------------------------------------------------------------- 1 | const helper = require("../helper"); 2 | 3 | const AssetPriceConsumer = artifacts.require("AssetPriceConsumer"); 4 | const LinkToken = artifacts.require("LinkTokenInterface"); 5 | 6 | module.exports = async(callback) => { 7 | let base = process.argv[4]; 8 | let quote = process.argv[5]; 9 | 10 | try { 11 | let network = await web3.eth.net.getNetworkType(); 12 | let linkToken = await LinkToken.at(helper.getLinkToken(network)); 13 | let asp = await AssetPriceConsumer.deployed(); 14 | console.log("Sending 1 LINK to the consumer contract..."); 15 | await linkToken.transfer(asp.address, web3.utils.toWei("1")); 16 | console.log("Requesting price..."); 17 | switch(quote) { 18 | case "USD": 19 | await asp.requestUSDPrice(base); 20 | break; 21 | case "EUR": 22 | await asp.requestEURPrice(base); 23 | break; 24 | case "BTC": 25 | await asp.requestSatsPrice(base); 26 | break; 27 | case "ETH": 28 | await asp.requestSatsPrice(base); 29 | break; 30 | } 31 | console.log("Done"); 32 | } catch (e) { 33 | console.error(e); 34 | } 35 | 36 | return callback(); 37 | }; -------------------------------------------------------------------------------- /scripts/rapidapiweather/request.js: -------------------------------------------------------------------------------- 1 | const helper = require("../helper"); 2 | 3 | const RapidAPIWeatherConsumer = artifacts.require("RapidAPIWeatherConsumer"); 4 | const LinkToken = artifacts.require("LinkTokenInterface"); 5 | 6 | module.exports = async(callback) => { 7 | let funcName = process.argv[4]; 8 | let location = process.argv[5]; 9 | 10 | try { 11 | let network = await web3.eth.net.getNetworkType(); 12 | let linkToken = await LinkToken.at(helper.getLinkToken(network)); 13 | let rw = await RapidAPIWeatherConsumer.deployed(); 14 | console.log("Sending 1 LINK to the consumer contract..."); 15 | await linkToken.transfer(rw.address, web3.utils.toWei("10")); 16 | console.log("Requesting the weather from RapidAPI Open Weather..."); 17 | switch (funcName) { 18 | case "imperialTemp": 19 | await rw.requestImperialTemp(location); 20 | break; 21 | case "metricTemp": 22 | await rw.requestMetricTemp(location); 23 | break; 24 | case "humidity": 25 | await rw.requestHumidity(location); 26 | break; 27 | case "windSpeed": 28 | await rw.requestWindSpeed(location); 29 | break; 30 | } 31 | console.log("Done"); 32 | } catch (e) { 33 | console.error(e); 34 | } 35 | 36 | return callback(); 37 | }; -------------------------------------------------------------------------------- /scripts/rapidapiweather/get.js: -------------------------------------------------------------------------------- 1 | const RapidAPIWeatherConsumer = artifacts.require("RapidAPIWeatherConsumer"); 2 | 3 | module.exports = async(callback) => { 4 | let funcName = process.argv[4]; 5 | let location = process.argv[5]; 6 | 7 | try { 8 | let rw = await RapidAPIWeatherConsumer.deployed(); 9 | switch (funcName) { 10 | case "imperialTemp": 11 | let it = await rw.temps.call(web3.utils.soliditySha3(location, "imperial")); 12 | console.log("Temperature in", location, "is", it.toNumber() / 100, "F"); 13 | return callback(); 14 | case "metricTemp": 15 | let mt = await rw.temps.call(web3.utils.soliditySha3(location, "metric")); 16 | console.log("Temperature in", location, "is", mt.toNumber() / 100, "C"); 17 | return callback(); 18 | case "humidity": 19 | let h = await rw.humidities.call(web3.utils.soliditySha3(location)); 20 | console.log("Humidity in", location, "is", h.toNumber(), "%"); 21 | return callback(); 22 | case "windSpeed": 23 | let ws = await rw.windSpeeds.call(web3.utils.soliditySha3(location, "imperial")); 24 | console.log("Windspeed in", location, "is", ws.toNumber() / 10, "mph"); 25 | return callback(); 26 | } 27 | } catch (e) { 28 | console.error(e); 29 | } 30 | }; -------------------------------------------------------------------------------- /contracts/Consumer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.24; 2 | 3 | import "chainlink/contracts/Chainlinked.sol"; 4 | import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; 5 | 6 | contract Consumer is Chainlinked, Ownable { 7 | // solium-disable-next-line zeppelin/no-arithmetic-operations 8 | uint256 constant private ORACLE_PAYMENT = 1 * LINK; 9 | 10 | bytes32 internal specId; 11 | bytes32 public currentPrice; 12 | 13 | event RequestFulfilled( 14 | bytes32 indexed requestId, // User-defined ID 15 | bytes32 indexed price 16 | ); 17 | 18 | constructor(address _oracle, bytes32 _specId) public { 19 | setLinkToken(0x20fE562d797A42Dcb3399062AE9546cd06f63280); 20 | setOracle(_oracle); 21 | specId = _specId; 22 | } 23 | 24 | function requestEthereumPrice(string _currency) public { 25 | Chainlink.Request memory req = newRequest(specId, this, this.fulfill.selector); 26 | req.add("url", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); 27 | string[] memory path = new string[](1); 28 | path[0] = _currency; 29 | req.addStringArray("path", path); 30 | chainlinkRequestTo(oracleAddress(), req, ORACLE_PAYMENT); 31 | } 32 | 33 | function cancelRequest( 34 | bytes32 _requestId, 35 | uint256 _payment, 36 | bytes4 _callbackFunctionId, 37 | uint256 _expiration 38 | ) 39 | public 40 | onlyOwner 41 | { 42 | cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); 43 | } 44 | 45 | function withdrawLink() public { 46 | LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); 47 | require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer"); 48 | } 49 | 50 | function fulfill(bytes32 _requestId, bytes32 _price) 51 | public 52 | recordChainlinkFulfillment(_requestId) 53 | { 54 | emit RequestFulfilled(_requestId, _price); 55 | currentPrice = _price; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /truffle.js: -------------------------------------------------------------------------------- 1 | const HDWalletProvider = require("truffle-hdwallet-provider"); 2 | 3 | module.exports = { 4 | compilers: { 5 | solc: { 6 | version: "0.4.24" 7 | } 8 | }, 9 | networks: { 10 | ropsten: { 11 | provider: function() { 12 | return new HDWalletProvider( 13 | "", // Mnemonic 14 | "", // Ethereum client, Infura etc. 15 | 0, 16 | 2 17 | ); 18 | }, 19 | network_id: 3, 20 | gas: 4712388, 21 | gasPrice: 10000000000, 22 | skipDryRun: true, 23 | 24 | // Chainlink Configuration: LinkPool Ropsten Node 25 | linkToken: "0x20fe562d797a42dcb3399062ae9546cd06f63280", 26 | assetPriceJob: { 27 | id: "740b88dd7d5347bfae116aa65a550ca9", 28 | oracle: "0x83F00b902cbf06E316C95F51cbEeD9D2572a349a", 29 | }, 30 | alphaVantageJob: { 31 | id: "4f5bd067b34a45b0adae559105f3e6fc", 32 | oracle: "0x83F00b902cbf06E316C95F51cbEeD9D2572a349a", 33 | }, 34 | apiAggregatorJob: { 35 | id: "becb68242def4f248faa84374d975d4a", 36 | oracle: "0x83F00b902cbf06E316C95F51cbEeD9D2572a349a", 37 | }, 38 | wolframAlphaJob: { 39 | id: "bdb5a7393629426f8a944f0ccbe6442e", 40 | oracle: "0x83F00b902cbf06E316C95F51cbEeD9D2572a349a", 41 | }, 42 | rapidApiWeather: { 43 | id: "73f03227e40e493f99abbc83e9b9da41", 44 | oracle: "0x83F00b902cbf06E316C95F51cbEeD9D2572a349a", 45 | }, 46 | httpGet: { 47 | id: "c179a8180e034cf5a341488406c32827", 48 | oracle: "0x83F00b902cbf06E316C95F51cbEeD9D2572a349a", 49 | } 50 | }, 51 | development: { 52 | host: "localhost", 53 | port: 8545, 54 | network_id: "*", 55 | gas: 6712390, 56 | 57 | // Chainlink Configuration: Enter your local job ids and oracle addresses 58 | linkToken: "", 59 | assetPriceJob: { 60 | id: "", 61 | oracle: "" 62 | }, 63 | alphaVantageJob: { 64 | id: "", 65 | oracle: "" 66 | }, 67 | apiAggregatorJob: { 68 | id: "", 69 | oracle: "" 70 | }, 71 | wolframAlphaJob: { 72 | id: "", 73 | oracle: "", 74 | }, 75 | rapidApiWeather: { 76 | id: "", 77 | oracle: "", 78 | }, 79 | httpGet: { 80 | id: "", 81 | oracle: "", 82 | } 83 | } 84 | }, 85 | solc: { 86 | optimizer: { 87 | enabled: true, 88 | runs: 200 89 | } 90 | } 91 | }; 92 | -------------------------------------------------------------------------------- /contracts/AlphaVantageConsumer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; 4 | import "chainlink/contracts/Chainlinked.sol"; 5 | 6 | /** 7 | @dev Alpha Vantage documentation: https://www.alphavantage.co/documentation/ 8 | */ 9 | contract AlphaVantageConsumer is Chainlinked, Ownable { 10 | // solium-disable-next-line zeppelin/no-arithmetic-operations 11 | uint256 constant private ORACLE_PAYMENT = 1 * LINK; 12 | 13 | bytes32 public jobId; 14 | 15 | event RequestFulfilled( 16 | bytes32 indexed requestId, 17 | uint256 price 18 | ); 19 | 20 | mapping(bytes32 => bytes32) requests; 21 | mapping(bytes32 => uint256) public prices; 22 | 23 | constructor(address _token, address _oracle, bytes32 _jobId) public { 24 | setLinkToken(_token); 25 | setOracle(_oracle); 26 | jobId = _jobId; 27 | } 28 | 29 | /** 30 | @dev Request a currency exchange rate 31 | @dev This includes Forex and Cryptocurrencies 32 | @param _from The currency you want to use as the base 33 | @param _to The currency to get in quote 34 | */ 35 | function requestExchangeRate(string _from, string _to) public { 36 | Chainlink.Request memory req = newRequest(jobId, this, this.fulfill.selector); 37 | req.add("function", "CURRENCY_EXCHANGE_RATE"); 38 | req.add("from_currency", _from); 39 | req.add("to_currency", _to); 40 | string[] memory path = new string[](2); 41 | path[0] = "Realtime Currency Exchange Rate"; 42 | path[1] = "5. Exchange Rate"; 43 | req.addStringArray("copyPath", path); 44 | req.addInt("times", 100); 45 | bytes32 requestId = chainlinkRequest(req, ORACLE_PAYMENT); 46 | requests[requestId] = keccak256(abi.encodePacked(_from, _to)); 47 | } 48 | 49 | function cancelRequest( 50 | bytes32 _requestId, 51 | uint256 _payment, 52 | bytes4 _callbackFunctionId, 53 | uint256 _expiration 54 | ) 55 | public 56 | onlyOwner 57 | { 58 | cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); 59 | } 60 | 61 | function fulfill(bytes32 _requestId, uint256 _price) 62 | public 63 | recordChainlinkFulfillment(_requestId) 64 | { 65 | emit RequestFulfilled(_requestId, _price); 66 | prices[requests[_requestId]] = _price; 67 | delete requests[_requestId]; 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /contracts/WolframAlphaConsumer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; 4 | import "chainlink/contracts/Chainlinked.sol"; 5 | 6 | /** 7 | @dev WolframAlpha Short Answers API Docs: https://products.wolframalpha.com/short-answers-api/documentation/ 8 | */ 9 | contract WolframAlphaConsumer is Chainlinked, Ownable { 10 | // solium-disable-next-line zeppelin/no-arithmetic-operations 11 | uint256 constant private ORACLE_PAYMENT = 1 * LINK; 12 | string constant public BASE_URL = "http://api.wolframalpha.com/v1/result?i="; 13 | 14 | bytes32 public jobId; 15 | 16 | event RequestFulfilled( 17 | bytes32 indexed requestId, 18 | bytes32 indexed hash, 19 | int256 distance 20 | ); 21 | 22 | event WolframAlphaQuery( 23 | string url 24 | ); 25 | 26 | mapping(bytes32 => bytes32) requests; 27 | mapping(bytes32 => int256) public distances; 28 | 29 | constructor(address _token, address _oracle, bytes32 _jobId) public { 30 | setLinkToken(_token); 31 | setOracle(_oracle); 32 | jobId = _jobId; 33 | } 34 | 35 | /** 36 | @dev Request the distance between two location in miles 37 | @param _from The location from, eg: London 38 | @param _to The location to, eg: Sydney 39 | */ 40 | function requestDistance(string _from, string _to) public { 41 | string memory query = string(abi.encodePacked("What's the distance between ", _from, " and ", _to, "?")); 42 | Chainlink.Request memory req = newRequest(jobId, this, this.fulfill.selector); 43 | req.add("query", query); 44 | req.addInt("index", 1); 45 | req.add("copyPath", "result"); 46 | bytes32 requestId = chainlinkRequest(req, ORACLE_PAYMENT); 47 | requests[requestId] = keccak256(abi.encodePacked(_from, _to)); 48 | 49 | emit WolframAlphaQuery(string(abi.encodePacked(BASE_URL, query))); 50 | } 51 | 52 | function cancelRequest( 53 | bytes32 _requestId, 54 | uint256 _payment, 55 | bytes4 _callbackFunctionId, 56 | uint256 _expiration 57 | ) 58 | public 59 | onlyOwner 60 | { 61 | cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); 62 | } 63 | 64 | function fulfill(bytes32 _requestId, int256 _distance) 65 | public 66 | recordChainlinkFulfillment(_requestId) 67 | { 68 | emit RequestFulfilled(_requestId, requests[_requestId], _distance); 69 | distances[requests[_requestId]] = _distance; 70 | delete requests[_requestId]; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /contracts/AssetPriceConsumer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; 4 | import "chainlink/contracts/Chainlinked.sol"; 5 | 6 | /** 7 | @dev Asset Price GitHub: https://github.com/linkpoolio/asset-price-cl-ea 8 | */ 9 | contract AssetPriceConsumer is Chainlinked, Ownable { 10 | // solium-disable-next-line zeppelin/no-arithmetic-operations 11 | uint256 constant private ORACLE_PAYMENT = 1 * LINK; 12 | 13 | bytes32 public jobId; 14 | 15 | event RequestFulfilled( 16 | bytes32 indexed requestId, 17 | uint256 price 18 | ); 19 | 20 | mapping(bytes32 => bytes32) requests; 21 | mapping(bytes32 => uint256) public prices; 22 | 23 | constructor(address _token, address _oracle, bytes32 _jobId) public { 24 | setLinkToken(_token); 25 | setOracle(_oracle); 26 | jobId = _jobId; 27 | } 28 | 29 | /** 30 | @dev Request the price of an asset quoted in wei 31 | */ 32 | function requestWeiPrice(string _base) public { 33 | requestPrice(_base, "ETH", 1 ether); 34 | } 35 | 36 | /** 37 | @dev Request the price of an asset quoted in sats 38 | */ 39 | function requestSatsPrice(string _base) public { 40 | requestPrice(_base, "BTC", 100000000); 41 | } 42 | 43 | /** 44 | @dev Request the price of an asset quoted in USD with 2 decimal places 45 | */ 46 | function requestUSDPrice(string _base) public { 47 | requestPrice(_base, "USD", 100); 48 | } 49 | 50 | /** 51 | @dev Request the price of an asset quoted in EUR with 2 decimal places 52 | */ 53 | function requestEURPrice(string _base) public { 54 | requestPrice(_base, "EUR", 100); 55 | } 56 | 57 | function requestPrice(string _base, string _quote, int _times) internal { 58 | Chainlink.Request memory req = newRequest(jobId, this, this.fulfill.selector); 59 | req.add("base", _base); 60 | req.add("quote", _quote); 61 | req.add("copyPath", "price"); 62 | req.addInt("times", _times); 63 | bytes32 requestId = chainlinkRequest(req, ORACLE_PAYMENT); 64 | requests[requestId] = keccak256(abi.encodePacked(_base, _quote)); 65 | } 66 | 67 | function cancelRequest( 68 | bytes32 _requestId, 69 | uint256 _payment, 70 | bytes4 _callbackFunctionId, 71 | uint256 _expiration 72 | ) 73 | public 74 | onlyOwner 75 | { 76 | cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); 77 | } 78 | 79 | function fulfill(bytes32 _requestId, uint256 _price) 80 | public 81 | recordChainlinkFulfillment(_requestId) 82 | { 83 | emit RequestFulfilled(_requestId, _price); 84 | prices[requests[_requestId]] = _price; 85 | delete requests[_requestId]; 86 | } 87 | 88 | } -------------------------------------------------------------------------------- /contracts/AliceAndBob.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; 4 | import "chainlink/contracts/Chainlinked.sol"; 5 | 6 | contract AliceAndBob is Chainlinked, Ownable { 7 | using SafeMath for uint256; 8 | uint256 constant private ORACLE_PAYMENT = 1 * LINK; // solium-disable-line zeppelin/no-arithmetic-operations 9 | 10 | address public aliceAddress; 11 | address public bobAddress; 12 | bytes32 public jobId; 13 | 14 | uint256 constant ESCROW_AMOUNT_EUR = 50; 15 | 16 | event DepositMade(uint256 amount); 17 | event RankingReturned(uint256 rank); 18 | 19 | constructor( 20 | address _token, 21 | address _oracle, 22 | bytes32 _jobId, 23 | address _alice, 24 | address _bob 25 | ) Ownable() public { 26 | setLinkToken(_token); 27 | setOracle(_oracle); 28 | jobId = _jobId; 29 | aliceAddress = _alice; 30 | bobAddress = _bob; 31 | } 32 | 33 | function() 34 | external 35 | payable 36 | onlyDepositor 37 | { 38 | emit DepositMade(msg.value); 39 | } 40 | 41 | function checkSiteListing() public { 42 | Chainlink.Request memory req = newRequest(jobId, this, this.fulfillRanking.selector); 43 | req.add("url", "https://pastebin.com/raw/NPXL33mj"); 44 | req.add("path", "ranking"); 45 | chainlinkRequest(req, ORACLE_PAYMENT); 46 | } 47 | 48 | function fulfillRanking(bytes32 _requestId, uint256 _ranking) 49 | public 50 | recordChainlinkFulfillment(_requestId) 51 | { 52 | emit RankingReturned(_ranking); 53 | if (_ranking < 10) { 54 | requestEthereumPrice(); 55 | } 56 | } 57 | 58 | function requestEthereumPrice() 59 | internal 60 | { 61 | Chainlink.Request memory req = newRequest(jobId, this, this.fulfillEthereumPrice.selector); 62 | req.add("url", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); 63 | req.add("path", "EUR"); 64 | req.addInt("times", 100); 65 | chainlinkRequest(req, ORACLE_PAYMENT); 66 | } 67 | 68 | function fulfillEthereumPrice(bytes32 _requestId, uint256 _price) 69 | public 70 | recordChainlinkFulfillment(_requestId) 71 | { 72 | uint256 transferAmount = ESCROW_AMOUNT_EUR.mul(10**20).div(_price); 73 | if (transferAmount <= address(this).balance) { 74 | bobAddress.transfer(transferAmount); 75 | selfdestruct(aliceAddress); 76 | } 77 | } 78 | 79 | function getChainlinkToken() public view returns (address) { 80 | return chainlinkToken(); 81 | } 82 | 83 | function getOracle() public view returns (address) { 84 | return oracleAddress(); 85 | } 86 | 87 | function withdrawLink() public onlyOwner { 88 | LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); 89 | require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer"); 90 | } 91 | 92 | modifier onlyDepositor() { 93 | require(msg.sender == aliceAddress, "Only the depositor may call this function."); 94 | _; 95 | } 96 | 97 | } -------------------------------------------------------------------------------- /contracts/APIAggregatorConsumer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; 4 | import "chainlink/contracts/Chainlinked.sol"; 5 | 6 | contract APIAggregatorConsumer is Chainlinked, Ownable { 7 | // solium-disable-next-line zeppelin/no-arithmetic-operations 8 | uint256 constant private ORACLE_PAYMENT = 1 * LINK; 9 | 10 | bytes32 public jobId; 11 | 12 | event RequestFulfilled( 13 | bytes32 indexed requestId, 14 | uint256 price 15 | ); 16 | 17 | mapping(bytes32 => bytes32) requests; 18 | mapping(bytes32 => uint256) public prices; 19 | 20 | constructor(address _token, address _oracle, bytes32 _jobId) public { 21 | setLinkToken(_token); 22 | setOracle(_oracle); 23 | jobId = _jobId; 24 | } 25 | 26 | /** 27 | @dev Request the price of ETH using Bitstamp and Coinbase, returning a median value 28 | @dev Value is multiplied by 100 to include 2 decimal places 29 | */ 30 | function requestETHUSDPrice() public { 31 | Chainlink.Request memory req = newRequest(jobId, this, this.fulfill.selector); 32 | string[] memory api = new string[](2); 33 | api[0] = "https://www.bitstamp.net/api/v2/ticker/ethusd/"; 34 | api[1] = "https://api.pro.coinbase.com/products/eth-usd/ticker"; 35 | req.addStringArray("api", api); 36 | string[] memory paths = new string[](2); 37 | paths[0] = "$.last"; 38 | paths[1] = "$.price"; 39 | req.addStringArray("paths", paths); 40 | req.add("aggregationType", "median"); 41 | req.add("copyPath", "aggregateValue"); 42 | req.addInt("times", 100); 43 | bytes32 requestId = chainlinkRequest(req, ORACLE_PAYMENT); 44 | requests[requestId] = keccak256("ETHUSD"); 45 | } 46 | 47 | /** 48 | @dev Request the price of BTC using Bitstamp and Coinbase, returning a median value 49 | @dev Value is multiplied by 100 to include 2 decimal places 50 | */ 51 | function requestBTCUSDPrice() public { 52 | Chainlink.Request memory req = newRequest(jobId, this, this.fulfill.selector); 53 | string[] memory api = new string[](2); 54 | api[0] = "https://www.bitstamp.net/api/v2/ticker/btcusd/"; 55 | api[1] = "https://api.pro.coinbase.com/products/btc-usd/ticker"; 56 | req.addStringArray("api", api); 57 | string[] memory paths = new string[](2); 58 | paths[0] = "$.last"; 59 | paths[1] = "$.price"; 60 | req.addStringArray("paths", paths); 61 | req.add("aggregationType", "median"); 62 | req.add("copyPath", "aggregateValue"); 63 | req.addInt("times", 100); 64 | bytes32 requestId = chainlinkRequestTo(oracleAddress(), req, ORACLE_PAYMENT); 65 | requests[requestId] = keccak256("BTCUSD"); 66 | } 67 | 68 | function cancelRequest( 69 | bytes32 _requestId, 70 | uint256 _payment, 71 | bytes4 _callbackFunctionId, 72 | uint256 _expiration 73 | ) 74 | public 75 | onlyOwner 76 | { 77 | cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); 78 | } 79 | 80 | function fulfill(bytes32 _requestId, uint256 _price) 81 | public 82 | recordChainlinkFulfillment(_requestId) 83 | { 84 | emit RequestFulfilled(_requestId, _price); 85 | prices[requests[_requestId]] = _price; 86 | delete requests[_requestId]; 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Example Chainlinks 2 | Example Chainlinks that get data from various sources. Already deployed to Ropsten, you can run the included scripts to easily fetch data on-chain via Chainlink. 3 | 4 | ### Current examples: 5 | 6 | - **AlphaVantage** ([Bridges URL](https://s3.linkpool.io/bridges/alphavantage.json))**:** Forex rates 7 | - **[API Aggregator](https://github.com/linkpoolio/bridges/tree/master/examples/apiaggregator)**: Aggregate values from 8 | multiple APIs for ETH & BTC. 9 | - **[Asset Price](https://github.com/linkpoolio/asset-price-cl-ea):** Specify any crypto pair and get a price aggregated by weighted volume from all supported exchanges 10 | that list a pair. Eg: BTC-USD, LINK-BTC, ETH-USDT, ADA-BTC. 11 | - **[Wolfram Alpha](https://github.com/linkpoolio/bridges/tree/master/examples/wolframalpha):** Find the distance between 12 | two locations in miles using the Short Answers API and natural language. 13 | - **Rapid API (Weather)** ([Bridges URL](https://s3.linkpool.io/bridges/rapidapi.json))**:** Get the temperature, 14 | humidity and windspeeds at any global location. 15 | 16 | ## Install 17 | 18 | Install dependencies with yarn/npm. 19 | 20 | ## General Usage 21 | 22 | To first use this on Ropsten, you can update `truffle.js` with your private key and RPC host for deployment. 23 | This could be Infura or your own node for example. 24 | 25 | **This repository includes the ropsten contract `build` files, so once you set up `truffle.js` you can use the scripts 26 | on the Ropsten network.** 27 | 28 | You can also deploy this locally using `ganache-cli`, but you need to deploy the `Oracle.sol` contract for 29 | your Chainlink node and create a new job spec as per the example you want to use in `specs`. 30 | 31 | ### Setup 32 | 33 | In `truffle.js` enter your mnemonic and Ethereum URL, eg Infura. 34 | 35 | ### Deployment 36 | 37 | To deploy, run a standard Truffle migration (uses Truffle from local deps): 38 | ``` 39 | npm run migrate 40 | ``` 41 | 42 | ### Requesting Data 43 | 44 | #### Alpha Vantage 45 | Request the current rate of the pound to the dollar: 46 | ``` 47 | npm run exec scripts/alphavantage/request.js -- GBP USD --network ropsten 48 | npm run exec scripts/alphavantage/get.js -- GBP USD --network ropsten 49 | ``` 50 | 51 | #### API Aggregator 52 | Request the current price of BTC aggregated from Coinbase & Bitstamp: 53 | ``` 54 | npm run exec scripts/apiaggregator/request.js -- --network ropsten 55 | npm run exec scripts/apiaggregator/get.js -- --network ropsten 56 | ``` 57 | 58 | #### Asset Price 59 | Request the price of BTC-USD aggregated from many exchanges: 60 | ``` 61 | npm run exec scripts/assetprice/request.js BTC USD -- --network ropsten 62 | npm run exec scripts/assetprice/get.js BTC USD -- --network ropsten 63 | ``` 64 | LINK-BTC: 65 | ``` 66 | npm run exec scripts/assetprice/request.js LINK BTC -- --network ropsten 67 | npm run exec scripts/assetprice/get.js LINK BTC -- --network ropsten 68 | ``` 69 | 70 | #### WolframAlpha Location Distance (Short Answers API) 71 | Request the distance between London and Tokyo: 72 | ``` 73 | npm run exec scripts/wolframalpha/request.js London Tokyo -- --network ropsten 74 | npm run exec scripts/wolframalpha/get.js London Tokyo -- --network ropsten 75 | ``` 76 | 77 | #### Rapid API Weather (OpenWeatherMap) 78 | Request the temperature in Celsius: 79 | ``` 80 | npm run exec scripts/rapidapiweather/request.js metricTemp London,uk -- --network ropsten 81 | npm run exec scripts/rapidapiweather/get.js metricTemp London,uk -- --network ropsten 82 | ``` 83 | 84 | Request the humidity percentage: 85 | ``` 86 | npm run exec scripts/rapidapiweather/request.js humidity London,uk -- --network ropsten 87 | npm run exec scripts/rapidapiweather/get.js humidity London,uk -- --network ropsten 88 | ``` 89 | 90 | Request the windspeed in mph: 91 | ``` 92 | npm run exec scripts/rapidapiweather/request.js windSpeed London,uk -- --network ropsten 93 | npm run exec scripts/rapidapiweather/get.js windSpeed London,uk -- --network ropsten 94 | ``` 95 | 96 | 97 | ## Notes 98 | The `truffle.js` ropsten network is configured to point to a [LinkPool](https://linkpool.io) node. 99 | You don't need to change the configuration as our node will accept requests from your contract with no changes. 100 | 101 | Although, you can edit the `jobId` and `oracleAddress` as specified in the Truffle configuration to point to 102 | your own node. 103 | -------------------------------------------------------------------------------- /contracts/RapidAPIWeatherConsumer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; 4 | import "chainlink/contracts/Chainlinked.sol"; 5 | 6 | /** 7 | @dev Rapid API Docs: https://rapidapi.com/community/api/open-weather-map 8 | @dev Open Weather Docs: https://openweathermap.org/current 9 | */ 10 | contract RapidAPIWeatherConsumer is Chainlinked, Ownable { 11 | // solium-disable-next-line zeppelin/no-arithmetic-operations 12 | uint256 constant private ORACLE_PAYMENT = 1 * LINK; 13 | 14 | bytes32 public jobId; 15 | 16 | event RequestFulfilled( 17 | bytes32 indexed requestId, 18 | bytes32 indexed hash, 19 | uint256 weather 20 | ); 21 | 22 | mapping(bytes32 => bytes32) requests; 23 | mapping(bytes32 => uint256) public temps; 24 | mapping(bytes32 => uint256) public humidities; 25 | mapping(bytes32 => uint256) public windSpeeds; 26 | 27 | constructor(address _token, address _oracle, bytes32 _jobId) public { 28 | setLinkToken(_token); 29 | setOracle(_oracle); 30 | jobId = _jobId; 31 | } 32 | 33 | /** 34 | @dev Request the temperature in imperial units (fahrenheit) 35 | @param _location Enter any location as the input, for example: "London,uk", "New York,us" 36 | */ 37 | function requestImperialTemp(string _location) public { 38 | requestWeather(_location, "imperial", "main.temp", 100, this.fulfillTemp.selector); 39 | } 40 | 41 | /** 42 | @dev Request the temperature in imperial units (celsius) 43 | @param _location Enter any location as the input, for example: "London,uk", "New York,us" 44 | */ 45 | function requestMetricTemp(string _location) public { 46 | requestWeather(_location, "metric", "main.temp", 100, this.fulfillTemp.selector); 47 | } 48 | 49 | /** 50 | @dev Request the humidity percentage in a location 51 | @param _location Enter any location as the input, for example: "London,uk", "New York,us" 52 | */ 53 | function requestHumidity(string _location) public { 54 | requestWeather(_location, "", "main.humidity", 1, this.fulfillHumidity.selector); 55 | } 56 | 57 | /** 58 | @dev Request the wind speed in a location returned in mph 59 | @param _location Enter any location as the input, for example: "London,uk", "New York,us" 60 | */ 61 | function requestWindSpeed(string _location) public { 62 | requestWeather(_location, "imperial", "wind.speed", 10, this.fulfillWindSpeed.selector); 63 | } 64 | 65 | function requestWeather( 66 | string _location, 67 | string _units, 68 | string _path, 69 | int256 _times, 70 | bytes4 _selector 71 | ) internal { 72 | Chainlink.Request memory req = newRequest(jobId, this, _selector); 73 | req.add("url", "https://community-open-weather-map.p.rapidapi.com/weather"); 74 | req.add("q", _location); 75 | req.add("copyPath", _path); 76 | req.add("units", _units); 77 | req.addInt("times", _times); 78 | bytes32 requestId = chainlinkRequest(req, ORACLE_PAYMENT); 79 | requests[requestId] = keccak256(abi.encodePacked(_location, _units)); 80 | } 81 | 82 | function cancelRequest( 83 | bytes32 _requestId, 84 | uint256 _payment, 85 | bytes4 _callbackFunctionId, 86 | uint256 _expiration 87 | ) 88 | public 89 | onlyOwner 90 | { 91 | cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); 92 | } 93 | 94 | function fulfillTemp(bytes32 _requestId, uint256 _temp) 95 | public 96 | recordChainlinkFulfillment(_requestId) 97 | { 98 | emit RequestFulfilled(_requestId, requests[_requestId], _temp); 99 | temps[requests[_requestId]] = _temp; 100 | delete requests[_requestId]; 101 | } 102 | 103 | function fulfillHumidity(bytes32 _requestId, uint256 _humidity) 104 | public 105 | recordChainlinkFulfillment(_requestId) 106 | { 107 | emit RequestFulfilled(_requestId, requests[_requestId], _humidity); 108 | humidities[requests[_requestId]] = _humidity; 109 | delete requests[_requestId]; 110 | } 111 | 112 | function fulfillWindSpeed(bytes32 _requestId, uint256 _windSpeed) 113 | public 114 | recordChainlinkFulfillment(_requestId) 115 | { 116 | emit RequestFulfilled(_requestId, requests[_requestId], _windSpeed); 117 | windSpeeds[requests[_requestId]] = _windSpeed; 118 | delete requests[_requestId]; 119 | } 120 | 121 | } --------------------------------------------------------------------------------