NEM-sdkを使ってみる WebSocket編

少しバタバタしていたので間が空いてしまいましたが、引き続き以下のNEM-sdkを使ってみます。

github.com

今回はsdkを利用してWebSocketのAPIと接続してみます。

コネクターオブジェクトの作成

まずendpointaddressを渡してconnectorオブジェクトを作成します。

let endpoint = nem.model.objects.create("endpoint")
  (nem.model.nodes.defaultMainnet, nem.model.nodes.websocketPort);
let address = "NDLHY5KMQTATAR7IBRBF32MAQWDK7333VNI2MD5W";
let connector = nem.com.websockets.connector.create(endpoint, address);

NISへの接続

次にconnectorオブジェクトのconnectを呼んでNISへ接続し、返されたPromiseのコールバック関数でチャネルの購読処理や、リクエストを行います。

subscribe

チャネルの購読処理にはnem.com.websockets.subscribeを利用します。

  • errors

 文字通りなんだとは思いますが、今のところ何か流れてきたことがありません。

  • chain.height

 現在のブロック高を返します。

  • chain.blocks

 最新のブロックの情報と含まれるトランザクションの配列を返します。

  • account.data

 アカウントの残高やパブリックキーなどの情報を返します。

  • account.transactions.recent

 該当アドレスの最新25個の承認済トランザクション情報を返します。

  • account.transactions.unconfirmed

 該当アドレスに関する未承認トランザクションを返します。

  • account.transactions.confirmed

 未承認トランザクションが承認されたタイミングで、そのトランザクションを返します。

  • account.mosaics.definitions

 該当アドレスが所有するモザイクの定義を返します。xemも含まれます。配列ではなくモザイクごとに別々にオブジェクトを返します。

  • account.mosaics.owned

 該当アドレスのモザイク残高を返します。xemも含まれます。配列ではなくモザイクごとに別々にオブジェクトを返します。

  • account.namespaces.owned

 該当アドレスがオーナーのnamespaceを返します。

requests

こちらからデータを要求する場合は、nem.com.websockets.requestsを利用します。

  • account.data
  • account.transactions.recent
  • account.mosaics.definitions
  • account.mosaics.owned
  • account.namespaces.owned

それぞれ該当のチャネルを購読していれば、そこにデータが流れてきます。

なお、account.transactions.recentをリクエストすると、承認済トランザクションと共に未承認トランザクションも返ってきます。逆に、初回起動時にaccount.transactions.recentをリクエストしていない場合、account.transactions.unconfirmedを購読していても、すでにブロードキャスト済で未承認なトランザクションを把握出来ません。

コード

そのまま書くと関数名がいちいち長くて見づらいですが、コードは以下のようになります。

connector.connect().then(() => {
  console.log("Connected");

  nem.com.websockets.subscribe.errors(connector, res => console.log("errors", res));
  nem.com.websockets.subscribe.chain.blocks(connector, res => console.log("blocks", res));
  nem.com.websockets.subscribe.chain.height(connector, res => console.log("height", res));
  nem.com.websockets.subscribe.account.data(connector, res => console.log("data", res));
  nem.com.websockets.subscribe.account.transactions.recent(connector,  res => console.log("recent", res));
  nem.com.websockets.subscribe.account.transactions.unconfirmed(connector, res => console.log("unconfirmed", res));
  nem.com.websockets.subscribe.account.transactions.confirmed(connector, res => console.log("confirmed", res));
  nem.com.websockets.subscribe.account.mosaics.definitions(connector, res => console.log("definitions", res));
  nem.com.websockets.subscribe.account.mosaics.owned(connector, res => console.log("owned", res));
  nem.com.websockets.subscribe.account.namespaces.owned(connector, res => console.log("namespaces", res));

  nem.com.websockets.requests.account.data(connector);
  nem.com.websockets.requests.account.transactions.recent(connector);

  nem.com.websockets.requests.account.mosaics.definitions(connector);
  nem.com.websockets.requests.account.mosaics.owned(connector);
  nem.com.websockets.requests.account.namespaces.owned(connector);

}, err => console.log("errorMessage", err));

実行時の流れ

まず接続に成功するとConnectedが出力され、リクエストしたdatarecentdefinitionsowned、存在すればnamespacesが返り、ブロックが進むごとにheightblocksが返ります。

ちなみに接続に失敗すると10回繰り返してその後エラーが出力されます。

送金や着金があった場合、まずunconfirmedが返ります。 この時点ではnem.com.websockets.requests.account.dataで最新データを要求してもまだ残高は変わっていないので、未承認トランザクションを含めるとどうなるかはこのunconfirmedの結果を反映してあげる必要があるようです。

ブロックが進むとheightblocksが返り、未承認のトランザクションが承認に変わるのでconfirmedが返ります。

承認されると自分の残高が変わるので最新のdataが返ります。ゼロになった場合は残高ゼロで値が返ります。

モザイク

xem以外のモザイクに動きがあった場合はdefinitionsownedが所有モザイクの数だけそれぞれ返りますが、ゼロになった場合はゼロが返るのではなく、該当モザイクのオブジェクトは何もかえってきません。

手持ちのモザイクの一つを送信してゼロになった場合、モザイクに動きがあったので残された他のモザイクについてdefinitionsownedは返りますが、該当のモザイクについては何も返らないという事になります。

返ってきたオブジェクトを次々と配列に入れていく作りにした場合、ゼロになったタイミングを把握出来ないのでいまいち使いにくいです。NanoWalletの実装もそうなっていて、送金後ゼロになった場合も、残高は更新されません。(少なくとも1.2.12ではそうでした)

何故配列で返す仕様にしなかったんだろう??

とりあえず、承認されたトランザクションを元に自力で計算するか、confirmedのところで一旦配列をリセットし、definitionsownedを強制的にリクエストして再度配列を作り直すなど工夫が必要そうです。


これで残高、未承認トランザクションなど、リアルタイムでデータを更新可能なサービスが作れるようになりました。

今度こそチャーハンを作る準備は整った。かな?

※筆者のモチベーション向上のため、以下NEMアドレスへxemなりシットトークンなりの寄付を受け付けています。

NDY4RH-UZ3CZO-Z53O5H-NEXTEM-7UF5X3-MMDGH4-IMAD