Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
您的应用程序不可避免地需要与“现实世界”API进行对话,例如是发送电子邮件,查询更多数据,或充当发起其他处理的信号。 下面让我们探讨如何让以太坊智能合约与脱链服务互通。
' a( T( V+ K) \" n. n简而言之,您可以在处理事务时使智能合约发出事件。一旦事务被挖掘,事件数据就可以读取。在下图中,您可以看到您的DApp发出的事件可以从您的API的任何服务中检索。
1 z, [% X2 B* M1 h6 `8 M8 `4 L# p- l! `' Q: Y
目前有两种方法可以获取事件数据:
% e  u4 r! S" [目前有两种方法可以获取事件数据:" J+ a8 x% P6 b
选项1:使用getTransactionReceipt
( ^2 W& T- e7 ]6 W0 U选项2:为事件注册监听器# ?* X: j! v& C( Q1 y5 |
您可以使用选项1来获取事件数据,但是可能会存在潜在问题,因为在区块被挖掘之前收据是空的。你可以提出调查,但这很难做到。
! q8 A2 J& ]" F7 J$ m另外,根据网络流量和gasPrice设置,交易可能长时间不会被打包。请注意,事件只有在被挖掘成区块后才会被传播。这意味着可以为任何一个区块调用多个事件。
+ c( ]. N6 x  H  Q9 {solidity事件& g. ]( {9 o/ h# w6 O
在solidity里创建事件需要两个步骤:定义事件,发出事件。, C* f, k" u- H3 b8 d1 y
    pragma solidity ^0.4.18;
$ x- L& V" |' S! C* V7 M( Pcontract MyContract {  
: j, T: l2 a7 F, `1 I- Mevent Transfer(address indexed from, address indexed to, uint256 value); /* This is an event */  ' d0 ]: Y- Q8 ?1 ^0 A5 k. p. H. ?
function MyContract() {} /* a constructor */  1 l/ X: K3 J6 \
function transfer(address _to) public {   6 Z9 H1 N! i0 n8 N9 o3 r0 r
Transfer(msg.sender, _to, msg.value);  }}    {; x7 Q6 L+ ^: q: ?
注意事件Transfer是如何在第5行创建的,然后在函数传输中使用它发出Transfer事件(第10行)。 但会告诉你如何使用一个事件,如果我们用0x123调用传递函数,并从0x4444的地址发送1以太,则事件触发传输事件并应返回[0x4444,0x123,BigNumber(1以太)]。- a; G/ I- `* Q  ?3 e  o" e
监听事件
% M3 U% Z' K( C+ W以太坊实现了他们的JSON RPC规范,但任何人都可以用他们选择的语言实现自己的库。 我们将使用Truffle和原始web3 Javascript API。 监听事件的一般流程如下:' w' y5 k. ^4 j' [1 I" X# i- q
1、加载合同组件# ?1 ^) i; y8 v4 ^
2、配置web3和使用truffle提供程序
) a# ~& J: z! L" o' }3、识别网络id
4 h4 H  k( ], C: k9 f; X3 A# Z4、从合同组件中获取正确的合同地址
/ K+ x& O5 g) F) P  T5、获取JavaScript合约实例: R- ]- ?( J8 K9 ?' g, m" B& M
6、使用可选配置调用contractInstace.NAME_OF_EVENT
0 g6 D: A4 P6 w下面我们有3个样本使用Truffle,Web3在1.0 beta之前,Web3在1.0 beta之后。) E9 w& d* j8 x$ \4 \. H7 c
Truffle API
4 s/ L( t2 L& j5 }( x$ @Truffle是web3的一个很好的包装器,它提供了一些便利功能,使用更加轻松。 看一下下面的代码示例:- U1 u/ F$ ]/ w' f6 _1 n/ ]; n& E
const Web3 = require('web3') // Web3 0.20.4 or web3 1 beta/ ]$ D! V9 E- Y& Q. ?
const truffleContract = require("truffle-contract")
! L( p3 {2 h" K* }# Nconst contractArtifact = require('./build/contracts/TutorialToken.json')
' w5 K2 q. A3 {! ~( {" v% qconst providerUrl = 'http://localhost:8545'
/ o+ I/ @2 Y* E/ \const provider = new Web3.providers.HttpProvider(providerUrl)
2 D' j& M2 m+ A# Wconst contract = truffleContract(contractArtifact). o8 T: N9 F# V  u7 w: U" R; }2 o& t# P
contract.setProvider(provider)7 q8 e. m  z: t) J% m* ^
// dirty hack for web3@1.0.0 support for localhost testrpc, see https://github.com/trufflesuite/truffle-contract/issues/56#issuecomment331084530, V3 b" ?" F9 u2 Q+ B
if (typeof contract.currentProvider.sendAsync !== "function") { 1 ]+ U- h( [& F# A; k
contract.currentProvider.sendAsync = function() {      
6 l3 B& V, W7 j, O+ o4 D' Z. g# rreturn contract.currentProvider.send.apply(      
# S& f& ~2 ?4 J3 o, [9 O contract.currentProvider,           3 {/ P/ X5 d: f: c# t. [; ]" h- r
arguments     $ Z* j7 A) n8 w7 V* k$ w
);    + W+ A+ y4 G- J7 ]2 x, K% ]
};  }
  w' y0 [/ T: acontract.deployed()  .then(contractInstance => {   
, Y9 [( {: A. m" \% |7 E const event = contractInstance.Transfer(null, {fromBlock: 0}, (err, res) => {    % b& G9 Y( f6 G, I0 T1 b2 x
  if(err) {      $ e7 c. q7 }  r2 d( {2 ]
  throw Error(err)     3 k4 a$ O+ M, o
}    })   
: g7 l9 O6 f: l event.watch(function(error, result){      $ L1 j( C: u! f9 [' S' u
if (error) { return console.log(error) }     
; g: X1 _% K+ o9 ^/ y. N$ b if (!error) {       $ ?3 W! P$ @: V$ h: Z
// DO ALL YOUR WORK HERE!       # R+ x; @2 b7 `4 _- m5 o
let { args: { from, to, value }, blockNumber } = result         H/ _$ t1 b9 w: r* [
console.log(`----BlockNumber (${blockNumber})----`)        
  O9 p2 _( d) ~. P+ v) ?console.log(`from = ${from}`)       ( T7 i! h6 ~/ j. w$ S& B
console.log(`to = ${to}`)       " R% R  G0 k( z. s- c! G
console.log(`value = ${value}`)       0 T; `+ j, [% b& M% |
console.log(`----BlockNumber (${blockNumber})----`)   ! O# a5 `  Y4 @& i; H4 v! B' D5 j
   }   - _# K1 ^0 F6 A% {7 X8 Y- ^
})  })
) e# d. I+ i6 `' s, D .catch(e => {   1 o9 w  `  |: T; ?
console.error('Catastrophic Error!')  & M* n2 m7 E. B/ V3 U: U2 h
  console.error(e) ) C- F  ?/ k4 m7 \+ o' c
})  
$ G, A' l: L* M; Y# n前9行需要一些模块,并设置truffle和web3能够正常网络通信。 第12-19行作为hack使其与web3一起使用,可以忽略。 工作从第21行开始,带有contract.deployed()。 这是一个很好的truffle辅助函数,可以从创建并保存到./build/contracts的工件中选择正确的合同地址。 返回contractInstance(第23行)后,我们通过调用contractInstance.NAME_OF_EVENT来“创建”该事件。 存在更多选项,可在此处找到。 我从0块中选择,因为它是我们自己的testrpc。 对于您的合同,最好选择更接近合同创建时的块编号。
: _3 \% y- {! O) {0 o8 TRaw Web3(0.20.4及以下)( Y; T, Y, Z6 S, M+ ]  b3 v# }
对于第二个示例,我们将直接使用Web3。 除了上一个示例中的hack之外,代码流程类似。# @1 M* E# F# C: A; c+ P- g3 W
  const Web3 = require('web3') // Works with web3 0.20.45 K3 R" B4 q. i' S# N) R
const contractArtifact = require('./build/contracts/TutorialToken.json')
( a. \# `$ E: K4 ]$ l! b7 k  a- K1 \const web3 = new Web3()0 p4 P3 X- L5 z& u) v8 d
const providerUrl = 'http://localhost:8545'
6 B) h) H( P6 s6 y5 ?3 ~const provider = new Web3.providers.HttpProvider(providerUrl)web3.setProvider(provider)
* ^2 C2 }5 @. ^const networkId = web3.version.networkconst
9 a( V: ]6 F( v: h; v! `contractAddr = contractArtifact.networks[networkId].address
% v  ^" o" ?& t' f3 w8 l" r+ Rconst TutorialToken = web3.eth.contract(contractArtifact.abi, contractAddr)
+ ~8 |( i6 ?  {6 V0 Uconst contract = TutorialToken.at(contractAddr)1 B! y/ n3 V5 f8 s2 n: n6 I! W
const event = contract.Transfer()1 _" Y! D% J$ i, K# s
event.watch(function(error, result){   
7 J" [$ `2 e7 u$ }, c! j+ O4 d. I if (error) { return console.error(error) }   
3 W3 A1 I' H; w9 L1 g  let { args: { from, to, value }, blockNumber } = result      
& a) K9 \, ^) T+ qconsole.log(`----BlockNumber (${blockNumber})----`)      
/ p% b$ l! _, Q9 vconsole.log(`from = ${from}`)      
, B# _  o6 ^4 ?" |% T& Mconsole.log(`to = ${to}`)      ' L! I. J) \2 N3 G. A: i, w$ A
console.log(`value = ${value}`)      
! r, @3 F& B( i0 g7 |console.log(`----BlockNumber (${blockNumber})----`)  });  & |, x# _4 ^+ F7 |' O
最重要的区别是第9-12行,我们手动从组件中抓取正确的网络。 我们没有很好的truffle.deployed功能来实现这一步。 现在我们在truffle示例中执行与之前相同的操作,并通过调用contract.NAME_OF_EVENT来创建事件。 在这个版本中我没有放一个块号,但是你可以传递与truffle版相同的东西。, u' u3 y$ g- m2 @
Raw Web3 1.0.0 beta* |. Y; Z6 R' d6 S
Web3确实为API带来了大量更改。 一个重大变化是我们必须使用webSockProvider来注册事件而不是httpProvider。
5 L; ^% b# }$ M& }' O  @3 jconst Web3 = require('web3') // Works with web3 1.0.0-beta27/ a; q# X/ d; X% X2 y" [
const contractArtifact = require('./build/contracts/TutorialToken.json'), _: @; q$ c# ~1 x
const web3 = new Web3()
, c$ f! N' t% 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& C  q  Q5 O- b$ F$ y. |! ^
const provider = new Web3.providers.WebsocketProvider(providerUrl)! Z& M% h+ e, n4 \7 ~" P# z
web3.setProvider(provider)5 b+ ?0 G; q+ z5 Q+ ?0 n
web3.eth.net.getId()  .then(networkId => {   
( h  {6 C5 H+ s/ [! v: M const contractAddr = contractArtifact.networks[networkId].address    / E! h4 f9 t& g9 H3 G" c: ]* c
const TutorialToken = new web3.eth.Contract(contractArtifact.abi, contractAddr)   
& a9 Y8 e8 |' c3 W9 O' ITutorialToken.events.Transfer({fromBlock: 0},
8 O" H. S; P; j function(error, event){ console.log(error) })      
. I6 n  X- P8 v! m* H  s.on('data', (log) => {      
% T) F' y& d5 Y let { 1 k- O; J. `8 A1 W9 ?; x
returnValues: { from, to, value }, blockNumber } = log   
" Q% R; _5 R3 b6 y    console.log(`----BlockNumber (${blockNumber})----`)        
6 J* Y5 _; V! ~! a# Uconsole.log(`from = ${from}`)      
1 y# t; ~$ d$ b" I! E# G  console.log(`to = ${to}`)       1 G9 w3 f" @! _0 D" o  Y
console.log(`value = ${value}`)        
/ {( y& @) V5 Mconsole.log(`----BlockNumber (${blockNumber})----`)     , _1 }+ s' ?$ j, v/ _
})      
% |  W$ X* s/ l: X% ].on('changed', (log) => {     / e: f7 K3 _, M* x: [/ c
   console.log(`Changed: ${log}`)   
& h/ v( W; c2 J: m8 r% ]2 l/ O$ F: X  })      .on('error', (log) => {   
* t* t+ ~  b: E  o9 Q  ~5 x/ {     console.log(`error:  ${log}`)   
) f2 q: \6 e; \* b- S. `  })  })  
1 p+ q( h0 u. |* V5 I, n此外,获取networkId也已更新。 但过程是一样的。 我们使用web3.eth.net.getId()获取networkId,然后从Artifact中选择正确的合同地址。 初始化合同现在是一个类构造函数,在web3.eth.Contract中有一个大写C. 最后,我们创建了事件监听器。 我们现在必须自己处理“数据”,“更改”和“错误”事件。 之前它包含在前面2个示例中的watch功能中。4 H5 ^5 N3 w4 Y" M9 M
总结
4 i4 p) I) M4 o; ^您应该了解如何将您的offchain服务连接到onchain事件。 这意味着您现在可以将区块链集成到现有基础架构中。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

李悔之2015 初中生
  • 粉丝

    1

  • 关注

    0

  • 主题

    13