Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
您的应用程序不可避免地需要与“现实世界”API进行对话,例如是发送电子邮件,查询更多数据,或充当发起其他处理的信号。 下面让我们探讨如何让以太坊智能合约与脱链服务互通。
' \1 |% t- y2 H4 w- ?' Z: H! V简而言之,您可以在处理事务时使智能合约发出事件。一旦事务被挖掘,事件数据就可以读取。在下图中,您可以看到您的DApp发出的事件可以从您的API的任何服务中检索。: S# o: g4 n, [! A* Q) O

- H$ N" w/ k+ D  Z$ c0 Y  y目前有两种方法可以获取事件数据:
) t& [! _! O$ t! H目前有两种方法可以获取事件数据:# T  q" J& m) I  R/ m! u
选项1:使用getTransactionReceipt$ X& T7 R1 z5 N  K5 |! g1 S
选项2:为事件注册监听器
( [9 ]# Q* _7 g2 ]9 p. |. k2 E0 G您可以使用选项1来获取事件数据,但是可能会存在潜在问题,因为在区块被挖掘之前收据是空的。你可以提出调查,但这很难做到。
) B8 t2 I: {: L, L另外,根据网络流量和gasPrice设置,交易可能长时间不会被打包。请注意,事件只有在被挖掘成区块后才会被传播。这意味着可以为任何一个区块调用多个事件。
+ t9 ?( K  F% jsolidity事件' g" W" O! O: n; P3 o5 v; T
在solidity里创建事件需要两个步骤:定义事件,发出事件。
9 g2 [, b( H! L" [0 U! h    pragma solidity ^0.4.18;
- N: g' ?' _0 m/ e1 C- kcontract MyContract {  : {  Z% M  v( M/ \3 b9 I: H
event Transfer(address indexed from, address indexed to, uint256 value); /* This is an event */  
! u% s: |1 k$ S' ffunction MyContract() {} /* a constructor */  
. U) o8 H6 R7 e* Rfunction transfer(address _to) public {   % f8 k) h! I. O0 x6 C  Q
Transfer(msg.sender, _to, msg.value);  }}  ( C' Q' E' \' c- [
注意事件Transfer是如何在第5行创建的,然后在函数传输中使用它发出Transfer事件(第10行)。 但会告诉你如何使用一个事件,如果我们用0x123调用传递函数,并从0x4444的地址发送1以太,则事件触发传输事件并应返回[0x4444,0x123,BigNumber(1以太)]。
( g- Q) @" O* e% E监听事件: C$ _) L6 H( R* y/ ^$ I  W; ~: \
以太坊实现了他们的JSON RPC规范,但任何人都可以用他们选择的语言实现自己的库。 我们将使用Truffle和原始web3 Javascript API。 监听事件的一般流程如下:
( l) J) h; f: E9 v: K7 [3 C1、加载合同组件
2 L, V, Z( q2 V; Y8 O. v2、配置web3和使用truffle提供程序& K0 K8 x2 b; D8 R' r! s
3、识别网络id
& x4 b9 U3 e/ i, `& P( i# P' |4、从合同组件中获取正确的合同地址4 e' A' V2 \, r8 X) B: v& i
5、获取JavaScript合约实例
: s: ]/ T  @. X# U, q* {1 J: U$ _& B- N6、使用可选配置调用contractInstace.NAME_OF_EVENT
" ^* A- X5 _4 F下面我们有3个样本使用Truffle,Web3在1.0 beta之前,Web3在1.0 beta之后。# |' o& f6 [3 s% u" _4 u
Truffle API$ t+ _0 Y* z" p) j& R7 X
Truffle是web3的一个很好的包装器,它提供了一些便利功能,使用更加轻松。 看一下下面的代码示例:5 y! Q9 m: N. q0 `
const Web3 = require('web3') // Web3 0.20.4 or web3 1 beta
6 p' B9 O, I1 }. y$ d5 S/ w4 jconst truffleContract = require("truffle-contract")
( g" Q" o. V* e- ^% xconst contractArtifact = require('./build/contracts/TutorialToken.json')
& q8 }1 Y1 y7 }const providerUrl = 'http://localhost:8545'0 n. `7 @2 J7 s, g
const provider = new Web3.providers.HttpProvider(providerUrl)# ^3 @! N, G1 ]0 I
const contract = truffleContract(contractArtifact)9 e  b( M) G$ A" N4 M
contract.setProvider(provider)
, W0 B: t* C$ h7 j/ |3 W* i// dirty hack for web3@1.0.0 support for localhost testrpc, see https://github.com/trufflesuite/truffle-contract/issues/56#issuecomment331084530
( X- M% C8 o/ b* Iif (typeof contract.currentProvider.sendAsync !== "function") {
- L+ u4 q# O+ i' g8 t. w contract.currentProvider.sendAsync = function() {      
6 u% r& ~+ W* L! y4 X0 K1 Preturn contract.currentProvider.send.apply(       8 g7 ^% S! N) x  X8 M3 a. z
contract.currentProvider,           
1 N* h( Z) S3 e% n. q arguments     
" d/ Z& V$ ]5 \: m- M% D );    % F6 {. i, X/ e& g, j
};  }" l* P! K/ ]  c
contract.deployed()  .then(contractInstance => {   5 W, R8 G- C- h& R6 i
const event = contractInstance.Transfer(null, {fromBlock: 0}, (err, res) => {   
& S3 h8 y8 S3 u! g# B  if(err) {      
9 s/ v) j2 C8 r* d* D- J" d  throw Error(err)     1 b( r/ g' c' E# }3 [) ?
}    })   , W  q7 w, L) f4 o
event.watch(function(error, result){      0 R2 R/ m/ {" V; h2 H) i# C
if (error) { return console.log(error) }     8 _$ V$ w  n1 i
if (!error) {      
& B9 h! X% ?. `) N // DO ALL YOUR WORK HERE!      
8 G7 ]: S& _; V, F( A) ]$ A let { args: { from, to, value }, blockNumber } = result       7 I% g& N" y5 \5 K9 S
console.log(`----BlockNumber (${blockNumber})----`)        2 D: U( q0 B& [, C
console.log(`from = ${from}`)      
+ h2 b4 T" C4 c0 W6 ` console.log(`to = ${to}`)       / |! S# q' V6 p1 A3 P9 Q1 h/ g; S
console.log(`value = ${value}`)       $ T9 ^# A; x  U. F6 k0 h$ T
console.log(`----BlockNumber (${blockNumber})----`)   ( n! T: E. u9 t3 x2 u
   }   , D3 n" g& v* M" T5 ?* e1 V
})  }) 3 s0 ]6 a- s% E7 z# x# D# h! T! |
.catch(e => {   
* X3 A' q/ f* h7 s console.error('Catastrophic Error!')  . S- u, }% ?" R4 c
  console.error(e) # K6 H8 f2 B0 ]' [2 i
})  9 C0 |" }/ ]1 c8 r/ A- l5 C
前9行需要一些模块,并设置truffle和web3能够正常网络通信。 第12-19行作为hack使其与web3一起使用,可以忽略。 工作从第21行开始,带有contract.deployed()。 这是一个很好的truffle辅助函数,可以从创建并保存到./build/contracts的工件中选择正确的合同地址。 返回contractInstance(第23行)后,我们通过调用contractInstance.NAME_OF_EVENT来“创建”该事件。 存在更多选项,可在此处找到。 我从0块中选择,因为它是我们自己的testrpc。 对于您的合同,最好选择更接近合同创建时的块编号。9 [" A/ R( M9 b4 j
Raw Web3(0.20.4及以下)
$ d% C6 r; f9 F$ d) ?对于第二个示例,我们将直接使用Web3。 除了上一个示例中的hack之外,代码流程类似。/ ]. R3 H2 ]* l+ V' E9 C
  const Web3 = require('web3') // Works with web3 0.20.4
4 C7 f! J' h4 ?const contractArtifact = require('./build/contracts/TutorialToken.json')
& H' T& C/ c7 J  r$ [" N. L% M( ~const web3 = new Web3()
) O2 z2 q+ p& e' L5 Nconst providerUrl = 'http://localhost:8545'
) P% _' q1 G. k% m7 gconst provider = new Web3.providers.HttpProvider(providerUrl)web3.setProvider(provider)
1 t& G! t, S" _; Z4 X5 ^const networkId = web3.version.networkconst
1 i% r# Y! m1 l- q5 Z( a" j, V  pcontractAddr = contractArtifact.networks[networkId].address
+ A& ~8 O( z: b( ?const TutorialToken = web3.eth.contract(contractArtifact.abi, contractAddr)
: U, N( {: R% f6 Iconst contract = TutorialToken.at(contractAddr)
/ a, Y# T# I7 G1 y- o" z! \const event = contract.Transfer()
( n8 l, g6 Q  `+ {event.watch(function(error, result){   
9 v/ L% S0 K# k7 E& e. l if (error) { return console.error(error) }    $ W" D1 b" f, j  i
  let { args: { from, to, value }, blockNumber } = result      
! ]% S: Z7 l) Nconsole.log(`----BlockNumber (${blockNumber})----`)      
' K- \$ I) C  H( W+ zconsole.log(`from = ${from}`)      
# t$ u6 X$ q$ z0 M( zconsole.log(`to = ${to}`)      
8 W; x! K" e. y/ B* Vconsole.log(`value = ${value}`)      
/ a5 T. P; j' W2 e# Q0 W% g3 xconsole.log(`----BlockNumber (${blockNumber})----`)  });  , [  [7 s2 x5 ], t' ~
最重要的区别是第9-12行,我们手动从组件中抓取正确的网络。 我们没有很好的truffle.deployed功能来实现这一步。 现在我们在truffle示例中执行与之前相同的操作,并通过调用contract.NAME_OF_EVENT来创建事件。 在这个版本中我没有放一个块号,但是你可以传递与truffle版相同的东西。
$ _" |) U5 g4 s( Q5 YRaw Web3 1.0.0 beta* r' R- D- D6 u3 M4 U2 M; T
Web3确实为API带来了大量更改。 一个重大变化是我们必须使用webSockProvider来注册事件而不是httpProvider。
) `# U& ^$ w6 i0 K2 Nconst Web3 = require('web3') // Works with web3 1.0.0-beta27
0 x: Y) n1 _) e) econst contractArtifact = require('./build/contracts/TutorialToken.json')
) l- k1 ^6 f% D8 h! J$ {: K8 [+ sconst web3 = new Web3()7 f# x. q+ P& m! r# V" x
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
& \1 q- \; G- M* Q' J7 Mconst provider = new Web3.providers.WebsocketProvider(providerUrl)9 \  L% g2 k$ ~. C4 k
web3.setProvider(provider)
4 `2 |9 V+ q: p* h' Jweb3.eth.net.getId()  .then(networkId => {   
' G; I! W( k$ ?( q; m const contractAddr = contractArtifact.networks[networkId].address   
7 I3 y: W' t5 L: n1 aconst TutorialToken = new web3.eth.Contract(contractArtifact.abi, contractAddr)   
1 _9 K1 G" |3 q7 Q: M% E* `' WTutorialToken.events.Transfer({fromBlock: 0},
4 f+ l1 l! Z; r7 ]9 k6 t function(error, event){ console.log(error) })      
6 E8 ?% a# O7 b9 _9 ~' P' w5 i.on('data', (log) => {       " z) n: Z  j/ X* Z+ G2 ~; m
let {
) ?7 _% c/ ]; Q/ l. I: x/ T. I4 ureturnValues: { from, to, value }, blockNumber } = log    9 E! t0 c2 F4 v# J7 W5 G" b. v
    console.log(`----BlockNumber (${blockNumber})----`)        : a! U- a' T7 m% W# \: i2 R
console.log(`from = ${from}`)      
1 f' H, d7 |; z; K4 E  console.log(`to = ${to}`)       / I3 V! \3 A& I! _$ C/ _3 h6 ~
console.log(`value = ${value}`)        
8 V; b9 n9 S, f% B) i, rconsole.log(`----BlockNumber (${blockNumber})----`)     : C# g# ?7 [) f* N! S7 I/ V  ]
})      
, H. }) ]- j8 B' d$ _/ a9 |- `.on('changed', (log) => {     
) ^% e4 ~1 c) ~5 I   console.log(`Changed: ${log}`)    6 `$ A% x' W: o& S4 s& R0 i1 r  E
  })      .on('error', (log) => {   
+ {) A) s9 T7 d. B0 l, ^     console.log(`error:  ${log}`)    & }3 |1 n- v1 \* p1 O
  })  })  
: x- T8 g3 j6 o- A" @. Q9 W此外,获取networkId也已更新。 但过程是一样的。 我们使用web3.eth.net.getId()获取networkId,然后从Artifact中选择正确的合同地址。 初始化合同现在是一个类构造函数,在web3.eth.Contract中有一个大写C. 最后,我们创建了事件监听器。 我们现在必须自己处理“数据”,“更改”和“错误”事件。 之前它包含在前面2个示例中的watch功能中。
9 A8 F, s1 T" R  w2 e总结$ |  K7 L1 l! ]6 U/ ?, ]' q, z3 s, m
您应该了解如何将您的offchain服务连接到onchain事件。 这意味着您现在可以将区块链集成到现有基础架构中。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

李悔之2015 初中生
  • 粉丝

    1

  • 关注

    0

  • 主题

    13