Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
您的应用程序不可避免地需要与“现实世界”API进行对话,例如是发送电子邮件,查询更多数据,或充当发起其他处理的信号。 下面让我们探讨如何让以太坊智能合约与脱链服务互通。
+ S0 _/ n$ D" A4 K简而言之,您可以在处理事务时使智能合约发出事件。一旦事务被挖掘,事件数据就可以读取。在下图中,您可以看到您的DApp发出的事件可以从您的API的任何服务中检索。8 |' v# ~, r* {! _- c

$ i+ U, A+ N' r0 p# g* `2 \6 }目前有两种方法可以获取事件数据:+ }9 _' |2 s  v5 W( G! |* q! p
目前有两种方法可以获取事件数据:) ~1 \" Q/ h) _( b$ V% z1 U1 Z
选项1:使用getTransactionReceipt3 @3 H+ h7 f% }3 i
选项2:为事件注册监听器) f( i: S8 s3 c1 H1 ~8 `
您可以使用选项1来获取事件数据,但是可能会存在潜在问题,因为在区块被挖掘之前收据是空的。你可以提出调查,但这很难做到。3 _& l2 y* {  ]6 U
另外,根据网络流量和gasPrice设置,交易可能长时间不会被打包。请注意,事件只有在被挖掘成区块后才会被传播。这意味着可以为任何一个区块调用多个事件。
" f5 G0 N, T& D2 L8 x2 y% k$ zsolidity事件
* c2 g; U0 q% y) u! f1 h( C在solidity里创建事件需要两个步骤:定义事件,发出事件。# z( m; }0 D( W" R$ u$ k+ q
    pragma solidity ^0.4.18;
9 I2 i2 }% Y; L6 q, Y. ncontract MyContract {  ' r$ J& S! P8 G; n
event Transfer(address indexed from, address indexed to, uint256 value); /* This is an event */  
* n* k0 p- w9 t# p& d6 Mfunction MyContract() {} /* a constructor */  
; [% A; s/ `7 A( I/ I( \function transfer(address _to) public {   
% k+ {. ^* I9 l Transfer(msg.sender, _to, msg.value);  }}  7 I, G& v9 P; S, K: Z& O; {* _
注意事件Transfer是如何在第5行创建的,然后在函数传输中使用它发出Transfer事件(第10行)。 但会告诉你如何使用一个事件,如果我们用0x123调用传递函数,并从0x4444的地址发送1以太,则事件触发传输事件并应返回[0x4444,0x123,BigNumber(1以太)]。0 b. Y  ]" Y5 F& l, y
监听事件
7 L1 a. M+ B6 N! }' N以太坊实现了他们的JSON RPC规范,但任何人都可以用他们选择的语言实现自己的库。 我们将使用Truffle和原始web3 Javascript API。 监听事件的一般流程如下:
# ?( t1 i+ `6 G  b1、加载合同组件
  D; {" X4 ]% H8 f& l1 y2、配置web3和使用truffle提供程序
& Y2 p( {; C; ]5 `3、识别网络id6 ?: }4 U2 U) m
4、从合同组件中获取正确的合同地址8 V' w3 S8 Y5 T7 f! n% |
5、获取JavaScript合约实例
' o, h+ @# b& r4 \$ N$ T, _! ?6、使用可选配置调用contractInstace.NAME_OF_EVENT' b; u$ G2 r. _; F0 D
下面我们有3个样本使用Truffle,Web3在1.0 beta之前,Web3在1.0 beta之后。. {3 Z: N) F1 q3 X
Truffle API
( i  H% Z- E/ n3 }) |/ I7 DTruffle是web3的一个很好的包装器,它提供了一些便利功能,使用更加轻松。 看一下下面的代码示例:
4 q; O" z+ e; P& p" S4 ^5 dconst Web3 = require('web3') // Web3 0.20.4 or web3 1 beta: G+ Q6 r, I. x% T! D6 y" c. H
const truffleContract = require("truffle-contract")
% j; W3 Y  B" F( ~& |7 fconst contractArtifact = require('./build/contracts/TutorialToken.json')5 Q5 Q0 V5 m, m
const providerUrl = 'http://localhost:8545'; E$ X0 v2 r+ a: F6 H
const provider = new Web3.providers.HttpProvider(providerUrl)
4 u: i( p5 ~8 I( wconst contract = truffleContract(contractArtifact)
; B; r, r8 q, scontract.setProvider(provider)
& b' r$ o& O! e' a' Z2 y# S- G- h' X& X' u/ Y// dirty hack for web3@1.0.0 support for localhost testrpc, see https://github.com/trufflesuite/truffle-contract/issues/56#issuecomment3310845302 |, l9 Q7 x. q
if (typeof contract.currentProvider.sendAsync !== "function") { - ~  h* _9 F, r% l% n& s
contract.currentProvider.sendAsync = function() {      + d+ E+ L0 f6 S
return contract.currentProvider.send.apply(       9 K! e0 B6 w( d' u
contract.currentProvider,           ' k0 m: {8 O1 k1 O  _& c
arguments     
" O- q& h! G5 h# d" O );    2 b* E. c7 j0 n
};  }5 @: v+ K2 R' \" H) y
contract.deployed()  .then(contractInstance => {   
& F, v& |  v, Q' ` const event = contractInstance.Transfer(null, {fromBlock: 0}, (err, res) => {   
/ r& n3 Y7 w# d# \& @( a  if(err) {        s; e3 c+ ^9 l5 q
  throw Error(err)     5 p4 t( B4 @6 s5 H# d/ H" E9 V
}    })   
' `7 @2 c5 K( ?- f% E3 T event.watch(function(error, result){      % h8 y$ v5 n  k9 Y
if (error) { return console.log(error) }     
" h! B  t7 z+ S/ ?2 Z7 u3 l5 @' k if (!error) {      
$ x; W4 o- u" z3 }: z // DO ALL YOUR WORK HERE!      
6 J$ p2 B. I; c9 ^ let { args: { from, to, value }, blockNumber } = result      
+ I0 x* |0 |; z. d console.log(`----BlockNumber (${blockNumber})----`)        
  c6 Y9 K' X& ~console.log(`from = ${from}`)       . ^7 Q) F) x" C# ^9 A2 G; x1 c5 [# c
console.log(`to = ${to}`)      
3 z8 S. Q* w3 f console.log(`value = ${value}`)      
7 {7 F0 s7 Y. i+ v7 K" ~+ v# U console.log(`----BlockNumber (${blockNumber})----`)   7 Y7 J! Q. J, v5 {( L! J3 H2 Y
   }   
$ u0 v' k! v, h/ O })  })   l3 @1 s- M- W  g4 _9 \
.catch(e => {   
, R# ^- s/ q, a6 K9 X; H* M console.error('Catastrophic Error!')  2 Z: r8 x5 ~* y" ]- Z
  console.error(e) : L! \/ F# V) s
})  
& R- U7 c! `* J$ t, F9 l前9行需要一些模块,并设置truffle和web3能够正常网络通信。 第12-19行作为hack使其与web3一起使用,可以忽略。 工作从第21行开始,带有contract.deployed()。 这是一个很好的truffle辅助函数,可以从创建并保存到./build/contracts的工件中选择正确的合同地址。 返回contractInstance(第23行)后,我们通过调用contractInstance.NAME_OF_EVENT来“创建”该事件。 存在更多选项,可在此处找到。 我从0块中选择,因为它是我们自己的testrpc。 对于您的合同,最好选择更接近合同创建时的块编号。( Z8 i3 ?3 _7 x( _  v  t9 n
Raw Web3(0.20.4及以下)$ d4 @* R. q, `) I: x% s! K7 o1 L( w; K
对于第二个示例,我们将直接使用Web3。 除了上一个示例中的hack之外,代码流程类似。
% X/ B: ^2 d) ]: I+ y+ I5 ~6 O  const Web3 = require('web3') // Works with web3 0.20.4
: F& P+ u( V5 n7 t5 vconst contractArtifact = require('./build/contracts/TutorialToken.json')
/ v, n, a0 J  S' x0 d  nconst web3 = new Web3()
; o+ ^6 v8 P$ K5 Hconst providerUrl = 'http://localhost:8545'. K7 b* f9 V: r. F) N9 c) G
const provider = new Web3.providers.HttpProvider(providerUrl)web3.setProvider(provider)
" e- W, w# f1 I' Lconst networkId = web3.version.networkconst # c9 n5 M' E4 u8 j
contractAddr = contractArtifact.networks[networkId].address" k1 v. z. j3 Z# b: s& N. @" b. s
const TutorialToken = web3.eth.contract(contractArtifact.abi, contractAddr)
6 X4 Y+ _% S1 ~8 U' |9 [const contract = TutorialToken.at(contractAddr)
1 p: A( f) j# s* |const event = contract.Transfer()2 g! l* }& h! [  k
event.watch(function(error, result){   
6 ^) K9 I) R8 G% t# B- N! | if (error) { return console.error(error) }    6 L7 P" R: i$ z: z" [
  let { args: { from, to, value }, blockNumber } = result      6 D( Q0 W9 t, g' A& b9 `
console.log(`----BlockNumber (${blockNumber})----`)      * J4 w3 \% m, `
console.log(`from = ${from}`)      
! y/ ^9 v- t$ \1 s& {2 \/ Yconsole.log(`to = ${to}`)      
' g4 w7 t6 ]- V9 m0 ]5 T$ O' ]+ \! Fconsole.log(`value = ${value}`)      
3 ~- q" H  ?! @; ]) _6 y1 hconsole.log(`----BlockNumber (${blockNumber})----`)  });  * j) B, g3 Y, @3 j
最重要的区别是第9-12行,我们手动从组件中抓取正确的网络。 我们没有很好的truffle.deployed功能来实现这一步。 现在我们在truffle示例中执行与之前相同的操作,并通过调用contract.NAME_OF_EVENT来创建事件。 在这个版本中我没有放一个块号,但是你可以传递与truffle版相同的东西。( v: I/ g7 f+ h/ L* I/ o
Raw Web3 1.0.0 beta
% ~) ]4 v( M! B2 Y$ uWeb3确实为API带来了大量更改。 一个重大变化是我们必须使用webSockProvider来注册事件而不是httpProvider。  A" I$ Q. r6 ^
const Web3 = require('web3') // Works with web3 1.0.0-beta279 |$ n! U- n' T5 D) r
const contractArtifact = require('./build/contracts/TutorialToken.json')% U& K9 y, [$ Y0 a2 i9 d) R# Q# p
const web3 = new Web3()
( D( C/ I& w: P2 U2 h8 S5 D% Iconst 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.05 ?" ?" \1 U. ~- `, i$ s# F. p3 @
const provider = new Web3.providers.WebsocketProvider(providerUrl)% H( W6 _4 v3 ?- [
web3.setProvider(provider)
5 ^2 l# C. `# {. _$ |# y0 v- kweb3.eth.net.getId()  .then(networkId => {   / |1 \. s- n$ ]
const contractAddr = contractArtifact.networks[networkId].address    : M# K# |5 H* e" v( T
const TutorialToken = new web3.eth.Contract(contractArtifact.abi, contractAddr)   
1 z1 H! M% v; N+ R! pTutorialToken.events.Transfer({fromBlock: 0},
3 b2 B1 M1 ~/ S3 W$ \. W function(error, event){ console.log(error) })      4 h" L! W" h. g- {
.on('data', (log) => {       ; E$ O) s) D& f4 m' P) X/ u6 x8 y: x6 [
let {
2 R# ]& E% D3 oreturnValues: { from, to, value }, blockNumber } = log    ) a) x2 M4 Q1 ?. e/ K1 m5 J
    console.log(`----BlockNumber (${blockNumber})----`)        
* X# X/ p+ [# l  s; d6 S3 J# \7 Sconsole.log(`from = ${from}`)      : Z" M. X" ~- s$ P+ O0 z% s. d! \
  console.log(`to = ${to}`)      
* O  R+ V7 ?: x% ? console.log(`value = ${value}`)        $ `0 V. w* W/ ?) j. ?
console.log(`----BlockNumber (${blockNumber})----`)     # A$ T4 n! u+ P% {% J& A
})      
) Q8 o! \1 |8 u% n) C.on('changed', (log) => {     
$ j6 o" R1 L. g! D4 X. D   console.log(`Changed: ${log}`)    4 G# ^2 L/ D8 v  q  {8 [* [
  })      .on('error', (log) => {   
3 x) P* H( Q$ t: ?  w7 j     console.log(`error:  ${log}`)    & q5 ?8 @1 j; |1 @' g2 D. \
  })  })  
0 a3 j4 R9 c) N/ [* K' P! }% q此外,获取networkId也已更新。 但过程是一样的。 我们使用web3.eth.net.getId()获取networkId,然后从Artifact中选择正确的合同地址。 初始化合同现在是一个类构造函数,在web3.eth.Contract中有一个大写C. 最后,我们创建了事件监听器。 我们现在必须自己处理“数据”,“更改”和“错误”事件。 之前它包含在前面2个示例中的watch功能中。
, ]2 H& _5 i8 v1 m3 x总结
' R5 i3 {: q9 @# W& u9 D# u) l; q您应该了解如何将您的offchain服务连接到onchain事件。 这意味着您现在可以将区块链集成到现有基础架构中。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

李悔之2015 初中生
  • 粉丝

    1

  • 关注

    0

  • 主题

    13