Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
您的应用程序不可避免地需要与“现实世界”API进行对话,例如是发送电子邮件,查询更多数据,或充当发起其他处理的信号。 下面让我们探讨如何让以太坊智能合约与脱链服务互通。& @4 j' L1 B% _$ e) L
简而言之,您可以在处理事务时使智能合约发出事件。一旦事务被挖掘,事件数据就可以读取。在下图中,您可以看到您的DApp发出的事件可以从您的API的任何服务中检索。4 d# u* `5 P1 K& O* v
8 B( E) G" z( D* ^6 _& i+ D
目前有两种方法可以获取事件数据:5 s* s% T: D- z2 R
目前有两种方法可以获取事件数据:# J& J7 s5 P: Q& O% r, T3 C
选项1:使用getTransactionReceipt; o% _3 ^* }; V  s% e8 ?
选项2:为事件注册监听器
/ c4 _6 a$ e+ y3 L# j! x您可以使用选项1来获取事件数据,但是可能会存在潜在问题,因为在区块被挖掘之前收据是空的。你可以提出调查,但这很难做到。8 u' {2 J( O  A3 O0 `  K
另外,根据网络流量和gasPrice设置,交易可能长时间不会被打包。请注意,事件只有在被挖掘成区块后才会被传播。这意味着可以为任何一个区块调用多个事件。
( S7 s/ F% f; t- M. Asolidity事件& Y" m- j5 N0 R0 E
在solidity里创建事件需要两个步骤:定义事件,发出事件。
9 f. @4 y/ U9 [! [    pragma solidity ^0.4.18;
- t  v. n* `5 a# k; Ucontract MyContract {  
+ F, D0 W" @/ C1 b: levent Transfer(address indexed from, address indexed to, uint256 value); /* This is an event */  * d8 [0 ^: }2 {4 d% Z
function MyContract() {} /* a constructor */  
5 Z0 E. w3 C' l- Ufunction transfer(address _to) public {   % T* C1 o1 T9 Z) ]5 _  P
Transfer(msg.sender, _to, msg.value);  }}  
- F. z! p! K! `/ p- J- s$ V1 }+ _注意事件Transfer是如何在第5行创建的,然后在函数传输中使用它发出Transfer事件(第10行)。 但会告诉你如何使用一个事件,如果我们用0x123调用传递函数,并从0x4444的地址发送1以太,则事件触发传输事件并应返回[0x4444,0x123,BigNumber(1以太)]。
% B. y+ k$ Q* i  u监听事件, I, f8 `6 C" K* [
以太坊实现了他们的JSON RPC规范,但任何人都可以用他们选择的语言实现自己的库。 我们将使用Truffle和原始web3 Javascript API。 监听事件的一般流程如下:
+ ?: m8 t1 V& O/ O9 A1、加载合同组件
9 Y* O* C# r- g! \  F& X" I2、配置web3和使用truffle提供程序) C# z- I- `8 M! Q9 z
3、识别网络id
0 d8 t( c  ^( t$ E4、从合同组件中获取正确的合同地址
/ M- W& V/ `5 f% q5、获取JavaScript合约实例
# W* I* N; }+ _: m& G* W% Y6、使用可选配置调用contractInstace.NAME_OF_EVENT7 z( `! k3 S- e# ^
下面我们有3个样本使用Truffle,Web3在1.0 beta之前,Web3在1.0 beta之后。8 u( @4 O  Q0 B2 D) T+ j* l- y
Truffle API
) h5 q: M% U2 h( T4 w3 d) GTruffle是web3的一个很好的包装器,它提供了一些便利功能,使用更加轻松。 看一下下面的代码示例:
, P0 _$ p# [% F6 c* F6 Fconst Web3 = require('web3') // Web3 0.20.4 or web3 1 beta
5 K+ L/ h  c) o; x( P/ Lconst truffleContract = require("truffle-contract")" U' t2 h7 U2 z- x9 d& r5 Z
const contractArtifact = require('./build/contracts/TutorialToken.json'). f; Q! |( z2 M
const providerUrl = 'http://localhost:8545'8 \& @; X) s) {  D  Q
const provider = new Web3.providers.HttpProvider(providerUrl)
4 t+ u& |1 p, b/ U6 X4 Fconst contract = truffleContract(contractArtifact)
! b5 c4 W$ ~/ L: o' K) r! y( u2 @contract.setProvider(provider)
# p2 Z0 f: i7 `$ R# l  k2 ^// dirty hack for web3@1.0.0 support for localhost testrpc, see https://github.com/trufflesuite/truffle-contract/issues/56#issuecomment331084530
+ c9 K# z8 h. V( ]4 }. r( Zif (typeof contract.currentProvider.sendAsync !== "function") { , O3 s6 H# W4 ^/ l4 r/ {5 d6 b
contract.currentProvider.sendAsync = function() {      
; U0 W+ X' X0 L7 S; a4 i3 Ureturn contract.currentProvider.send.apply(      
) {1 j4 d5 {  T" _6 m9 k contract.currentProvider,           
* J0 G6 [" _2 u0 p  O. z5 S  I- n+ X arguments     & b- l3 K, i) H" W5 f; [
);    9 I1 f2 _1 b: r, P
};  }
; ~9 C& [3 g  O2 z' S! \: tcontract.deployed()  .then(contractInstance => {   & |# ]2 a* k% G+ w1 Z
const event = contractInstance.Transfer(null, {fromBlock: 0}, (err, res) => {    # x( D- k% c! w
  if(err) {      3 [- U3 {; e/ g- F0 X1 H5 a
  throw Error(err)     
2 {- d' n! r/ L8 h" F5 m; `8 ] }    })   & N8 j1 F9 O% |& u6 G  n4 B# D
event.watch(function(error, result){      
- b: o+ m8 a4 y/ f1 _6 Y  _/ B- J5 Oif (error) { return console.log(error) }     ) |3 M- T3 X: W; f: [# X( {% R
if (!error) {       ! O# u8 P, F; b( p8 O& V( b
// DO ALL YOUR WORK HERE!      
$ d3 b$ L2 w+ ~7 k/ C/ @ let { args: { from, to, value }, blockNumber } = result       : S' ^: C# |  z7 L+ F: C/ {3 I* \
console.log(`----BlockNumber (${blockNumber})----`)        : ^$ \, e6 j3 x6 Q
console.log(`from = ${from}`)      
) P$ K" }# L9 u; @$ g1 } console.log(`to = ${to}`)       ' n- o/ G% O- [
console.log(`value = ${value}`)       6 Y- S0 B0 z$ u' N0 b9 \# b
console.log(`----BlockNumber (${blockNumber})----`)   
7 u% G  c" R1 y* U% {0 a. w7 H; ^   }   : j7 u( |" Y/ J  M; ]- g  o
})  })
& U) {& g7 h  K/ d, k .catch(e => {   
) l" Q5 \& L' }; ? console.error('Catastrophic Error!')  4 q; r9 n5 S# Y6 h6 i% t# R
  console.error(e)
) A6 B- b% ?6 }+ L })  
7 h/ w% z5 s/ M3 E7 _前9行需要一些模块,并设置truffle和web3能够正常网络通信。 第12-19行作为hack使其与web3一起使用,可以忽略。 工作从第21行开始,带有contract.deployed()。 这是一个很好的truffle辅助函数,可以从创建并保存到./build/contracts的工件中选择正确的合同地址。 返回contractInstance(第23行)后,我们通过调用contractInstance.NAME_OF_EVENT来“创建”该事件。 存在更多选项,可在此处找到。 我从0块中选择,因为它是我们自己的testrpc。 对于您的合同,最好选择更接近合同创建时的块编号。
& K. z. V3 M7 q# JRaw Web3(0.20.4及以下)
5 s6 g+ N! @) c% y6 X  {' `; I对于第二个示例,我们将直接使用Web3。 除了上一个示例中的hack之外,代码流程类似。
/ E+ }/ C) }  v2 ^" {" K$ P2 e+ o  const Web3 = require('web3') // Works with web3 0.20.4
: [1 C7 w# x, t& R: Gconst contractArtifact = require('./build/contracts/TutorialToken.json')' p. g  d5 O7 n% Y: p
const web3 = new Web3(); m) P) W0 ^6 ~2 r5 ^9 \
const providerUrl = 'http://localhost:8545'
! ^: u5 N/ f6 P2 s6 k8 zconst provider = new Web3.providers.HttpProvider(providerUrl)web3.setProvider(provider)
2 s1 R1 j; X" [+ ^# }) F6 wconst networkId = web3.version.networkconst $ b$ a9 X$ y, C. h% n5 {3 S
contractAddr = contractArtifact.networks[networkId].address5 u' ^7 X# v( b9 q/ `/ r
const TutorialToken = web3.eth.contract(contractArtifact.abi, contractAddr)8 C( z* Z3 G& l' {
const contract = TutorialToken.at(contractAddr)
. h; {7 D& f2 g2 _9 V/ A' l& M" qconst event = contract.Transfer()
; Z$ u3 c) z7 r. k5 N9 uevent.watch(function(error, result){   
1 k8 _" g8 d* v0 F1 {! K+ S1 A if (error) { return console.error(error) }      f" ?* Z$ H2 ]
  let { args: { from, to, value }, blockNumber } = result      
* s% I( g7 h; nconsole.log(`----BlockNumber (${blockNumber})----`)      % J$ R+ i! q* @$ k. e
console.log(`from = ${from}`)      * t/ k( r2 N  `5 j9 M; g0 l5 a
console.log(`to = ${to}`)      3 P2 ^3 C( ]; p" d% t
console.log(`value = ${value}`)      
5 v/ E" b: l3 C$ F" }console.log(`----BlockNumber (${blockNumber})----`)  });  & U1 O. K5 H6 x# r/ b, D
最重要的区别是第9-12行,我们手动从组件中抓取正确的网络。 我们没有很好的truffle.deployed功能来实现这一步。 现在我们在truffle示例中执行与之前相同的操作,并通过调用contract.NAME_OF_EVENT来创建事件。 在这个版本中我没有放一个块号,但是你可以传递与truffle版相同的东西。) N* d3 _( i- s. Z  @! [, `( s
Raw Web3 1.0.0 beta
2 D& n% c3 i, _& d+ X6 kWeb3确实为API带来了大量更改。 一个重大变化是我们必须使用webSockProvider来注册事件而不是httpProvider。$ u& i; I; U7 v  I, J
const Web3 = require('web3') // Works with web3 1.0.0-beta27
* X4 l. H5 C+ a+ B8 A2 Qconst contractArtifact = require('./build/contracts/TutorialToken.json')9 w! b7 s' _/ k# L3 ~, n9 m
const web3 = new Web3()
5 s5 `) M3 j" x, h* j# T3 sconst providerUrl = 'ws://localhost:8545' // requires # https://github.com/trufflesuite/ganache-cli/releases/tag/v7.0.0-beta.0 or https://github.com/trufflesuite/ganache/releases/tag/v1.1.0-beta.0
2 A; N7 ~' m- o# econst provider = new Web3.providers.WebsocketProvider(providerUrl)/ ]% V$ g6 F$ Y3 ~8 V4 t
web3.setProvider(provider)
1 K; u4 `9 q5 {8 h! g( [- qweb3.eth.net.getId()  .then(networkId => {   
# N; D$ N$ G: k3 P: @ const contractAddr = contractArtifact.networks[networkId].address    % y$ r" ^4 o# S7 L; Q
const TutorialToken = new web3.eth.Contract(contractArtifact.abi, contractAddr)    0 ]: X7 W7 m* P) ]2 q  Q. ]3 M+ N
TutorialToken.events.Transfer({fromBlock: 0}, $ b! j: H& O! J* e, k$ l
function(error, event){ console.log(error) })      # U# c7 f4 I: s+ z- C0 w' y' G
.on('data', (log) => {      
1 L7 z! Q* Z% M* k( M" N$ R let { 3 k, J  }5 x7 ~% E
returnValues: { from, to, value }, blockNumber } = log   
0 F+ f2 y3 h' {& t6 y8 x7 T5 @    console.log(`----BlockNumber (${blockNumber})----`)        
) ?2 y. s+ d: w7 G  `7 e  Wconsole.log(`from = ${from}`)      
9 ^3 x: @2 h6 [" G  console.log(`to = ${to}`)      
9 c$ l( Q0 p5 `& W$ ~ console.log(`value = ${value}`)        
1 A1 \0 |1 x) o% N. Xconsole.log(`----BlockNumber (${blockNumber})----`)     8 h# F4 k: k- t/ a
})      ) u( u% w; p+ ^/ h9 G0 t) Q% ?
.on('changed', (log) => {     
0 Q5 i7 J5 |3 }. E' _4 b2 S/ p   console.log(`Changed: ${log}`)   
' D. @6 `$ g6 h; a9 u: s  })      .on('error', (log) => {   1 R3 j0 I* h+ P: e( R- Q& H
     console.log(`error:  ${log}`)   
  ?, `1 N: Z  m$ o* `8 t  l0 B  })  })  ; Q* z6 D, E0 W  f! k
此外,获取networkId也已更新。 但过程是一样的。 我们使用web3.eth.net.getId()获取networkId,然后从Artifact中选择正确的合同地址。 初始化合同现在是一个类构造函数,在web3.eth.Contract中有一个大写C. 最后,我们创建了事件监听器。 我们现在必须自己处理“数据”,“更改”和“错误”事件。 之前它包含在前面2个示例中的watch功能中。
# Y) K- m- }" S; ]1 v总结
6 L8 Y  g1 u! T5 i$ q$ o0 l  G# c. f您应该了解如何将您的offchain服务连接到onchain事件。 这意味着您现在可以将区块链集成到现有基础架构中。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

李悔之2015 初中生
  • 粉丝

    1

  • 关注

    0

  • 主题

    13