ブロックチェーンでリモート承認してみる（２）


今回は申請者と承認者でタブを分けて実運用に近い形で検討してみます。
また、リスナーやフィルターを利用して自動承認なども実装してみましょう。

前回の記事をまだ読んでいない方は[こちら](https://qiita.com/nem_takanobu/items/78eb872a80db8c88f4ef)から先にお読みください。

[ブロックチェーンでリモート承認を導入してみる](https://qiita.com/nem_takanobu/items/78eb872a80db8c88f4ef)


### 事前準備（申請者、承認者両方で実行）

申請者をAlice、承認者をBobとします。
chromeブラウザで申請者タブと承認者タブの2つを開いてください。双方ともにF12キーあるいは fn+F12キーを押してデベロッパーツールを起動しておきます。

まずはライブラリの読み込みます。

```js:alice,bob
(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クラスも生成しておきます。

```js:alice,bob
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()を実行してブロック生成ごとに通信が走るように設定しておきましょう。


### 申請者アカウントの作成と準備

アカウントの作成と蛇口からの入金、残高確認を申請者タブで実行します。

```js:alice

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]));
```

コンソールに申請者のアドレスと蛇口サイトのリンクが出力されます。

### 承認者アカウントの作成と準備

アカウントの作成と蛇口からの入金、残高確認を承認者タブで実行します。

```js:bob

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からのトランザクションを発見次第、自動承認する動きにしてみます。


```js:bob

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機能を使います。

### 承認確認

最後に承認者から承認された場合の確認をあらかじめ記述しておきます。

```js:alice

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)
});

```

### 申請
それでは申請を行ってみましょう。

```js:alice

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エンジンの真骨頂となる機能満載でのリモート承認にチャレンジです！お楽しみに。