Waves - ブロックチェーンの更新情報を受け取る

Wavesネットワーク上には、発行されたトランザクションや生成されたブロックが飛び交っている。
これらの情報はWavesノードに問い合わせれば都度得られる。
けれど、リアルタイムに更新されていく訳だから通知してくれるとありがたいよね。
Waves WebSocket APIがリアルタイムにプッシュ通知してくれる。

受け取れる情報は上記リンク先のサイトに書いてある通り。

  • 新たに発行された未承認トランザクション
  • 承認された(ブロックに取り込まれた)トランザクション
  • 新たに生成されたブロック
  • ブロックチェーンの更新により変化する残高
  • DEX取引

特定のアドレス/アセットIDのみ指定して通知を受け取ることもできる。

使ってみる

例によってPythonでやる。
PythonでのWebsocketは、いくつかライブラリがある。
今回はAutobahnを使う。
(選定理由はとくにない)

インストール

pip でインストール

$ pip3 install autobahn

asyncio または twistedの仕組みの上で動かす。
twistedでやる場合はtwistedが必要、合わせてインストールしておく。
今回は asyncioでやる

使い方

ドキュメントの通り。
ほぼサンプルコードのまま。
WebSocketのセッションが確立されるとonOpen()が呼ばれるので、
通知してほしい(sabscribeする)イベント情報をサーバへメッセージを送って伝える。
あとは、プッシュ通知のあった都度onMessage()が呼ばれるので、何の通知(情報)かを判定し処理をする。
subscribeメッセージの応答やキープアライブのping-pongがあるので、
一種類のみの購読であっても判定処理はちゃんとやる。

非同期通信の細かい話を知りたい場合は、別途勉強のこと。

サンプル

#!/usr/bin/env python3
# coding: utf-8
"""python script
"""

import asyncio
import json

from autobahn.asyncio.websocket import WebSocketClientProtocol, WebSocketClientFactory


class WavesDataFeed(WebSocketClientProtocol):

    def onConnect(self, response):
        # tcp connected
        print('connected - {}'.format(response.peer))

    def onOpen(self):
        # websocket のセッション開始
        print('ws open')

        # subscribe する
        self.sendMessage('{"op": "subscribe block"}'.encode('utf-8'))

        # keepalive
        def keepalive():
            self.sendMessage('{"op": "ping"}'.encode('utf-8'))
            # 30秒間隔でkeep-aliveし続ける
            self.factory.loop.call_later(30, keepalive)

        keepalive()

    def onClose(self, wasClean, code, reason):
        print('ws closed - {}'.format(reason))

    def onMessage(self, payload, isBinary):
        if isBinary:
            # binary data はこない
            return

        resp = json.loads(payload.decode('utf-8'))
        op = resp.get('op', 'pong')
        # subscribeしている情報を処理する
        if op == 'block':
            msg = resp.get('msg')
            # 生成した人は?
            print('generated by: {}'.format(msg.get('generator')))

        # 何もしない
        #elif op == 'pong':
        #    print('ping - pong')


def main():
    # websocket endpoint
    factory = WebSocketClientFactory('ws://ws.wavesplatform.com/api')
    factory.protocol = WavesDataFeed

    loop = asyncio.get_event_loop()
    coro = loop.create_connection(factory, 'ws.wavesplatform.com', 80)
    loop.run_until_complete(coro)
    loop.run_forever()
    loop.close()


if __name__ == '__main__':
    main()

使い道など

Wavesノードを動かさなくてもブロックチェーンを追えるようになるわけだが。
(ただし、古い情報を得るにはノードに問い合わせるしかない。)

分かりやすいのはDEXのボット用かな。
自分の(特定の)アドレスを監視しておき、WAVES/トークン受信と同時に何かしら処理するとか。
リース管理やアタッチメント部分にコマンド埋め込んでシステム制御くらいはすでにやられてそう。


See also