Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
您的应用程序不可避免地需要与“现实世界”API进行对话,例如是发送电子邮件,查询更多数据,或充当发起其他处理的信号。 下面让我们探讨如何让以太坊智能合约与脱链服务互通。) r% N5 N% ^8 b/ `: I
简而言之,您可以在处理事务时使智能合约发出事件。一旦事务被挖掘,事件数据就可以读取。在下图中,您可以看到您的DApp发出的事件可以从您的API的任何服务中检索。
) k5 P0 M( o4 g
1 ]9 P# c% y, J目前有两种方法可以获取事件数据:: X2 L, Z; w2 H# s4 c1 t: L
目前有两种方法可以获取事件数据:0 G/ i) \+ x6 c0 C% t  }
选项1:使用getTransactionReceipt
9 o! b0 ^% q9 e. R选项2:为事件注册监听器
2 \! T7 o+ o" l. n1 d; K您可以使用选项1来获取事件数据,但是可能会存在潜在问题,因为在区块被挖掘之前收据是空的。你可以提出调查,但这很难做到。6 G: X; d# y8 J  F8 N1 B
另外,根据网络流量和gasPrice设置,交易可能长时间不会被打包。请注意,事件只有在被挖掘成区块后才会被传播。这意味着可以为任何一个区块调用多个事件。/ ~' g$ B  E& \9 j6 s6 [& X9 C
solidity事件
( F2 p- N& l3 l- u6 W# f: _1 D在solidity里创建事件需要两个步骤:定义事件,发出事件。
0 W( F3 j  M+ d: b' \- m; C! P    pragma solidity ^0.4.18;0 `( t3 A5 }8 [1 b) Y6 H
contract MyContract {  ( z  {! x/ u. ]  m/ y
event Transfer(address indexed from, address indexed to, uint256 value); /* This is an event */  
2 M# t1 r' T6 v! G/ P. A( V2 `function MyContract() {} /* a constructor */  
. J" p0 v  o6 p2 s& Qfunction transfer(address _to) public {   
, l# s' {7 O# A; W Transfer(msg.sender, _to, msg.value);  }}  
# V. M" r' \) e. V5 \& j注意事件Transfer是如何在第5行创建的,然后在函数传输中使用它发出Transfer事件(第10行)。 但会告诉你如何使用一个事件,如果我们用0x123调用传递函数,并从0x4444的地址发送1以太,则事件触发传输事件并应返回[0x4444,0x123,BigNumber(1以太)]。) I" u% D  A, c5 k3 E
监听事件
. }, C' L( _1 r' }. _* |- W, E9 D! G以太坊实现了他们的JSON RPC规范,但任何人都可以用他们选择的语言实现自己的库。 我们将使用Truffle和原始web3 Javascript API。 监听事件的一般流程如下:
1 d! I- I' T+ a) @% L& g1、加载合同组件
- m% A' W, e. f* n2 c, b8 M: J8 O- A! l2、配置web3和使用truffle提供程序9 t- v4 J7 @0 j9 l- _/ `
3、识别网络id7 y4 v- V4 l( X6 G6 ]8 h/ [
4、从合同组件中获取正确的合同地址1 [  y, p0 `) E$ i
5、获取JavaScript合约实例/ H5 g% P* V" r9 c4 V
6、使用可选配置调用contractInstace.NAME_OF_EVENT
( Q3 h" }' Z# U8 x; X下面我们有3个样本使用Truffle,Web3在1.0 beta之前,Web3在1.0 beta之后。
1 P/ _# U* }0 h* _7 v, h3 |7 kTruffle API; s* f: j3 q& K4 l' p8 c) T! s. ]+ X, ]
Truffle是web3的一个很好的包装器,它提供了一些便利功能,使用更加轻松。 看一下下面的代码示例:
5 ]# J+ h5 J3 z5 jconst Web3 = require('web3') // Web3 0.20.4 or web3 1 beta) o' ^+ A& Z0 B" c, }* a( S  p/ s
const truffleContract = require("truffle-contract")7 Z6 }+ k' U  I  C  R# U7 r
const contractArtifact = require('./build/contracts/TutorialToken.json')
8 X- T$ A8 H% J8 L* |const providerUrl = 'http://localhost:8545'; O! l$ X. {# S/ r# Y9 L
const provider = new Web3.providers.HttpProvider(providerUrl)
( V, X/ H) _& [' w/ gconst contract = truffleContract(contractArtifact)
$ {1 g$ u  F9 p1 S) Mcontract.setProvider(provider)& P6 F. j: _( f" {. Y
// dirty hack for web3@1.0.0 support for localhost testrpc, see https://github.com/trufflesuite/truffle-contract/issues/56#issuecomment331084530$ o9 e8 h, z' H4 H
if (typeof contract.currentProvider.sendAsync !== "function") {
, Z+ k- g" q4 [6 z: t contract.currentProvider.sendAsync = function() {      , {% I9 \; m( P% F; l
return contract.currentProvider.send.apply(      
1 }: M( a/ r) w0 Q contract.currentProvider,           . f/ t5 ]3 `) {8 E2 q' P
arguments     : g; L2 k- X$ T8 r/ V
);   
) M  k+ C0 l; v7 |( Q/ Y};  }2 H: ]: i0 B. n, R" v& [* z
contract.deployed()  .then(contractInstance => {   7 b! y0 z+ ?  t4 Y
const event = contractInstance.Transfer(null, {fromBlock: 0}, (err, res) => {    4 s+ C, h8 s4 {& s; {
  if(err) {      
; w; [; M0 {, S! c  throw Error(err)     * e7 h5 r, {/ p& C* e
}    })   
/ ^+ C  H2 Q1 k6 p event.watch(function(error, result){      " K- K5 J5 j. h2 B7 ~; [5 P
if (error) { return console.log(error) }     ' Z' ~9 O6 d* F6 L2 N# c2 k
if (!error) {      
  s0 b+ @" A: i4 t0 [ // DO ALL YOUR WORK HERE!      
) R8 |: `$ ?% b/ a; s5 N let { args: { from, to, value }, blockNumber } = result      
, P% ^& s8 F' q: \ console.log(`----BlockNumber (${blockNumber})----`)        
' G8 F) K5 X: Y. }$ @$ ^2 X& H" `console.log(`from = ${from}`)      
! q" `! Q1 V7 j* {" f( M. G5 ?/ b console.log(`to = ${to}`)       $ c1 i/ C( {! |. ]* l
console.log(`value = ${value}`)      
* d: b2 g; z5 H+ T/ V* V7 ~ console.log(`----BlockNumber (${blockNumber})----`)   ) {( Q& [  u4 F0 w0 H7 e/ I. R# V! j! u
   }   
# T6 k+ [! @. k! u: s })  })
4 x5 z* z% @+ i$ h .catch(e => {   
0 Z  E. ?# k) `3 D; f9 w/ A console.error('Catastrophic Error!')  ' T7 R+ R6 N7 m7 Z. X8 X! n
  console.error(e) - ^+ z1 ?8 S# r! t' g6 z3 s* Z3 ?
})  0 J' J- t) W! X0 B0 f
前9行需要一些模块,并设置truffle和web3能够正常网络通信。 第12-19行作为hack使其与web3一起使用,可以忽略。 工作从第21行开始,带有contract.deployed()。 这是一个很好的truffle辅助函数,可以从创建并保存到./build/contracts的工件中选择正确的合同地址。 返回contractInstance(第23行)后,我们通过调用contractInstance.NAME_OF_EVENT来“创建”该事件。 存在更多选项,可在此处找到。 我从0块中选择,因为它是我们自己的testrpc。 对于您的合同,最好选择更接近合同创建时的块编号。  F3 [% \3 `' ~; C
Raw Web3(0.20.4及以下)( d' h/ p. p6 F) X- x' T" E
对于第二个示例,我们将直接使用Web3。 除了上一个示例中的hack之外,代码流程类似。
. r" R% }* R6 E$ _  const Web3 = require('web3') // Works with web3 0.20.4
4 W% Z( R' [5 s& h6 _% _2 Wconst contractArtifact = require('./build/contracts/TutorialToken.json')
8 d0 _6 J) _9 F' J. ]" a- Y5 yconst web3 = new Web3()
! u' u3 g0 \; A+ n6 B, ^const providerUrl = 'http://localhost:8545'$ W7 N; k1 B( }) I& V
const provider = new Web3.providers.HttpProvider(providerUrl)web3.setProvider(provider)
, h( P; Z; d* z/ ~) Fconst networkId = web3.version.networkconst , N6 Y0 Y- x0 T! d, Y
contractAddr = contractArtifact.networks[networkId].address( V$ O! S% H7 [4 j, Z- O
const TutorialToken = web3.eth.contract(contractArtifact.abi, contractAddr)
7 d. W; z$ E, Q( E9 \const contract = TutorialToken.at(contractAddr)/ H! F; y: E- b! Q9 Y
const event = contract.Transfer()* M3 x0 s* ~' Y0 Z1 p" `
event.watch(function(error, result){   
# Q4 ?: o: T  N+ q if (error) { return console.error(error) }   
- B/ S* ~' D  r6 \% @! l  let { args: { from, to, value }, blockNumber } = result      
9 k; h4 Y3 V! f! n  Mconsole.log(`----BlockNumber (${blockNumber})----`)      7 D( X8 a% r/ o, N1 y9 U7 J
console.log(`from = ${from}`)      8 w) K2 B: b1 R* K5 S' N3 ]# }+ @
console.log(`to = ${to}`)      
9 V; F8 V" f- Z% `! m6 A' g4 N4 lconsole.log(`value = ${value}`)      
# v+ X# l* }* Gconsole.log(`----BlockNumber (${blockNumber})----`)  });  2 ^# ]" t( g$ H/ t7 z- Z4 @: |/ w
最重要的区别是第9-12行,我们手动从组件中抓取正确的网络。 我们没有很好的truffle.deployed功能来实现这一步。 现在我们在truffle示例中执行与之前相同的操作,并通过调用contract.NAME_OF_EVENT来创建事件。 在这个版本中我没有放一个块号,但是你可以传递与truffle版相同的东西。) n3 {% ^$ S0 a$ v3 ~( U( S/ o) Y
Raw Web3 1.0.0 beta
! U9 c7 J/ d' B9 e! b/ _: _Web3确实为API带来了大量更改。 一个重大变化是我们必须使用webSockProvider来注册事件而不是httpProvider。% }; ?5 m2 z. E1 t
const Web3 = require('web3') // Works with web3 1.0.0-beta27
1 ?* A. Q! [* q4 b. b1 sconst contractArtifact = require('./build/contracts/TutorialToken.json')& t7 q, B: }7 ]! r# T1 r
const web3 = new Web3()0 M' ]6 c! _5 j
const 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.06 V7 h9 y2 o2 h  q; ^; C% x
const provider = new Web3.providers.WebsocketProvider(providerUrl)! Y/ f% `) L& A4 \3 F
web3.setProvider(provider)
; ~5 c- q- W0 P8 ~0 J& M2 Sweb3.eth.net.getId()  .then(networkId => {   8 U% c8 r  U4 x9 f; r" z/ _
const contractAddr = contractArtifact.networks[networkId].address   
0 j" b) T8 s! m& A, J- Aconst TutorialToken = new web3.eth.Contract(contractArtifact.abi, contractAddr)    ; |/ G" I; W* i2 w; L
TutorialToken.events.Transfer({fromBlock: 0},
9 w  S& D8 I9 |  P* F2 q0 u function(error, event){ console.log(error) })      
. b/ ?" |8 d: d" U.on('data', (log) => {       9 k( `2 s+ c* m2 {# n/ @
let {
8 c$ G# [- c8 [/ n& I0 Y! {3 _  greturnValues: { from, to, value }, blockNumber } = log    - j* b/ s& C* k3 v+ c
    console.log(`----BlockNumber (${blockNumber})----`)        $ W) x7 B6 Q4 b' A2 K
console.log(`from = ${from}`)      5 N! t) R' l0 k: S3 E8 d" S
  console.log(`to = ${to}`)       $ Y! ^3 p/ o% R6 O; K
console.log(`value = ${value}`)        
" j$ o0 Z( R& S1 u# xconsole.log(`----BlockNumber (${blockNumber})----`)     
1 x7 i2 K2 y$ `& D. V  Q; v })      : V* R! \, w( T2 b% H7 S1 P
.on('changed', (log) => {     3 w, ]! T6 N/ ^$ ]2 b- p
   console.log(`Changed: ${log}`)   
9 x( e- E$ ~" O2 U: c4 F  })      .on('error', (log) => {   
; k6 {, E- _5 Y8 @. G* p( j3 B+ n$ q     console.log(`error:  ${log}`)    + U  j$ v9 m1 O. q
  })  })  
1 y! P) I% u. C6 z! K4 v5 Q' ~此外,获取networkId也已更新。 但过程是一样的。 我们使用web3.eth.net.getId()获取networkId,然后从Artifact中选择正确的合同地址。 初始化合同现在是一个类构造函数,在web3.eth.Contract中有一个大写C. 最后,我们创建了事件监听器。 我们现在必须自己处理“数据”,“更改”和“错误”事件。 之前它包含在前面2个示例中的watch功能中。
3 ?, z! j" [; @; S6 H" A总结0 a5 X7 d' i' \. s$ Q+ k# x+ w% N! s
您应该了解如何将您的offchain服务连接到onchain事件。 这意味着您现在可以将区块链集成到现有基础架构中。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

李悔之2015 初中生
  • 粉丝

    1

  • 关注

    0

  • 主题

    13