今回は申請者と承認者でタブを分けて実運用に近い形で検討してみます。
また、リスナーやフィルターを利用して自動承認なども実装してみましょう。
前回の記事をまだ読んでいない方はこちらから先にお読みください。
事前準備(申請者、承認者両方で実行)
申請者をAlice、承認者をBobとします。
chromeブラウザで申請者タブと承認者タブの2つを開いてください。双方ともにF12キーあるいは fn+F12キーを押してデベロッパーツールを起動しておきます。
まずはライブラリの読み込みます。
(script = document.createElement('script')).src = 'https://xembook.github.io/nem2-browserify/symbol-sdk-pack-0.21.0.js';
document.getElementsByTagName('head')[0].appendChild(script);
次に、使用するモジュールのインポートです。前回のsymbol-sdkに加えて今回はrxjsのoperatorsを使用します。Websocketでブロックチェーンをリアルタイムに監視しますので、Listenerクラスも生成しておきます。
nem = require("/node_modules/symbol-sdk");
op = require("/node_modules/rxjs/operators");
NODE = "https://sym-test.opening-line.jp:3001";
GENERATION_HASH = "6C1B92391CCB41C96478471C2634C111D9E989DECD66130C0430B5B8D20117CD";
txHttp = new nem.TransactionHttp(NODE);
accountHttp = new nem.AccountHttp(NODE);
wsEndpoint = NODE.replace('http', 'ws');
listener = new nem.Listener(wsEndpoint, WebSocket);
listener.open().then(() => {
listener.newBlock();
});
websocketのエンドポイントはhttp
をws
に置き換えたものになります。
listenerは何も通信することが無いと1分ほどで切断されてしまいます。
newBlock()を実行してブロック生成ごとに通信が走るように設定しておきましょう。
申請者アカウントの作成と準備
アカウントの作成と蛇口からの入金、残高確認を申請者タブで実行します。
alice = nem.Account.generateNewAccount(nem.NetworkType.TEST_NET);
console.log(alice.address.plain());
"http://faucet-0.10.0.x-01.symboldev.network/?recipient=" + alice.address.address +"&amount=10"
//15秒後ぐらいに確認
accountHttp.getAccountInfo(alice.address).subscribe(x=>console.log(x.mosaics[0]));
コンソールに申請者のアドレスと蛇口サイトのリンクが出力されます。
承認者アカウントの作成と準備
アカウントの作成と蛇口からの入金、残高確認を承認者タブで実行します。
bob = nem.Account.generateNewAccount(nem.NetworkType.TEST_NET);
console.log(bob.address.plain());
"http://faucet-0.10.0.x-01.symboldev.network/?recipient=" + bob.address.address +"&amount=10"
//15秒後ぐらいに確認
accountHttp.getAccountInfo(bob.address).subscribe(x=>console.log(x.mosaics[0]));
コンソールに申請者のアドレスと蛇口サイトのリンクが出力されます。
承認時のふるまい
次に、申請が来た時の承認者のふるまいをあらかじめ記述しておきます。
本来ならファイルハッシュの確認してから承認ですが、今回は申請者Aliceからのトランザクションを発見次第、自動承認する動きにしてみます。
aliceAddress = nem.Address.createFromRawAddress("{Aliceのアドレス}");
listener.confirmed(bob.address)
.pipe(
op.filter((x) => x.signer.address.plain() === aliceAddress.plain()),
)
.subscribe(x=>{
console.log(x);
tx = nem.TransferTransaction.create(
nem.Deadline.create(),
aliceAddress,
[],
nem.PlainMessage.create('approved:' + x.transactionInfo.hash),
nem.NetworkType.TEST_NET,
nem.UInt64.fromUint(100000)
);
signedTx = bob.sign(tx,GENERATION_HASH);
txHttp.announce(signedTx).subscribe(_ => console.log(_), err => console.error(err));
console.log("https://sym-test.opening-line.jp:3001/transactionStatus/" + signedTx.hash )
});
Aliceタブで出力されたAliceのアドレスを使ってAddressクラスを生成します。Bob宛のトランザクションを受信した場合に、署名者がAliceだった場合"Approved:{受信トランザクションのhash値}"をメッセージにして承認トランザクションを発生させます。
pipe 内部で rxjs.operators の filter機能を使います。
承認確認
最後に承認者から承認された場合の確認をあらかじめ記述しておきます。
bobAddress = nem.Address.createFromRawAddress("{Bobのアドレス}");
listener.confirmed(alice.address)
.pipe(
op.filter((x) => x.signer.address.plain() === bobAddress.plain()),
)
.subscribe(x=>{
console.log("承認されました");
console.log("https://sym-test.opening-line.jp:3001/transactionStatus/" + x.transactionInfo.hash)
});
申請
それでは申請を行ってみましょう。
tx = nem.TransferTransaction.create(
nem.Deadline.create(),
bobAddress,
[],
nem.PlainMessage.create('b7d3e3191d2d2e77ed6e455eeaec147c13e19f0c079f0ca0dcff853f3df46911'),
nem.NetworkType.TEST_NET,
nem.UInt64.fromUint(100000)
);
signedTx = alice.sign(tx,GENERATION_HASH);
txHttp.announce(signedTx).subscribe(_ => console.log(_), err => console.error(err));
"https://sym-test.opening-line.jp:3001/transactionStatus/" + signedTx.hash
事前にHash生成器で作成したファイルハッシュ b7d3e3191d2d2e77ed6e455eeaec147c13e19f0c079f0ca0dcff853f3df46911
をメッセージに指定して承認者へ送信します。トランザクションがconfirmedになると、承認者(Bob)タブの承認トランザクションが走ります。さらに承認トランザクションがconfirmedになった時点で申請者(Alice)タブにて"承認されました"と表示されます。
ぜひお試しください。
次回はNEM Catapultエンジンの真骨頂となる機能満載でのリモート承認にチャレンジです!お楽しみに。