Web3.js 1.0构建以太坊Oracle

Posted 汇智网

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Web3.js 1.0构建以太坊Oracle相关的知识,希望对你有一定的参考价值。

以太坊oracle:一个人们可能会在Meetups听到或其他技术活动中被抛出的非常模糊的术语。如果你不了解,你可能没有意识到区块链oracle只是一个离线数据源的专门案例,它通过响应合约中的链上事件与以太坊EVM进行交互。这可能听起来似乎挺复杂,但实际上并非如此——只需坚持几分钟。

oracle的主要关注点是在合约要求时将外部数据返回合约。这些数据可以是合约开展业务所需的任何数据:存储在数据库中的客户数量,由40年历史的大型机计算的精算风险评估。在本文中,我们将关注通过易于使用的Dark Sky weather forecast API获得的请求洛杉矶温度时的数据。

Chatty合约

人们需要开始与外界联系,以太坊虚拟机也不例外。否则,它只会是另一个孤立的书呆子,坐在周围,害羞只与自己说话。EVM是一种社交动物,它让你知道它想要聊天的方式是发射一个事件(希望有人在听)。在oracle的情况下,该事件会告诉你合约想要谈论的内容,你要提供的信息以及有时你如何加入对话。如果正在运行的合约是礼貌的话,如果你想知道,它甚至可以通过让你知道你做了什么来完成对话。然而,就像脱衣舞娘和律师一样,对EVM的讨厌会花钱,所以我们将不必要的调情保持在最低限度。

无论如何,让我们开始构建我们的Weather oracle。我们使用的是Web3.js 1.0,它的工作方式与0.2.x版本略有不同。我们还使用Ganache作为testnet,它可以很好地处理Websockets连接和事件。除了Node和javascript之外,你不需要Truffle或Embark或其他工具——oracle将为你编译和部署合约。

确保安装了最新的Solidity编译器以及solc npm软件包。并且不要忘记安装针对Dark Sky的出站HTTP调用的请求包。

如果你想在家里玩,oracle和测试客户端的完整代码位于https://github.com/robinagist/EthereumWeatherOracle。为了清楚起见,有一些冗余。(注意:我在Javascript和Node上有一点菜鸟,但不是软件,所以请原谅我可能已经Python化了你心爱的Javascript,Python和Go是我的主要语言。)

你还需要在https://darksky.net上获得一个Dark Sky API帐户。

细节

过程很简单:

  • 一个帐户(EOA或合约)调用主合约上的方法,询问一些离线数据,然后回归其业务。

  • 合约方法与在执行期间发出的事件相关联。

Web3.js 1.0构建以太坊Oracle

合约

我们的合约很简单。除了通常的潜在交互者(与构造函数的合约)之外,我们有两种方法和两种事件。第一个被调用的方法是request。请求没有参数,并且它的唯一目的是在被调用时发出一个TempRequest事件,希望它被oracle选中。如果我们的oracle选择事件,它会调用Dark Sky获取最新数据,然后使用当前温度调用fill方法。fill方法需要无符号整数作为参数,将合约变量temp设置为传递的值并以当前温度作为参数触发FilledRequest事件。(注意:这里不需要返回值 - 我们只是为了控制台输出而在这里传递它们。)

pragma solidity ^0.4.21;

contract WeatherOracle {

    address public owner;
    uint public temp;
    uint public timestamp;

    event TempRequest(address sender);
    event FilledRequest(uint rtemp);

    function constructor() public {
        temp = 0;
        owner = msg.sender;
    }

    function request() public returns (string) {
        emit TempRequest(msg.sender);
        return "sent";
    }

    function fill(uint rtemp) public returns (uint){
        temp = rtemp;
        emit FilledRequest(rtemp);
        return temp;
    }


}

代码

只是一个标准的设置。我们宣布abi以便以后分配。该帐户是Ganache帐户。

要注意的一件事(特别是如果你使用过Web3.js的早期版本)是我们现在正在使用Websockets。这为我们提供了真正的点对点功能,并且无需轮询即可捕获事件通知。

// SETUP //
let Web3 = require('web3')
let fs = require('fs')
let request = require('request')

// using Websockets URL.  Ganache works w/ Web3 1.0 and Websockets
const testNetWS = "ws://127.0.0.1:7545"

// create a WebsocketProvider
const web3 = new Web3(new Web3.providers.WebsocketProvider(testNetWS))

// account address
const account = "0xf17f52151EbEF6C7334FAD080c5704D77216b732"

// we're using the Dark Sky API - get your API key at darksky.net
const apiKey = "GetYourOwnKey"
// using the Dark Sky API - getting the forecast, centered on LA
let url= "https://api.darksky.net/forecast/"+apiKey+"/37.8267,-122.4233"
// store the ABI for the contract so we can use it later
let abi = null
// LOAD, COMPILE, DEPLOY //
// load, compile and deploy the included contract (contract.sol)
let c = loadCompileDeploy("contract.sol", ":WeatherOracle").then(function(address) {
    console.log("contract address: " + address)
    startListener(address)
}, function(err) {
    console.log("didn't work.  here's why: " + err)
})
// EVENT LISTENER //
function startListener(address) {
    console.log("starting event monitoring on contract: " + address)
    let myContract = new web3.eth.Contract(abi, address);
    myContract.events.TempRequest({fromBlock: 0, toBlock: 'latest'
    }, function(error, event){ console.log(">>> " + event) })
        .on('data', (log) => {
            console.log("event data: " + JSON.stringify(log, undefined, 2))
            handler(address)
        })
        .on('changed', (log) => {
            console.log(`Changed: ${log}`)
        })
        .on('error', (log) => {
            console.log(`error:  ${log}`)
        })
}
// REQUEST HANDLER //
// handles a request event and sends the response to the contract
function handler(address) {
    request(url, function(error, response, body) {
        if(error)
            console.log("error: " + error)

        console.log("status code: " + response.statusCode)
        let wx = JSON.parse(body)
        let temperature = Math.round(wx.currently.temperature)
        console.log("temp: " + temperature)

        // run the 'fill' method on the contract
        let MyContract = new web3.eth.Contract(abi, address);
        MyContract.methods.fill(temperature).call()
            .then(function(result) {
                console.log("call result: " + result)
                if (temperature == result)
                    console.log("+++success+++")
            }, function(error) {
                console.log("error "  + error)
            })

    })
}

启动Oracle

  • Clone the repo

    https://github.com/robinagist/EthereumWeatherOracle

  • 配置你的Dark Sky API密钥和Ganache的帐户。

  • 运行npm install

  • 运行oracle:node wxoracle.js

测试客户端

此外,从Ganache获取帐户并粘贴帐户。

// account address
const account = "0xC5fdf4076b8F3A5357c5E395ab970B5B54098Fef"

'''
'''
// cut and paste the deployed contract address
const address = "contract address here"

运行测试客户端

启动一个新终端,然后在提示符下键入node wxclient

目前,测试客户端编译contract.sol文件以获取ABI,这对于此示例来说是不必要的,但很快。我就不进入测试客户端的工作。这很简单。

如果你正在观看oracle输出,你应该看到如下内容:

Web3.js 1.0构建以太坊Oracle

在测试客户端上,从另一个终端运行:

你可以从oracle的输出中看到它从Dark Sky获得了200状态代码,并且圆形温度为53(对于LA来说太冷了)。温度存储在合约存储中,并触发另一个事件以通知监听器新的温度可用。

结论

Web3 1.0和Websockets使oracle构建成为一个快照。你不再需要构建轮询事件的系统。

其他oracle教程要么过时,要么太复杂。我试图保持这个简单的,并保持像Truffle和Embark这样的工具,所以你可以看到一切真的如何工作。oracle进行自己的部署,oracle和test客户端都编译并生成自己的ABI(虽然我会优化它,所以没有那么多的编译和剪切和粘贴)。

文章来自官方博客:

http://blog.hubwiz.com。您也可以直接点击左下角的“阅读原文”进行访问。

已经覆盖以下编程技术,发送相应的文字会获取对应教程的信息:

区块链以太坊EOS比特币Tendermint、Node.jsMongoDB、JavaScript、C、C#、php、Python、AngularjsIonic、React、UML、redis、mysqlnginx、CSS、htmlBootstrap、Flask、Gulp、Mocha、Git、Meteor、Canvas、zebra、Typescript、Material Design Lite、ECMAScript、Elasticsearch、Mongoose、jQuery、d3.js、django、cheerioSVG、phoneGap、jQueryMobile、Saas、YAML、Vue.js、webpack、Firebird、jQuery Easy UI、ruby、asp.net、c++、Express......



以上是关于Web3.js 1.0构建以太坊Oracle的主要内容,如果未能解决你的问题,请参考以下文章

使用 web3.js 将新合约部署到以太坊网络

以太坊系列 - Web3.js

以太坊 web3.js 文档翻译及说明

Web3.js的基本使用(与以太坊智能合约的交互)

Web3.js

如何通过web3.js通过余额获得前N个以太坊账户?