NEM1とNEM2のユースケース別API変更点
最近、ProximaX に contribution させていただき、NEM2(Catapult)向けの Swift SDK を開発しました。
ProximaX に contribution させてもらいました。
NEM2(Catapult) の Swift SDK を開発させてもらいました。
Aggregate Transaction など含めて、NEM2 で使えるトランザクションは対応済みです。#nemhttps://t.co/xzwMJdA5tT— りゅーた@田舎フリーランス (@ryuta461) October 15, 2018
SDK 開発を通して、結果的に NEM2 で用意されてる API を一通り触ることになりました。
NEM2 では後方互換性が担保されないという話は聞いていましたが、NEM2 と NEM1 がどれくらい API が違うのか理解する良い機会になったので、わかったことなどをシェアさせてもらえればと思います。
説明は少し大雑把なので、API の詳細知りたい方は公式の API リファレンスを確認してください。
https://nemtech.github.io/api.html
この記事のゴール
NEM1(現在の NEM ) で何かアプリ・サービスを開発されている方が、現状のアプリ・サービスを NEM2 に対応させるにはどういう変更が必要か、なんとなくイメージを掴めるようになる。
NEM2で追加されたトランザクションを使えばいろいろおもしろいことができそうに思いましたが、今回は主に既存サービスの移行を目的とした内容を書いています。
目次
ユースケース別に書いていきます。開発しているウォレット(RaccoonWallet) で使ってる API に寄ってるかもしれませんが、たぶん大体のアプリはこの範囲に入るのではないかと思ってます。
- アカウント作成
- 残高取得
- アカウントのマルチシグ情報取得
- トランザクション取得
- トランザクション発行
アカウント作成
NEM1
- Path: /account/generate
NEM1 の方にはAPIで秘密鍵・公開鍵を作成する方法がありますが、通常は SDK などで用意されてる方法でオフラインでアカウント生成することが多いかと思います。
NEM2
NEM2 では API でアカウント作成する方法はなさそうです。SDK でオフラインでアカウントを生成することになるのではないかと思います。
それは良いんですが、現状の NEM2 の SDK の実装、NEM1 の SDK とハッシュ関数が違うみたいなんですよね。Keccak じゃなく SHA3 を使ってるみたいです。その結果、同じ秘密鍵から生成したアドレスが NEM1 と NEM2 の SDK で違うという結果になっていました。
・・・という話を Twitter で呟いたところ、planetさんより、将来的にはプライベートチェーンとパブリックチェーンで Keccak と SHA3 をわけることになっているらしいという話を伺いました。
うーん、多分ないと思います。私の場合は、slackで質問したら、Aleixが答えてくれました。 pic.twitter.com/nSVIowA4va
— planet★箒星 (@planethouki) September 27, 2018
というわけで、最終的にはパブリックチェーンでは NEM1 と NEM2 で同じ秘密鍵から、同じアドレスが生成されることになると思います。(そうじゃないと大混乱になりそう。)
残高取得
NEM1
XEM の保有量を調べる
- Path: /account/get
- パラメータ: アドレス
アドレスを渡してアカウント情報を取得します。アカウント情報の中に balance
として XEM の残高があるので、これを使います。アドレスではなく公開鍵を渡して情報を取得する、/account/get/from-public-key
という API もあります。
モザイク保有量
- Path: /account/mosaic/owned
- パラメータ: アドレス
API のレスポンスには XEM もモザイクとして含まれているので、XEM も含めてモザイク保有量を取得する場合は /account/mosaic/owned
一発で済ます場合もあるかと思います。
/account/mosaic/owned
は、ネームスペース名、モザイク名と保有量が取得できますが、可分性の情報が取得できません。可分性については以前モザイク送金のところで書いたのでそちらの記事を参考にしてください。
保有量そのままで表示すると 「実際に持ってる量の1000倍の値が表示されてるよ!」 みたいなツッコミを受けることがありますので、可分性の情報も合わせて取得する事が多いかと思います。その場合はモザイク定義を取得する API を使います。
- Path: /namespace/mosaic/definition/page
- パラメータ: ネームスペース名
ネームスペース名を渡して、そのネームスペース内にあるモザイク定義を取得します。この API、ページングする仕様になっていて、目当てのモザイク定義が見つかるまで複数回 API の呼び出しする必要があるんですよね・・・ちょっと面倒。
ともあれ、
XEM の残高だけが必要 => /account/get
モザイクも含めて残高取得 => /account/mosaic/owned
で保有量取得後、 /namespace/mosaic/definition/page
で可分性取得
という流れが NEM1 の方法です。
NEM2
NEM2 では、NEM1 の XEM 保有量だけ調べる API がありません。また、公開鍵を指定して残高を取得する API はありません。
XEM 保有量もそれ以外のモザイク保有量も、アカウント情報を取得する API を使うことになります。(XEM とそれ以外のモザイクについて区別がない)
- Path: /account/アドレス
大きな変更点の一つは、モザイクは名前ではなく、固有の ID が返ってくるという点です。
これはレスポンス例を見たほうがわかりやすいかと。
1 2 |
$ curl "http://192.168.10.9:3000/account/SA3G7ZXZ3XTFXIKA4B7PKET67UBGYB6AW3YYXPOY" |
レスポンス例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "meta":{}, "account":{ "address":"90366FE6F9DDE65BA140E07EF5127EFD026C07C0B6F18BBDD8", "addressHeight":[78533,0], "publicKey":"9073C65412CA38705EBB2131C97C5189F8B9F9EF314CE0F85BB9E0A43325BED3", "publicKeyHeight":[102798,0], "mosaics":[ { "id":[3646934825,3576016193], "amount":[930065378,2] }, ], "importance":[0,0],"importanceHeight":[0,0] } } |
mosaics
という項目で ID と保有量とが返ってきているのがわかるかと思います。
id、amount ともに2つの整数から成る配列として返ってきていますが、これは [3646934825,3576016193]
の部分で 一つの64bit 整数を表現しています。
id、amount に限らず、64ビットの整数は、下位32ビット分と上位32ビット分の整数の配列としてレスポンスが返ってきます。Javascript に配慮したような記載がAPI リファレンスの最初の方に書いてあります。
生のレスポンスは整数の配列ですが、おそらく各言語の SDK で 符号なし64ビット整数型など変換すると思うので、SDK 利用者はあまり意識しなくても良いかも。(Swift の SDK でも当然 64ビット整数に変換してます)
とりあえず、上記 account
API で保有してるモザイクの ID は取得できるのですが、IDをユーザに見せてもわからないと思うので、モザイク名とネームスペース名を取得する必要があります。mosaic
API を使ってモザイクの定義を取得します。
- Path: /mosaic/モザイクのID
この API で、ネームスペース名、モザイク名と可分性などの情報も取得できます。
また、上記 Path は GETバージョンですが、POST で複数のモザイクIDをパラメータとして渡し、一回のAPIコールでまとめてモザイク定義を取得することもできます。
モザイク保有量取得した時にモザイク名がわからないので、NEM2の方が手数が多くなっているように感じるかもしれませんが、どうせ可分性を取得することまで考えると NEM2 は 2回の API コール、NEM1 は 2回以上の API コールなので、微妙に効率が良くなってると捉えることもできます。
ちなみに、モザイクIDはモザイクの名前からオフラインで計算する事ができます。(ネームスペースIDとモザイク名を連結したバイト列の SHA-3 ハッシュ)
アカウントのマルチシグ情報取得
最低必要署名数とかの情報です。
NEM1
上記の /account/get
で、multisigInfo
という項目で返ってきます
NEM2
アカウントのマルチシグ情報を取得するための API があります。
- Path: /account/アドレス/multisig
レスポンス内容はだいたい同じ。
トランザクション取得
NEM1
- Path: /account/transfers/all
- パラメータ: アドレス
アドレスを指定してトランザクション取得。承認済みの全てのトランザクション(all)、送信トランザクション(outgoing)、受信トランザクション(incoming)、未承認トランザクション(unconfirmedTransactions) といった API があります。
NEM2
- Path: /account/公開鍵/transactions
トランザクションはアドレスではなく公開鍵を使って取得するようになりました。
アドレスから公開鍵を取得するのは、上記の account
API を使います。
公開鍵からアドレスはオフラインで計算できるので、もしユーザの情報とか保存する必要があるならアドレスより公開鍵保存した方が良いかも、と思いました。
送信や受信、未承認などそれぞれに API があるのは NEM1 と同じです。
トランザクション発行
トランザクションを秘密鍵を使って署名して送信する流れは同じなので、送信する部分の API の違いだけ見ます。
NEM1
- Path: /transaction/announce
署名済みのトランザクションを送信します。
レスポンスで、トランザクションが問題ないかが返ってきます。残高不足などのエラーであればエラーレスポンスが返ってきます。
実はここが NEM2 と違います。
NEM2
- Path: /transaction
署名済みのトランザクションを送信するのは同じですが、レスポンスは送信できた旨を表すもので、残高不足などのエラーが発生するかはこの時点では返ってきません。
レスポンス例
1 2 3 4 |
{ "message": "packet 9 was pushed to the network via /transaction" } |
送信したトランザクションでエラーが発生しているかどうかは別途取得する必要があります。
私の知っている範囲ではこの方法は2つ、REST API を使用する方法と WebSocket を使用する方法があります。
トランザクションのハッシュを使用して API で取得
トランザクションのハッシュ値を指定して、トランザクションの状態を取得するという API があります。
- Path: /transaction/ハッシュ値/status
レスポンス例(残高不足で失敗)
1 2 3 4 5 6 7 |
{ "group":"failed", "hash":"81EC792C0672702DDA7017D584729C73B738907307A2328EAF6FB5A3E30245CB", "status":"Failure_Core_Insufficient_Balance", "deadline":[2992771583,18], } |
レスポンス例(成功。承認済み)
1 2 3 4 5 6 7 8 |
{ "group":"confirmed", "status":"Success", "hash":"E7341AB350CCF6DFA25696548ACC26FBE71834EC7D8D20889748AA28B8B6102D", "deadline":[2992694643,18], "height":[142870,0] } |
group
という項目でエラー、承認済み、未承認などの状態がわかります。エラーであれば status
でそのエラー内容がわかります。
で、このトランザクションのハッシュはどうやって取得するんだという話ですが、トランザクションの署名を行う際にオフラインで計算することができます。
TypeScript の SDKだと、トランザクション署名時に作られる SignedTransaction というクラスのオブジェクトがメンバとしてハッシュを保持していますので、これを API に指定すれば OK です。( Swift の SDK でも同様)
つまり、トランザクションの発行時は
1. トランザクション署名(SignedTransactionを取得)
2. SignedTransactionを送信
3. SignedTransaction.hash を使ってトランザクションの状態を取得
の流れになるかと思います。
WebSocket を使用してトランザクションのエラーを取得する
NEM2 でも NEM1 と同じように WebSocket があります。
その中に、status
というチャンネルがあり、特定のアドレスに関係するトランザクションでエラーが発生した場合に通知が送られてくるチャンネルがあります。
ただ、ハッシュ値がわかっているのであれば上記の REST API を使う方法の方が簡単なので、そちらを使うほうが良いかなと思います。
まとめ
- アカウント作成
現状だと NEM1 と NEM2 の SDK でハッシュアルゴリズム違うからアドレス変わってしまうけど、たぶん最終的には気にしなくて良くなると思う。 - 残高取得
モザイクが ID で返ってくるのでモザイク定義の取得が別途必要 - アカウントのマルチシグ情報取得
新規で専用のAPI があるのでそれを使う - トランザクション取得
アドレスじゃなくて公開鍵を使って取得するようになった - トランザクション発行
トランザクションでエラーが発生しているかは別途取得が必要
さいごに
ここに書いたこと以外にも細かい違いはたくさんあります。
API 自体の変更が多く、ライブラリで差分を吸収できる範囲を超えてると思いますので、ライブラリを差し替えて終了ってわけにはいかなそうです。
現状のNEM1 でアプリ・サービスを開発してるときはいつかは対応が必要かと思います。(いつかは、知らないけど・・・)
繰り返しですが、NEM2 の新しいトランザクションについてここでは書いてませんので、もしかしたら別記事で書くかもしれません。
最後まで読んでいただきありがとうございます。 このブログを「いいな」と感じていただけましたら、Twiter にてフォローいただけるとうれしいです。ブログ更新情報などもお届けします。
Follow @ryuta461
この記事をシェアする