Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
您的应用程序不可避免地需要与“现实世界”API进行对话,例如是发送电子邮件,查询更多数据,或充当发起其他处理的信号。 下面让我们探讨如何让以太坊智能合约与脱链服务互通。
! t, ]: H% S; D简而言之,您可以在处理事务时使智能合约发出事件。一旦事务被挖掘,事件数据就可以读取。在下图中,您可以看到您的DApp发出的事件可以从您的API的任何服务中检索。
' A, G" `" [7 k2 q9 n; r
7 B4 |9 \0 Y9 s, {2 `9 a$ P! g目前有两种方法可以获取事件数据:
/ Y$ N/ X- v8 u8 g目前有两种方法可以获取事件数据:
& l, T5 ?! ]/ V6 P8 T, l- F$ T选项1:使用getTransactionReceipt7 E8 p! j  c( z  E
选项2:为事件注册监听器
. l, r" f# F! t您可以使用选项1来获取事件数据,但是可能会存在潜在问题,因为在区块被挖掘之前收据是空的。你可以提出调查,但这很难做到。
  `6 E1 X6 ^+ u9 h. Q) {另外,根据网络流量和gasPrice设置,交易可能长时间不会被打包。请注意,事件只有在被挖掘成区块后才会被传播。这意味着可以为任何一个区块调用多个事件。- y* F. n+ C: s, E* B: y
solidity事件
; }! N7 D1 [# ^9 O3 y" @' G: r& J在solidity里创建事件需要两个步骤:定义事件,发出事件。' e. `2 ~, S( W8 C' R8 k
    pragma solidity ^0.4.18;
. H* a' v3 t. O4 h5 V; h1 `4 I) lcontract MyContract {  
9 D! B7 I, y7 ~. W+ Vevent Transfer(address indexed from, address indexed to, uint256 value); /* This is an event */  
. i8 c& J- w7 v7 a5 I% J7 ]function MyContract() {} /* a constructor */  
$ i  _# Y* s% ]! Jfunction transfer(address _to) public {   
/ _- S3 e8 s# r, \ Transfer(msg.sender, _to, msg.value);  }}  / v9 \$ d7 M! v0 p
注意事件Transfer是如何在第5行创建的,然后在函数传输中使用它发出Transfer事件(第10行)。 但会告诉你如何使用一个事件,如果我们用0x123调用传递函数,并从0x4444的地址发送1以太,则事件触发传输事件并应返回[0x4444,0x123,BigNumber(1以太)]。
* ]$ A4 [8 d: z5 y+ x7 ^& Q监听事件
& g1 |1 p, p2 O& x- R. a以太坊实现了他们的JSON RPC规范,但任何人都可以用他们选择的语言实现自己的库。 我们将使用Truffle和原始web3 Javascript API。 监听事件的一般流程如下:" g: q- G$ y- _3 x* T; M
1、加载合同组件
& `8 F: k1 J" B) L/ }, T( I2、配置web3和使用truffle提供程序
- B9 L. h8 O9 {' ^3、识别网络id
6 u; {5 H0 e5 T$ M. X" E( z4、从合同组件中获取正确的合同地址
+ O1 s7 x. i/ e, S" W5、获取JavaScript合约实例2 G- {: G# x2 A! c4 j- O$ f( _
6、使用可选配置调用contractInstace.NAME_OF_EVENT' `- Q0 w3 Q' L  @' k5 X
下面我们有3个样本使用Truffle,Web3在1.0 beta之前,Web3在1.0 beta之后。4 ~' y+ C7 G- D# V  C6 R
Truffle API
) R- `8 N# J) v8 _% }( A7 u! zTruffle是web3的一个很好的包装器,它提供了一些便利功能,使用更加轻松。 看一下下面的代码示例:$ f6 z$ b+ ^) y9 t- t9 k2 A% }! I
const Web3 = require('web3') // Web3 0.20.4 or web3 1 beta
6 b3 Q  s8 C' S; d1 p$ nconst truffleContract = require("truffle-contract"): ^  K1 z9 @4 ]7 l: Q/ ~$ Y
const contractArtifact = require('./build/contracts/TutorialToken.json'). m+ Z- K/ _4 V' F3 j% \" P5 M
const providerUrl = 'http://localhost:8545'
" S# D' P" L" a  Q  hconst provider = new Web3.providers.HttpProvider(providerUrl)
+ ~$ s/ N/ {! ~+ Oconst contract = truffleContract(contractArtifact)
: A: x" k; k% }; x0 ?1 Kcontract.setProvider(provider)
6 c- m2 _* S5 M( L' K6 n// dirty hack for web3@1.0.0 support for localhost testrpc, see https://github.com/trufflesuite/truffle-contract/issues/56#issuecomment331084530: P5 d; X+ H3 t
if (typeof contract.currentProvider.sendAsync !== "function") { . B3 H& S, b$ j) b' r0 Y8 L" n$ J
contract.currentProvider.sendAsync = function() {      
$ l. H1 R3 U# R8 G, ureturn contract.currentProvider.send.apply(      
; ~4 G: h( `0 j" q9 E6 z contract.currentProvider,           
: ^5 r4 Y% X& d' ^$ L$ [3 E( K" ~+ J arguments     
9 P0 W+ G' Q) q8 Z/ M8 _+ T );   
( v8 I& `+ E& G! H};  }1 R% O" h0 |) q: f* V
contract.deployed()  .then(contractInstance => {   : R( l+ c8 g8 m
const event = contractInstance.Transfer(null, {fromBlock: 0}, (err, res) => {    : |& u& ^3 d3 `' j+ o! E+ ^
  if(err) {        x5 E0 \* D' P8 e1 e: ]! T# T1 J
  throw Error(err)     4 @; s6 V. C- P% E) l" M) E
}    })   8 c. `9 A9 n2 K- f: q5 C
event.watch(function(error, result){      ! F) l" i+ u; i" }# {! O. h5 U
if (error) { return console.log(error) }     
) [* U6 j1 f  M  }7 A0 ? if (!error) {       # ~' p" s! F2 U
// DO ALL YOUR WORK HERE!       ; {$ x2 F4 S6 A
let { args: { from, to, value }, blockNumber } = result       5 C, R  i( b. |' D- Y" Y- ?
console.log(`----BlockNumber (${blockNumber})----`)        
5 v+ C1 w5 t3 ^( G, _( Q5 P  ^# c% iconsole.log(`from = ${from}`)      
" \0 t; b3 X6 n1 y9 r* t# G console.log(`to = ${to}`)       # A  J! v, u) T% p
console.log(`value = ${value}`)      
- \* F/ N$ t2 J4 `9 j3 z6 z' S console.log(`----BlockNumber (${blockNumber})----`)   
! |1 c* ~2 L$ N+ W/ S% n   }   ! b' P8 I2 p4 g
})  }) 0 C0 _4 \" d0 _2 R( }
.catch(e => {   , q$ _. l! `; q7 K
console.error('Catastrophic Error!')  
* q5 T$ ~1 v; ^, [! G' X  console.error(e) 3 K# e8 X# H! \9 n" \$ n
})  
! Q: r, \: v, V前9行需要一些模块,并设置truffle和web3能够正常网络通信。 第12-19行作为hack使其与web3一起使用,可以忽略。 工作从第21行开始,带有contract.deployed()。 这是一个很好的truffle辅助函数,可以从创建并保存到./build/contracts的工件中选择正确的合同地址。 返回contractInstance(第23行)后,我们通过调用contractInstance.NAME_OF_EVENT来“创建”该事件。 存在更多选项,可在此处找到。 我从0块中选择,因为它是我们自己的testrpc。 对于您的合同,最好选择更接近合同创建时的块编号。7 `% b! {8 N+ j- R7 q
Raw Web3(0.20.4及以下), B( j* c9 ~; V& i! i
对于第二个示例,我们将直接使用Web3。 除了上一个示例中的hack之外,代码流程类似。
9 v0 j# \$ \: t3 ^# C( H3 y$ u" c' n* z  const Web3 = require('web3') // Works with web3 0.20.4
3 b, _: k9 K' H: N  p5 j) Cconst contractArtifact = require('./build/contracts/TutorialToken.json')
, [3 r. T) v3 M. b* Bconst web3 = new Web3()
% T; B4 n0 s! q9 q+ u% Rconst providerUrl = 'http://localhost:8545'
5 I& G0 p& `$ {6 T* e& O' q" kconst provider = new Web3.providers.HttpProvider(providerUrl)web3.setProvider(provider)
% h) h; O7 V' B" o! @0 jconst networkId = web3.version.networkconst . q( D5 W+ |5 [9 k: l& @
contractAddr = contractArtifact.networks[networkId].address
, j# `& ]4 p- l4 Y5 jconst TutorialToken = web3.eth.contract(contractArtifact.abi, contractAddr)2 p% L& t+ c, J( L) c8 ]
const contract = TutorialToken.at(contractAddr)
2 B4 k/ g& Z# rconst event = contract.Transfer()
$ I+ V9 D0 L4 p$ l# Nevent.watch(function(error, result){   
; N' G; i; i5 C& D" ^) b' @& E if (error) { return console.error(error) }   
& g! c5 C' S) n+ Z2 f0 D3 V  let { args: { from, to, value }, blockNumber } = result      . H* n' O6 p6 ?3 R; j4 u
console.log(`----BlockNumber (${blockNumber})----`)      $ v" l# J5 ^& C& Y3 |3 W& H
console.log(`from = ${from}`)      % }4 n! L8 W- J# Q/ P
console.log(`to = ${to}`)      3 s& C5 H% f: D# X( x, A
console.log(`value = ${value}`)      ) p3 P+ W. {& q3 \
console.log(`----BlockNumber (${blockNumber})----`)  });  
7 O# q: g1 l7 k( ^3 g2 m4 D4 U最重要的区别是第9-12行,我们手动从组件中抓取正确的网络。 我们没有很好的truffle.deployed功能来实现这一步。 现在我们在truffle示例中执行与之前相同的操作,并通过调用contract.NAME_OF_EVENT来创建事件。 在这个版本中我没有放一个块号,但是你可以传递与truffle版相同的东西。
: f; i8 f" M- t" v  c/ U1 uRaw Web3 1.0.0 beta
1 W% P) H/ m4 m6 AWeb3确实为API带来了大量更改。 一个重大变化是我们必须使用webSockProvider来注册事件而不是httpProvider。4 D+ F* A- W" _2 l9 d2 m
const Web3 = require('web3') // Works with web3 1.0.0-beta27
2 A) v( `, l, Q3 _4 ]" Uconst contractArtifact = require('./build/contracts/TutorialToken.json'). |' ?9 c* R$ T0 N' Q; \! }
const web3 = new Web3()
; W7 g7 J; [& D7 H% nconst 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
& }# F6 d( a8 ]const provider = new Web3.providers.WebsocketProvider(providerUrl)4 `1 G$ ~2 Z/ X6 \; _2 Y
web3.setProvider(provider)6 o5 D9 n3 d  J% A1 o4 r
web3.eth.net.getId()  .then(networkId => {   
1 O. \; f1 x- a( ~ const contractAddr = contractArtifact.networks[networkId].address   
! @+ o! ?, N& M* b$ @( H$ I( A9 Xconst TutorialToken = new web3.eth.Contract(contractArtifact.abi, contractAddr)   
/ N: r5 X6 T8 y4 L2 s' JTutorialToken.events.Transfer({fromBlock: 0}, 4 E! `/ G4 i6 E" @
function(error, event){ console.log(error) })      
5 M) B! A% J- t+ H2 h.on('data', (log) => {      
6 ?/ F2 P+ V8 m; I let {
, ^0 a; \; k5 ^: nreturnValues: { from, to, value }, blockNumber } = log    ( U( [. K7 R+ H
    console.log(`----BlockNumber (${blockNumber})----`)        ( {! H1 U* V9 b6 Y* b6 o- J  c2 x
console.log(`from = ${from}`)      
( l" A0 L' w/ _2 E0 W- W6 q  console.log(`to = ${to}`)       + ?: d0 r6 w& U' [
console.log(`value = ${value}`)        
, ], |& U" {# ]1 P' C7 i1 U: _6 Jconsole.log(`----BlockNumber (${blockNumber})----`)     
- j/ i4 k" k! l, E })      ! X1 r! p% P5 _; f" o' r+ Q# z
.on('changed', (log) => {     
- N+ a6 t4 y5 M2 D- h# _! G   console.log(`Changed: ${log}`)   
1 M' S5 I7 J; `# N- q& W  })      .on('error', (log) => {   ( k# V5 @3 @9 u1 c9 e
     console.log(`error:  ${log}`)    ( `% b, H3 U6 d! H( w& X& a! w
  })  })  
5 r. y5 W/ d* G6 |8 Y. c  P' s此外,获取networkId也已更新。 但过程是一样的。 我们使用web3.eth.net.getId()获取networkId,然后从Artifact中选择正确的合同地址。 初始化合同现在是一个类构造函数,在web3.eth.Contract中有一个大写C. 最后,我们创建了事件监听器。 我们现在必须自己处理“数据”,“更改”和“错误”事件。 之前它包含在前面2个示例中的watch功能中。% e9 l9 k5 D' J, n+ j4 j
总结+ f9 _# A/ \5 Z6 y7 D4 Z
您应该了解如何将您的offchain服务连接到onchain事件。 这意味着您现在可以将区块链集成到现有基础架构中。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

李悔之2015 初中生
  • 粉丝

    1

  • 关注

    0

  • 主题

    13