1. 链一财经首页
  2. 资讯

tendermint提供的RPC接口(三)

本文是系列文章第三篇,主要介绍如何自定义订阅事件。
/subscribe
说明:通过wensocket订阅事件。
想要订阅某个事件,需要提供一个字符串表达式,格式是“condition AND condition ”(只能用AND不能用OR)。condition的格式是“key operation operand”,
key是一个字符串(tnr()'”=><不允许出现在key中)
operation可以是“=”,“”,“> =”, “CONTAINS”
operand可以是一个字符串(要用单引号转义),数字,日期或者事件。
比如:
tm.event = ‘NewBlock’ // 新区快产生
tm.event = ‘CompleteProposal’ // 完成一个提案
tm.event = ‘Tx’ AND tx.hash = ‘XYZ’ // 某一笔交易
tm.event = ‘Tx’ AND tx.height = 5 // 第五个块的所有交易
tx.height = 5 // 第五个块的所有交易
tendermint提供了几个预定义的key:tm.event,tx.hash,tx.height。但是用户可以通过重定义DeliverTx的响应来增加key,用以订阅其他的事件。例如定义以下event
types.ResponseDeliverTx{
   Events: []types.Event{
      {
         Type: “rewards.withdraw”,
         Attributes:
         common.KVPairs{
            common.KVPair{Key: []byte(“address”), Value: []byte(“AddrA”)},
            common.KVPair{Key: []byte(“source”), Value: []byte(“SrcX”)},
            common.KVPair{Key: []byte(“amount”), Value: []byte(“…”)},
            common.KVPair{Key: []byte(“balance”), Value: []byte(“…”)},
         },
      },
      {
         Type: “rewards.withdraw”,
         Attributes: common.KVPairs{
            common.KVPair{Key: []byte(“address”), Value: []byte(“AddrB”)},
            common.KVPair{Key: []byte(“source”), Value: []byte(“SrcY”)},
            common.KVPair{Key: []byte(“amount”), Value: []byte(“…”)},
            common.KVPair{Key: []byte(“balance”), Value: []byte(“…”)},
         },
      },
      {
         Type: “transfer”,
         Attributes: common.KVPairs{
            common.KVPair{Key: []byte(“sender”), Value: []byte(“AddrC”)},
            common.KVPair{Key: []byte(“recipient”), Value: []byte(“AddrD”)},
            common.KVPair{Key: []byte(“amount”), Value: []byte(“…”)},
         },
      },
   },
}
所有事件都由eventType和eventAttrKey形式的符合键索引,在上面的示例中,将对以下键进行索引:
rewards.withdraw.address
rewards.withdraw.source
rewards.withdraw.amount
rewards.withdraw.balance
transfer.sender
transfer.recipient
transfer.amount
允许多个事件类型具有重复的键,并且可以用于对唯一和不同事件进行分类。
在上面的示例中,在密钥rewards.withdraw.address下索引的所有事件将具有以下存储和可查询的值:AddrA,AddrB
创建各种类型的交易订阅:
query.MustParse(“tm.event = ‘Tx’ AND rewards.withdraw.address = ‘AddrA'”)
query.MustParse(“tm.event = ‘Tx’ AND rewards.withdraw.address = ‘AddrA’ AND rewards.withdraw.source = ‘Y'”)
query.MustParse(“tm.event = ‘Tx’ AND transfer.sender = ‘AddrA'”)
这几种是无返回值的:
query.MustParse(“tm.event = ‘Tx’ AND transfer.sender = ‘AddrZ'”)
query.MustParse(“tm.event = ‘Tx’ AND rewards.withdraw.address = ‘AddrZ'”)
query.MustParse(“tm.event = ‘Tx’ AND rewards.withdraw.source = ‘W'”)
下面是示例。
自定义的event代码:
var events []types.Event
if strings.HasPrefix(k,”a”){
   events = []types.Event{
      {
         Type: “string”,
         Attributes: []common.KVPair{
            {Key: []byte(“startWith”), Value: []byte(“a”)},
            {Key: []byte(“key”), Value: key},
         },
      },
   }
}
if strings.HasPrefix(k,”b”){
   events = []types.Event{
      {
         Type: “string”,
         Attributes: []common.KVPair{
            {Key: []byte(“startWith”), Value: []byte(“b”)},
            {Key: []byte(“key”), Value: key},
         },
      },
   }
}
订阅代码分为2个线程:
func main() {
   cli := client.NewHTTP(“http://localhost:26657”, “/websocket”)
   err := cli.Start()
   if err != nil {
      fmt.Println(err)
      return
   }
   defer cli.Stop()
   ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
   defer cancel()
   //query := “app.key=’author'”
   txs, err := cli.Subscribe(ctx, “test-client”, “string.startWith = ‘a'”)
   if err != nil {
      fmt.Println(“错误信息”, err)
      return
   }
   for tx := range txs {
      fmt.Println(“startWithA接收到消息:n”, tx)
   }
}
func main() {
   cli := client.NewHTTP(“http://localhost:26657”, “/websocket”)
   err := cli.Start()
   if err != nil {
      fmt.Println(err)
      return
   }
   defer cli.Stop()
   ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
   defer cancel()
   //query := “app.key=’author'”
   txs, err := cli.Subscribe(ctx, “test-client”, “string.startWith = ‘b'”)
   if err != nil {
      fmt.Println(“错误信息”, err)
      return
   }
   for tx := range txs {
      fmt.Println(“startWithB接收到消息:n”, tx)
   }
}
分别发送交易:
curl -s localhost:26657/broadcast_tx_commit?tx=”aunt=a1234″
curl -s localhost:26657/broadcast_tx_commit?tx=”buss=b5678″

可以看到两个窗口分别收到消息:

tendermint提供的RPC接口(三)

这只是一个示例,在实际使用过程中会更加复杂一些,例如对某个交易地址的监控,对大额转账的监控等等。
文章发布只为分享区块链技术内容,版权归原作者所有,观点仅代表作者本人,绝不代表区块链兄弟赞同其观点或证实其描述。

根据国家《关于防范代币发行融资风险的公告》,大家应警惕代币发行融资与交易的风险隐患。

本文来自LIANYI转载,不代表链一财经立场,转载请联系原作者。

发表评论

登录后才能评论

联系我们

在线咨询:点击这里给我发消息

邮件:kefu@lianyi.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code