LoginSignup
14
5

More than 5 years have passed since last update.

文系プログラマがdAPPs開発ハンズオン with NEM(Catapult - Cowアップデート済)

Last updated at Posted at 2019-03-24

あいさつ

教育学部一年です。
東京の会社にリモートでインターンをしてます。

今回はその業務関連で勉強したことをまとめます。
多くのバグに衝突し、その対処法を逐次書くのでテンポは非常に悪いです。必要なところだけを適宜読み抜くようにしてください。

ほんと、バグがいっぱいで辛かった……

やること

NEMの公式チュートリアルの冒頭から、TypeScriptのサンプルコードを実行するところまでです。

環境(執筆時)

Windows 10
TypeScript Version 3.3.4000
Node.js v8.11.3
nem2-cli @0.11.0
nem2-sdk @0.11.1
npm @6.9.0
ts-node @8.0.3

環境設定

Node.jsはインストールしておいてください。

npm i npm
npm init
npm i -g nem2-cli nem2-sdk typescript rxjs js-joda ts-node utf8

アカウント作成

まず、NEMアカウントを作成します。
今回は会社の上司がオンラインでNodeを建ててくれたので、そちらを使います。
(通常はローカルで環境を作りそこでテストするのが王道のようです。)

>nem2-cli profile create

しかし、まずここからエラーに衝突します。幸先悪いですね。

Error1: アカウント作成エラー

Error Provide a valid NEM2 Node URL. Example: http://localhost:3000
エラーに記述があるとおりのURLや、Private KEYなど様々確認するのですが、どうやら違う様子。

解決

Profile stored correctly
default->
        Network:        MIJIN_TEST
        Url:            http://~
        Address:        SCJY~
        PublicKey:      63FD~
        PrivateKey:     783E~

端的に言って、これはいつの間にか解決していました。
しかし、エラーの原因をいろいろ探していた経験を鑑みると、ホームディレクトリに.nem2rc.jsonファイルが存在しなかったのが第一の原因のように思います。

同様のことにぶち当たった方は、ホームディレクトリに.nem2rc.jsonファイルを作成し、{}とだけ記入して保存してみてください。

話をチュートリアルに戻し、アカウント情報を取得してみます。

>nem2-cli account info

Account:        SCJY~
-------------------------------------------------------

Address:        SCJY~
at height:      1

PublicKey:      0000~
at height:      0

Importance:     0
at height:      0

Mosaics
650b00d30620b86a:       409090909

MosaicIDが650b~のモザイクがすでに付与されていますね。

ここで、チュートリアルを進めるため、別アカウントも作成しておきます。

>nem2-cli account generate --network MIJIN_TEST --save --url http://~ --profile buyer

New Account:    SAXS~
Public Key:     8CF5~
Private Key:    8BF8~

Stored buyer profile

Monitor類の作成

モニタリング用のコマンドプロンプトを3つ用意し、それぞれnem2-cli monitor status, nem2-cli monitor unconfirmed, nem2-cli monitor confirmedを実行しておきます。

最初のコマンドはエラーを表示してくれます。二番目のが「正常に予約された処理」。三番目のは「正常に終了した処理」を表示します。

モザイク作成

チュートリアル通りです。
すでにトークンが付与されていましたが、新しく作ってみます。

>nem2-cli transaction mosaic --amount 1000000 --supplymutable --divisibility 0 --duration 1000

Do you want mosaic to be transferable? [y/n]: n
Do you want mosaic to have levy mutable? [y/n]: y
Transaction announced correctly
Hash:    A2D3~
Signer:  63FD~
Your mosaic id is:
Hex:  10a5abae76de8603
Uint64: [ 1994294787 279292846]

モザイク送信

これもチュートリアル通り。
最初に登録したdefaultアカウントから、buyerアカウントへモザイクを送信しています。

まずは、もともと作ってあったモザイクの方から。

>nem2-cli transaction transfer --recipient SAXS~ --mosaics @cat.currency::10 --message "Hello NEM" --profile default

Transaction announced correctly
Hash:    969E65EBFF15827A34B2C949D9AC6F7299A62DA04F372FB272952A6DA8AAD0BE
Signer:  63FD~

buyerアカウント情報を取得してみましょう。

>nem2-cli account info --profile buyer

Account:        SAXS~
-------------------------------------------------------

Address:        SAXS~
at height:      16561

PublicKey:      0000~
at height:      0

Importance:     0
at height:      0

Mosaics
650b00d30620b86a:       0.00001

モザイクは正常に送信されていますね。

作った方のモザイクも送信してみます。

>nem2-cli transaction transfer --recipient SAXS~ --mosaics 10a5abae76de8603::10 --message "Hello buyer" --profile default

Transaction announced correctly
Hash:    B830~
Signer:  63FD~

同じく、defaultアカウントからbuyerアカウントへの送信です。
アカウント情報を確認してみます。

>nem2-cli account info --profile buyer

Account:        SAXS~
-------------------------------------------------------

Address:        SAXS~
at height:      16561

PublicKey:      0000~
at height:      0

Importance:     0
at height:      0

Mosaics
10a5abae76de8603:       10
650b00d30620b86a:       0.00001

650b~以外のモザイクが取得できていますね!

TypeScriptサンプルコードの実行

さて、ここからがひどい泥沼だったのですが……
まず、NEMアプリを記述したTSコードを実行するには、Node.js上で実行する必要があります。
手段は二通り。

  1. ~.tsファイルを直接ts-nodeコマンドで実行
  2. ~.tsファイルを~.jsファイルにコンパイルし、nodeコマンドで実行

結論から言うと、1は断念し、2はうまくいきました。

こちらがソースコード。

test.ts
import {
    Account, Address, Deadline, UInt64, NetworkType, PlainMessage, TransferTransaction, Mosaic, MosaicId,
    TransactionHttp
} from 'nem2-sdk';

const transferTransaction = TransferTransaction.create(
    Deadline.create(),
    Address.createFromRawAddress('SC7A~'),
    [new Mosaic(new MosaicId([ 1994294787, 279292846 ]), UInt64.fromUint(1))], // Replace with your mosaicId
    PlainMessage.create('enjoy your ticket'),
    NetworkType.MIJIN_TEST
);

const privateKey = process.env.PRIVATE_KEY;

const account = Account.createFromPrivateKey(privateKey, NetworkType.MIJIN_TEST);

const signedTransaction = account.sign(transferTransaction);

const transactionHttp = new TransactionHttp('http://~');

transactionHttp.announce(signedTransaction).subscribe(
    x => console.log(x),
    err => console.log(err)
);

チュートリアルサイトのコードを貼り合わせてMosaicIDとかを変更しただけですね。

実行前に、環境変数にPRIVATE_KEYを登録しておくのもお忘れなく。

では方針1「ts-nodeで直接実行」を試してみます。

>ts-node ./~/test.ts

C:\~\index.ts:226
    return new TSError(diagnosticText, diagnosticCodes)
           ^
TSError: ⨯ Unable to compile TypeScript:
~/test.ts:4:8 - error TS2307: Cannot find module 'nem2-sdk'.

4 } from 'nem2-sdk';
         ~~~~~~~~~~
~/test.ts:14:20 - error TS2580: Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.

14 const privateKey = process.env.PRIVATE_KEY;
                      ~~~~~~~

    at createTSError (C:~\index.ts:226:12)
    at getOutput (C:~\index.ts:335:40)
    at Object.compile (C:~\index.ts:368:11)
    at Module.m._compile (C:~\index.ts:414:43)
    at Module._extensions..js (module.js:663:10)
    at Object.require.extensions.(anonymous function) [as .ts] (C:~\index.ts:417:12)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)

だめみたいですね。
じゃあ方針2「一度コンパイルしてから実行」も試してみます。

>tsc ./~/test.ts

~/MultisigAccountGraphInfo.d.ts(8,48): error TS2583: Cannot find name 'Map'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.
~/Observable.d.ts(89,59): error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.
~/types.d.ts(41,84): error TS2304: Cannot find name 'Iterable'.
~/types.d.ts(45,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.
C:~\index.ts(14,20): error TS2580: Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i @types/node` and then add `node` to the types field in your tsconfig.

あらら……

Error2: TSファイルが実行できない

エラーコード通りにtsconfigを設定するも解決せず。
まぁエラーの一部は.tsファイルの存在するディレクトリでnpm i nem2-sdkやってなかったとかいう超初歩的なものだったのですが…笑

tsconfig設定とかをいろいろ調べ回った挙げ句、原因は「型定義ファイルがインストールされていない」、「管理者権限でないとコンパイラが環境変数を読みにいけない」ということでした。

解決

TSファイルのあるディレクトリでnpm i nem2-sdk @types/core-js @types/nodeを実行します。
次に、管理者モードでコマンドプロンプトを開き、tscコマンドでTSファイルをコンパイル。
そうしたら、非管理者モードのコマンドプロンプトに戻ってnode ~.tsを実行。

管理者モードではPOSTメソッドが許可されていないらしいので、実行そのものは非管理者モードでないといけないようです。(おそらく、ts-nodeがうまくいかないのはこのため……)

>node ./~/test.js

TransactionAnnounceResponse {
  message: 'packet 9 was pushed to the network via /transaction' }

以上、TSサンプルコードの実行は見事達成できました。

終わりに

以下蛇足ですが感想など。

前半からエラー(しかも環境依存ぽい)に苦しまされ続けたので、非常に疲れました。右も左もわからない中でもがくハメになり、NEMコミュニティの皆様の助言の数々は(直接の解決には至らずとも)貴重なマイルストーンとなり、とても感謝しています。
ともかくも良い勉強になりましたね。またできることが一つ増えた。

次回からはNEMの新機能などに深く突っ込んだ記事を書いていく所存です。

最後になりましたが、いろいろご指導くださった @daoka さんに感謝申し上げます。これからも頑張っていきます。

14
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
5