Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
您的应用程序不可避免地需要与“现实世界”API进行对话,例如是发送电子邮件,查询更多数据,或充当发起其他处理的信号。 下面让我们探讨如何让以太坊智能合约与脱链服务互通。
4 ]) O5 [8 i" C! f! X, [简而言之,您可以在处理事务时使智能合约发出事件。一旦事务被挖掘,事件数据就可以读取。在下图中,您可以看到您的DApp发出的事件可以从您的API的任何服务中检索。
6 Q1 ^/ Y2 l7 z: J2 o# ?
+ |  U3 b5 @, e8 N目前有两种方法可以获取事件数据:# u& q$ `9 q" }5 E
目前有两种方法可以获取事件数据:, q+ `2 p' O( ^% K+ P4 q: U
选项1:使用getTransactionReceipt& S, c# B4 M6 O
选项2:为事件注册监听器' X! ~$ h: w) o. I* r+ g8 g
您可以使用选项1来获取事件数据,但是可能会存在潜在问题,因为在区块被挖掘之前收据是空的。你可以提出调查,但这很难做到。
, \! Z. n* {- f. U: ~另外,根据网络流量和gasPrice设置,交易可能长时间不会被打包。请注意,事件只有在被挖掘成区块后才会被传播。这意味着可以为任何一个区块调用多个事件。
" U% k! T6 m+ D$ C0 y- m8 \solidity事件9 Z) ]! G; G8 W  ]! j8 j
在solidity里创建事件需要两个步骤:定义事件,发出事件。
0 _; I' ~1 c" a5 Z+ _: w' r    pragma solidity ^0.4.18;: g6 _3 ?* b% ^4 ~% T
contract MyContract {  0 G6 x" q* `  f; x" r. P5 _
event Transfer(address indexed from, address indexed to, uint256 value); /* This is an event */  ; x( A2 o8 N+ I- i
function MyContract() {} /* a constructor */  
) D' F' q" l2 _! \function transfer(address _to) public {   
0 B" z  \1 N  c" @% G+ k Transfer(msg.sender, _to, msg.value);  }}  
, V! P; F2 h- T注意事件Transfer是如何在第5行创建的,然后在函数传输中使用它发出Transfer事件(第10行)。 但会告诉你如何使用一个事件,如果我们用0x123调用传递函数,并从0x4444的地址发送1以太,则事件触发传输事件并应返回[0x4444,0x123,BigNumber(1以太)]。/ X( b  A. V: m, [1 @) S' j) {
监听事件
+ |4 o2 M$ Y4 C7 ]5 ^) g以太坊实现了他们的JSON RPC规范,但任何人都可以用他们选择的语言实现自己的库。 我们将使用Truffle和原始web3 Javascript API。 监听事件的一般流程如下:
! i& r# H9 X, {1 u1、加载合同组件( L$ K8 q6 V. F( j4 K, t% m% K
2、配置web3和使用truffle提供程序$ d' N+ \, m* ]5 S! z
3、识别网络id% f8 T9 u) Q$ z- N, r
4、从合同组件中获取正确的合同地址
0 E; C5 J. k( A+ b6 D/ Y# l5、获取JavaScript合约实例
  b! P$ J) `( Q6、使用可选配置调用contractInstace.NAME_OF_EVENT! r+ x" t; @+ H# h
下面我们有3个样本使用Truffle,Web3在1.0 beta之前,Web3在1.0 beta之后。
; M& {8 J. d" ?$ a6 i" PTruffle API$ T5 ~/ [! H# A7 f' w
Truffle是web3的一个很好的包装器,它提供了一些便利功能,使用更加轻松。 看一下下面的代码示例:
) M( [2 I3 @2 B$ P7 E0 X( A; iconst Web3 = require('web3') // Web3 0.20.4 or web3 1 beta% w  o2 n/ ]+ Q* U
const truffleContract = require("truffle-contract")! `, @. x  t' ~) O
const contractArtifact = require('./build/contracts/TutorialToken.json')
$ i* T. W+ k0 y% U) }, Uconst providerUrl = 'http://localhost:8545'
. ?5 ~4 e, f  k/ z% \const provider = new Web3.providers.HttpProvider(providerUrl)
: r! U/ T6 }3 bconst contract = truffleContract(contractArtifact)
3 i- ]& M3 W+ V3 ?. N% ucontract.setProvider(provider)' c3 f+ Y+ V2 }! ~
// dirty hack for web3@1.0.0 support for localhost testrpc, see https://github.com/trufflesuite/truffle-contract/issues/56#issuecomment331084530) ^. [, O5 k! U5 x/ `& G; Q
if (typeof contract.currentProvider.sendAsync !== "function") { * N: e" [3 d% E+ a+ A
contract.currentProvider.sendAsync = function() {      
0 W6 n# t9 L* \return contract.currentProvider.send.apply(       - Z" E. P! e# }  a4 S
contract.currentProvider,           ' `9 e0 O$ b5 `- c" E7 O9 n
arguments     
& W3 J" T+ G( d );    - Q  }9 l6 t" q7 c
};  }- [( t- W- Y  i( ]. R+ i: S
contract.deployed()  .then(contractInstance => {   
/ `' k9 j0 r! g- v, V" O const event = contractInstance.Transfer(null, {fromBlock: 0}, (err, res) => {   
6 a2 o* k; [, b& v$ `2 y  if(err) {      8 M7 d8 T$ d' f: M) ^" t
  throw Error(err)     ! Z2 d7 A. s( N+ w
}    })   
" F* y# }6 ]/ E event.watch(function(error, result){      
% a; B  T) D# b# X3 O! Iif (error) { return console.log(error) }     ' L* y" [( I+ m9 r; |8 [7 v
if (!error) {       / K3 X, s3 o( t  G8 d: o9 L! T- H
// DO ALL YOUR WORK HERE!      
& S! m( a: Q9 T, L4 w: D5 Y- a$ @ let { args: { from, to, value }, blockNumber } = result       # X# ^  O" p$ E1 ~
console.log(`----BlockNumber (${blockNumber})----`)        / Y' G; P2 q: \/ d. b& V
console.log(`from = ${from}`)      
/ r5 \. _0 s7 I console.log(`to = ${to}`)       / M' S5 H+ q3 O% D6 i! G1 }
console.log(`value = ${value}`)      
" M: C0 V+ f* V0 c0 z8 P& Q- G console.log(`----BlockNumber (${blockNumber})----`)   # \) q7 B* w/ m6 K
   }   
: o& p" T, i0 q  S7 U9 ` })  }) % w( r7 m) `0 u
.catch(e => {   
/ p2 U$ o5 f4 L* S console.error('Catastrophic Error!')  - r( j- B2 `( [+ T) `9 x( a6 K5 S: Q
  console.error(e) & f0 ~* M# O' G8 G8 g9 h
})  2 C9 H* D6 S! H+ `; E& `
前9行需要一些模块,并设置truffle和web3能够正常网络通信。 第12-19行作为hack使其与web3一起使用,可以忽略。 工作从第21行开始,带有contract.deployed()。 这是一个很好的truffle辅助函数,可以从创建并保存到./build/contracts的工件中选择正确的合同地址。 返回contractInstance(第23行)后,我们通过调用contractInstance.NAME_OF_EVENT来“创建”该事件。 存在更多选项,可在此处找到。 我从0块中选择,因为它是我们自己的testrpc。 对于您的合同,最好选择更接近合同创建时的块编号。
; {$ |/ b: B3 @9 gRaw Web3(0.20.4及以下)
. E5 {/ i! W2 i  g4 d# {# j对于第二个示例,我们将直接使用Web3。 除了上一个示例中的hack之外,代码流程类似。5 s) _) D1 X% Z0 y( k8 D- K4 O
  const Web3 = require('web3') // Works with web3 0.20.4" l+ o3 [4 X6 P" p8 ?, ?0 W& r
const contractArtifact = require('./build/contracts/TutorialToken.json')
2 X* c; [" X$ a; pconst web3 = new Web3()
( }! X4 \" h$ Vconst providerUrl = 'http://localhost:8545'
; b5 K( F5 C2 P4 P* E9 Nconst provider = new Web3.providers.HttpProvider(providerUrl)web3.setProvider(provider)0 _' c1 v6 Q  G& P6 F
const networkId = web3.version.networkconst   ~# R# D& K9 e7 T. u- I
contractAddr = contractArtifact.networks[networkId].address
  [5 N& C6 B$ p# B3 iconst TutorialToken = web3.eth.contract(contractArtifact.abi, contractAddr)( u1 c  p, A5 Z1 a7 S0 {, h
const contract = TutorialToken.at(contractAddr)1 j7 O$ c% [4 V) z3 d
const event = contract.Transfer()
7 v& a" D) r6 j# U; }5 A3 u/ ~, mevent.watch(function(error, result){   
+ n- z0 X! g4 t if (error) { return console.error(error) }    7 Q% K, Z3 t4 d
  let { args: { from, to, value }, blockNumber } = result      
. _8 R9 R, _9 Zconsole.log(`----BlockNumber (${blockNumber})----`)      9 q0 l* X( k  y+ f- D9 v
console.log(`from = ${from}`)      
9 ~5 x8 x9 t6 [  O! q2 ]% F3 Tconsole.log(`to = ${to}`)      % U) B2 J/ a! S. @) v! h
console.log(`value = ${value}`)      
5 g; V; q* [$ ]7 Lconsole.log(`----BlockNumber (${blockNumber})----`)  });  
) n9 v; a( U7 Z; V! Y9 t最重要的区别是第9-12行,我们手动从组件中抓取正确的网络。 我们没有很好的truffle.deployed功能来实现这一步。 现在我们在truffle示例中执行与之前相同的操作,并通过调用contract.NAME_OF_EVENT来创建事件。 在这个版本中我没有放一个块号,但是你可以传递与truffle版相同的东西。7 |" X* \/ _8 `8 [4 H
Raw Web3 1.0.0 beta
, H  h* H: K4 |" dWeb3确实为API带来了大量更改。 一个重大变化是我们必须使用webSockProvider来注册事件而不是httpProvider。
! _$ t4 ~# J. L/ `' e( X: `const Web3 = require('web3') // Works with web3 1.0.0-beta27
0 O2 g% k; h) D. g+ l2 |const contractArtifact = require('./build/contracts/TutorialToken.json')
! _$ L( v. I* i+ X, I  e0 a$ M4 Uconst web3 = new Web3()5 |/ x! ]2 ~0 b% f. D9 X9 d" l) ]
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.0, w1 J- C9 y5 {8 H, u" x6 v
const provider = new Web3.providers.WebsocketProvider(providerUrl)
+ R  P, ]+ t9 U. R& _( b- U5 i: L1 D" @" wweb3.setProvider(provider)
  t7 K( L$ a! ]  c, Uweb3.eth.net.getId()  .then(networkId => {   
" J- ], m) S& ~5 l" S9 ?! z! u/ v const contractAddr = contractArtifact.networks[networkId].address   
* u; G! _+ X* _. |5 lconst TutorialToken = new web3.eth.Contract(contractArtifact.abi, contractAddr)   
/ E" _, q2 A3 A( n  c) U! `TutorialToken.events.Transfer({fromBlock: 0}, 1 K2 Y( w& \- ~/ g# Y9 X' Z8 l* v
function(error, event){ console.log(error) })      0 T$ a  {: M8 g
.on('data', (log) => {      
& O/ [5 T" u1 N+ x/ v3 q let {
. N2 n! Z& C  XreturnValues: { from, to, value }, blockNumber } = log   
! }: N) |& {2 `$ g* L$ }    console.log(`----BlockNumber (${blockNumber})----`)        
/ ?' S& R! U/ T+ E4 B% N* {console.log(`from = ${from}`)      
3 S$ d- h7 J. O% w  console.log(`to = ${to}`)      
# V) q9 c' o& s5 m console.log(`value = ${value}`)        5 \0 x8 c  [( D# }
console.log(`----BlockNumber (${blockNumber})----`)     
2 Q2 D$ H# I& r( i; q" h3 O& { })      
6 {$ m& x7 K; o, O4 Y6 U.on('changed', (log) => {     
$ J& h  X: V( ?$ l   console.log(`Changed: ${log}`)    : {: n" g0 F; d0 G# v9 {$ J
  })      .on('error', (log) => {   
: l3 l- ^7 w; `- R     console.log(`error:  ${log}`)    % \6 M) @% \2 r. ~$ @2 T
  })  })  
& D& G+ ~5 S6 {此外,获取networkId也已更新。 但过程是一样的。 我们使用web3.eth.net.getId()获取networkId,然后从Artifact中选择正确的合同地址。 初始化合同现在是一个类构造函数,在web3.eth.Contract中有一个大写C. 最后,我们创建了事件监听器。 我们现在必须自己处理“数据”,“更改”和“错误”事件。 之前它包含在前面2个示例中的watch功能中。) ~" S8 @1 d8 R
总结
  o, F$ h6 I0 F! L# [7 q; Q您应该了解如何将您的offchain服务连接到onchain事件。 这意味着您现在可以将区块链集成到现有基础架构中。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

李悔之2015 初中生
  • 粉丝

    1

  • 关注

    0

  • 主题

    13