NEM NanoWalletのServicesをnpmモジュール化する

前回に続いて、NEM NanoWalletの中身をnpmモジュール化していきます。

tadajam.hateblo.jp

前回はUtilsをnpmモジュール化したので、今回はそのモジュールを利用した各種Servicesの移植に進みます。

Services

まずはServicesの中身を整理します。

github.com

  • Alert alert.service.js

 エラーメッセージに関するサービス。

  • Connector connector.service.js

 SockJSを利用してWebSocket APIに接続するサービス。

  • DataBridge dataBridge.service.js

 NetworkRequestsやConnectorを利用してデータを取得、保持するサービス。

  • NetworkRequests networkRequests.service.js

 各種APIへ接続するサービス。

  • Transactions transactions.service.js

 各種トランザクションを作成するサービス。

  • Wallet wallet.service.js

 カレントアドレスと接続ノードなどを設定するサービス。

  • WalletBuilder walletBuilder.service.js

 アドレスを生成するサービス。

WebSocketでリアルタイムにデータを取得したいのであれば、ConnectorDataBridgeが必要になりますが、トランザクションを生成してブロードキャストするだけなら、NetworkRequestsTransactionsがあれば事足りるので、今回はこの二つのファイルを対象とします。

対象のファイル2ファイルは、上記のDataBridgeWalletを参照しています。

DataBridgeについては、NISとの時刻の同期を行っている部分を参照しているだけなので、今回は時刻同期無しでDataBridgeは無視します。

Walletについては、今回は定数としてしか使わないので、定数を保持するだけのクラスとして実装します。本来はWalletインスタンスをコンストラクタで受ける形になるかと思います。

また、以下のconfigフォルダにあるAppConstantsも参照しています。

github.com

AppConstantsはデフォルトのポート番号や、有効な言語の一覧などが入っている設定ファイルなので、スタティックな変数だけ持つクラスとして実装します。

Typescriptで実装する

せっかくなのでTypescriptで書き換えていきます。(と言っても片っ端からanyで型指定していくことに何の意味があるのかは知りませんがw)

まずは、TypeScriptのファイルと、生成されるJavaScriptのファイルをそれぞれ管理する必要があるので、少し環境を整えます。

srcがソース置き場、libが実体置き場ということにしてディレクトリを分けます。

npmには実体だけアップしたいので、.npmignoreに除外するsrcフォルダを指定します。

.npmignore

src/

また、生成されたJavaScriptのファイルをgitで管理したくないので、.gitignoreに除外するlibフォルダを指定します。

.gitignore

lib/

srcディレクトリに移動してtsc--initオプションでtsconfig.jsonを生成し、outDirで出力先を設定します。

tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "noImplicitAny": false,
    "sourceMap": false,
    "outDir": "../lib"
  }
}

最終的なディレクトリ構成は以下のようになります。

nem-services
│  .gitignore
│  .npmignore
│  LICENSE
│  package.json
│  README.md
│
├─lib
│      appConstants.js
│      index.js
│      networkRequests.js
│      transactions.js
│      wallet.js
│
└─src
        appConstants.ts
        index.ts
        networkRequests.ts
        transactions.ts
        tsconfig.json
        wallet.ts

それぞれのサービスの実装

あとはそれぞれのファイルの、元のコードのままでは動かない部分について修正しつつ、狂ったように型指定していきます。

基本的にはそのままですが、AngularJSのhttp部分をisomorphic-fetchで書き換えました。 fetchした時に帰ってくるPromiseObservableにしていじくりまわしたのでrxjsも必要になりました。 なぜここでRxJSかというと、それってモダンじゃね?ぐらいの感覚で良く分かってませんw

package.json

"dependencies": {
  "rxjs": "^5.1.0",
  "isomorphic-fetch": "^2.2.1",
  "nem-utils": "0.0.3"
}

NetworkRequests

httpアクセス部分は以下のような感じです。 正直、Observableの使い方、使いどころが正しいのか良く分かりませんが、動いたので正しいということにしておきます。

import * as fetch from "isomorphic-fetch";
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';

getHeight(host: string): Observable<number> {
  let url: string = "http://" + host + ":" + this.getPort() + "/chain/height";

  return Observable.fromPromise(fetch(url))
    .flatMap(response => response.json())
    .map(json => json.height);
}

Transactions

DataBridgeが担っていた部分は、以下のように書き換えました。


// let d = new Date();
// let timeStamp = Math.floor(this._DataBridge.networkTime) + Math.floor(d.getSeconds() / 10);
let timeStamp: number = helpers.createNEMTimeStamp();

その他、jQueryを使っている部分をNativeなコードに直したり、型に関しては結構ゆるい作り(数値型っぽいところに突然エラーメッセージ配列を放り込む)になっていたので、その辺を微調整しました。

実行

以下のようにしてインポートして利用します。 プライベートキーは伏せてありますが、実際は正しいものを利用します。

import { Transactions } from "nem-services";

let common = {
  privateKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  password: ""
}
let dummyTransaction = {
  recipient: "NDLHY5KMQTATAR7IBRBF32MAQWDK7333VNI2MD5W",
  recipientPubKey: "099132a49ed0c15936a464cf6ef43120f01fa88835803593571882feea6161db",
  amount: 0,
  message: "sooooooooooooooooooooooooooooon",
  mosaics: null,
  fee: 12000000,
  innerFee: 0,
  due: 60,
  isMultisig: false,
  multisigAccount: ""
}

let tx = new Transactions();
let entity = tx.prepareTransfer(common, dummyTransaction, null);
tx.serializeAndAnnounceTransaction(entity, common)
  .subscribe(s => console.log(s));

以下のレスポンスが返ってきました。

{
  innerTransactionHash: Object,
  code: 1,
  type: 1,
  message: "SUCCESS",
  transactionHash: Object
}

そして無事トランザクションが取り込まれました。

http://chain.nem.ninja/#/transfer/aa530b1189fa5401101df71232fa0cf0f883a5d25364e552ea95d986a2c215c4


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

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