Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
您的应用程序不可避免地需要与“现实世界”API进行对话,例如是发送电子邮件,查询更多数据,或充当发起其他处理的信号。 下面让我们探讨如何让以太坊智能合约与脱链服务互通。) _+ e2 R4 V# H% ^
简而言之,您可以在处理事务时使智能合约发出事件。一旦事务被挖掘,事件数据就可以读取。在下图中,您可以看到您的DApp发出的事件可以从您的API的任何服务中检索。
/ Z6 n! r1 Q/ X4 j& {" t" K
4 {0 X5 j% N% C' G0 j目前有两种方法可以获取事件数据:
. ]9 S6 o; [3 K% {; a7 j4 v目前有两种方法可以获取事件数据:
) q& V' f' H* J: x& D. _选项1:使用getTransactionReceipt7 L" Z) C7 z) S4 p) p6 P% I
选项2:为事件注册监听器
4 m! r7 E1 q2 U您可以使用选项1来获取事件数据,但是可能会存在潜在问题,因为在区块被挖掘之前收据是空的。你可以提出调查,但这很难做到。
- f: z# \; ^: b8 u( p另外,根据网络流量和gasPrice设置,交易可能长时间不会被打包。请注意,事件只有在被挖掘成区块后才会被传播。这意味着可以为任何一个区块调用多个事件。5 ?1 r4 j  K* L7 y& j! F
solidity事件
% h: j) u0 u1 v2 i在solidity里创建事件需要两个步骤:定义事件,发出事件。" D# \+ p6 R* e1 f$ M
    pragma solidity ^0.4.18;
9 y0 _+ }# H7 g  Y* l0 r  G; Ocontract MyContract {  
* }& `5 t8 c' Gevent Transfer(address indexed from, address indexed to, uint256 value); /* This is an event */  
3 P% W, H, C( X  afunction MyContract() {} /* a constructor */  3 Z- R' g% ]1 z
function transfer(address _to) public {   0 k$ l# O% V' _: M3 ]
Transfer(msg.sender, _to, msg.value);  }}  
3 v9 [) Z" H9 H+ ^1 R1 E注意事件Transfer是如何在第5行创建的,然后在函数传输中使用它发出Transfer事件(第10行)。 但会告诉你如何使用一个事件,如果我们用0x123调用传递函数,并从0x4444的地址发送1以太,则事件触发传输事件并应返回[0x4444,0x123,BigNumber(1以太)]。3 v9 B  j. ?1 h+ {
监听事件
0 s) P+ g# A# }. u* K( h以太坊实现了他们的JSON RPC规范,但任何人都可以用他们选择的语言实现自己的库。 我们将使用Truffle和原始web3 Javascript API。 监听事件的一般流程如下:
/ h8 k+ `: H) d& M1、加载合同组件
. r5 p/ e# x% G. e# b# }2、配置web3和使用truffle提供程序; h% l8 d" P3 u2 ?1 F
3、识别网络id
3 _  j. r( L: c6 A8 z+ D4 Z! N) z6 n4、从合同组件中获取正确的合同地址
8 q2 N  r" i" z" O; O2 G5、获取JavaScript合约实例
* Q1 Z" S- Q" j0 H' y6、使用可选配置调用contractInstace.NAME_OF_EVENT
. L: ^" B" T' D% b. I下面我们有3个样本使用Truffle,Web3在1.0 beta之前,Web3在1.0 beta之后。* q/ Z$ N) y/ {  E& M+ N
Truffle API
0 b3 F" \- F# q+ xTruffle是web3的一个很好的包装器,它提供了一些便利功能,使用更加轻松。 看一下下面的代码示例:" h- p6 l  g) ~4 \' w
const Web3 = require('web3') // Web3 0.20.4 or web3 1 beta0 t, H' L. z( N- j% K
const truffleContract = require("truffle-contract")
0 s! @2 V) R4 n9 \% b. jconst contractArtifact = require('./build/contracts/TutorialToken.json')
7 n) @+ l* ]+ j/ S+ Mconst providerUrl = 'http://localhost:8545'! T  h. s+ R: w0 u: [/ H9 v& r5 G
const provider = new Web3.providers.HttpProvider(providerUrl)6 r5 A4 T; Y# ?: C( K
const contract = truffleContract(contractArtifact)' ?3 o+ I( C6 y& W2 ^7 e+ x/ s
contract.setProvider(provider)" r9 g6 J5 W3 m# ?$ r) j# p
// dirty hack for web3@1.0.0 support for localhost testrpc, see https://github.com/trufflesuite/truffle-contract/issues/56#issuecomment331084530
; O: ?$ y. ~% h0 k' n7 ^7 f  {$ eif (typeof contract.currentProvider.sendAsync !== "function") {
) z7 u9 i# s, U% u& ^6 a9 k contract.currentProvider.sendAsync = function() {      ' T4 t1 z9 w5 }: I( q+ t8 n
return contract.currentProvider.send.apply(       1 o% ]( l; S% H2 D' L: u
contract.currentProvider,           # Y/ M, z9 X! B& q7 t! b% F
arguments     
( `' B1 S! v4 G6 a );   
* u' n+ b- m) _. x};  }
4 G" r5 u) ^7 o8 c3 ^. k- ^contract.deployed()  .then(contractInstance => {   % M* [5 O8 g( D
const event = contractInstance.Transfer(null, {fromBlock: 0}, (err, res) => {   
9 x- F% c5 v4 r4 q( T# p7 |9 O0 J  if(err) {      , ^! m, d7 G8 R7 A; d
  throw Error(err)     " K8 m% ]3 {/ d% L; ]' ?
}    })   
8 B6 D' O' w! R; ]" I event.watch(function(error, result){      7 F3 f  O2 i) f1 F
if (error) { return console.log(error) }     6 D' J6 D3 [/ S5 L0 u  D8 ?' x) @
if (!error) {      
+ |7 I' g5 a, b // DO ALL YOUR WORK HERE!      
  q7 d, S* Z. U! H+ F  e, U, J let { args: { from, to, value }, blockNumber } = result      
6 e6 \' u- g0 S, Y3 w4 a( G console.log(`----BlockNumber (${blockNumber})----`)        
* G/ H8 d% s* J+ {console.log(`from = ${from}`)      
# x* L2 B. l0 a. K* C6 D! P6 S console.log(`to = ${to}`)       1 H1 Y" [9 N9 T! R6 C
console.log(`value = ${value}`)      
8 n' e! n+ e$ o: {4 h console.log(`----BlockNumber (${blockNumber})----`)   
2 l3 t" F5 G- r4 o   }   & }1 S; |1 ]1 x# T3 j% v" v* I/ V
})  })
" p4 G/ D6 g4 e6 b) I" x+ {* j( G7 m$ d .catch(e => {   2 S) Q0 Z0 O! \) h2 _1 F9 @
console.error('Catastrophic Error!')  4 Z: c% B( f% U% M7 P! M* S* E( n
  console.error(e)
, D  J+ @& c* V- w* a })  
  r$ N$ T$ \4 S& m# ~6 K6 C- t: F前9行需要一些模块,并设置truffle和web3能够正常网络通信。 第12-19行作为hack使其与web3一起使用,可以忽略。 工作从第21行开始,带有contract.deployed()。 这是一个很好的truffle辅助函数,可以从创建并保存到./build/contracts的工件中选择正确的合同地址。 返回contractInstance(第23行)后,我们通过调用contractInstance.NAME_OF_EVENT来“创建”该事件。 存在更多选项,可在此处找到。 我从0块中选择,因为它是我们自己的testrpc。 对于您的合同,最好选择更接近合同创建时的块编号。6 Q: D5 f$ K, r
Raw Web3(0.20.4及以下)
! o0 i( b0 f; d: h- t7 _对于第二个示例,我们将直接使用Web3。 除了上一个示例中的hack之外,代码流程类似。
! {! u/ u4 m7 D( I" z* P! b0 k  const Web3 = require('web3') // Works with web3 0.20.4
1 g' t; p) @/ h) h1 m1 Cconst contractArtifact = require('./build/contracts/TutorialToken.json')
' W. V' G& y. b7 i* o' r9 w/ }2 `const web3 = new Web3()+ s+ R2 V) w. J& Q; ^% U
const providerUrl = 'http://localhost:8545'
# h: U% U" q. h5 ]const provider = new Web3.providers.HttpProvider(providerUrl)web3.setProvider(provider)
# `5 K! J" ]0 sconst networkId = web3.version.networkconst 4 u) J: C$ q& |  z
contractAddr = contractArtifact.networks[networkId].address8 X4 S! K* G  I% L2 k, G
const TutorialToken = web3.eth.contract(contractArtifact.abi, contractAddr)
8 l! d7 o& j9 Aconst contract = TutorialToken.at(contractAddr)
5 [+ j( k, \; S3 e7 ]const event = contract.Transfer()
8 ^( U) y" Q- d" `3 M) F' wevent.watch(function(error, result){   + W6 A) J1 C: U) v/ o3 U" }
if (error) { return console.error(error) }    + S3 [) `8 A! S" U' A9 Q# T
  let { args: { from, to, value }, blockNumber } = result      % ~' y2 e/ x. {
console.log(`----BlockNumber (${blockNumber})----`)      6 l/ C9 n% q9 ]0 [
console.log(`from = ${from}`)      / E" P# H$ Q) t6 _% [
console.log(`to = ${to}`)      
* H; T$ M5 ^2 m) h+ @* Fconsole.log(`value = ${value}`)      
: l$ I  Q9 X% d9 Z# `3 N6 `' Iconsole.log(`----BlockNumber (${blockNumber})----`)  });  4 A5 @: ]1 o5 ?4 @2 {  n
最重要的区别是第9-12行,我们手动从组件中抓取正确的网络。 我们没有很好的truffle.deployed功能来实现这一步。 现在我们在truffle示例中执行与之前相同的操作,并通过调用contract.NAME_OF_EVENT来创建事件。 在这个版本中我没有放一个块号,但是你可以传递与truffle版相同的东西。
% s; Y) b: R3 j& \& j  X* J+ @Raw Web3 1.0.0 beta$ r" c  M0 I! O1 l; G
Web3确实为API带来了大量更改。 一个重大变化是我们必须使用webSockProvider来注册事件而不是httpProvider。) t$ A: l- A" @
const Web3 = require('web3') // Works with web3 1.0.0-beta27
4 [- e- b) w" s& h1 Fconst contractArtifact = require('./build/contracts/TutorialToken.json')
4 M- @1 B, i. m% ]const web3 = new Web3()
# [; B+ X1 r: c3 S, ]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# v6 {9 @8 a7 e( e& r
const provider = new Web3.providers.WebsocketProvider(providerUrl)
2 F$ M; ^# E/ D# S" A, U$ g8 dweb3.setProvider(provider)
9 q8 @2 z- ]$ `$ i3 k* mweb3.eth.net.getId()  .then(networkId => {   : N: J' [5 {0 v7 e+ R# e$ l
const contractAddr = contractArtifact.networks[networkId].address    1 `  l. j; b9 |+ |% a* d- R0 l) ^" B
const TutorialToken = new web3.eth.Contract(contractArtifact.abi, contractAddr)      |! y* `$ L' j/ r. F% B% c0 v
TutorialToken.events.Transfer({fromBlock: 0},
7 U' f( Z; p; b: U function(error, event){ console.log(error) })      * t5 t: s4 ]5 E; C" b
.on('data', (log) => {       6 V% j' n! q/ u! m' S" p
let {
7 S$ J3 x, a" s) X! A' W8 C7 g$ I& y" XreturnValues: { from, to, value }, blockNumber } = log    7 W7 F& ~' |! G" v
    console.log(`----BlockNumber (${blockNumber})----`)        & l# V( ~, G3 G6 }. d2 P$ ?
console.log(`from = ${from}`)      
2 g% B; o. J. A9 d" h+ t  console.log(`to = ${to}`)      
# g# B3 u5 L# n: T7 F/ E9 z# M" J* J console.log(`value = ${value}`)        * M% `- D, S2 A! \; s2 X/ L
console.log(`----BlockNumber (${blockNumber})----`)     
2 `' H+ A  v( ?; e })      ' t. w$ K) L8 `7 T0 z. T% r
.on('changed', (log) => {     
# K. ]0 r  Z- a/ L9 _9 G% X0 Z8 r   console.log(`Changed: ${log}`)    $ E8 T6 v/ U! [/ n7 J) Q) R
  })      .on('error', (log) => {   ' Y0 {) o6 x5 F4 t- v$ c/ L: H
     console.log(`error:  ${log}`)    - x/ P7 d4 N: A+ f5 i" O. K2 q2 f
  })  })  
4 o; H5 ]1 u) ]此外,获取networkId也已更新。 但过程是一样的。 我们使用web3.eth.net.getId()获取networkId,然后从Artifact中选择正确的合同地址。 初始化合同现在是一个类构造函数,在web3.eth.Contract中有一个大写C. 最后,我们创建了事件监听器。 我们现在必须自己处理“数据”,“更改”和“错误”事件。 之前它包含在前面2个示例中的watch功能中。
5 E% m' E& x$ Y6 u4 L总结6 A$ f% F6 w) Z8 W! E
您应该了解如何将您的offchain服务连接到onchain事件。 这意味着您现在可以将区块链集成到现有基础架构中。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

李悔之2015 初中生
  • 粉丝

    1

  • 关注

    0

  • 主题

    13