SlackなどのSNSからユニークなNEMアカウントを生成する

今回でTipSLACK解剖最終編となります。

前回まで、XEMやlc:jpyなどに使用されているmosaicの送金方法をお伝えしました。
nem-libraryを利用すればほんの数行でできることがわかりましたね。
あとは送金するアカウントを準備すれば送金システムが完成となります。

[amazon linuxでNode.jsのNEM開発環境を爆速で整える](https://qiita.com/nem_takanobu/items/39231820416a8a58b99a)
[nem-libraryを利用してJavaScriptでXEM送金する](https://qiita.com/nem_takanobu/items/20f9dc7bbae2d730cb96)
[nem-libraryを利用してJavaScriptでlc:jpyを送金する](https://qiita.com/nem_takanobu/items/7d8480478d1bf3f46b54)

SlackなどのSNSで暗号通貨の送金を行う場合、SNSアカウントに紐づいたNEMアドレスを準備する必要があります。それぞれがユニークであり、他者によって生成不可能な形式にしておかなければいけません。また、ユニークなアドレスを準備せず、送金時のメッセージIDなどで単一アドレスないで口座振り分けを行う方法もあります。tipnemなどのtipbotは後者で運用されている場合が多いですね。しかしながら独自にDBを準備しておく必要があるなど、運用については若干の専門的知識を要する場合もあります。

それでは、実際のソースコードを見てみましょう。

```node.js

const SYSTEM_PRIVATE_KEY = "aaaa bbbb cccc dddd eeee ffff gggg hhhh iiii jjjj kkkk llll mmmm nnnn oooo pppp";  //sample
const SLACK_HOOK_URL = "https://hooks.slack.com/services/XXXXXXXXX/YYYYYYYYY/ZZZZZZZZZZZZZZZZZZZZZZZZ";
const SLACK_TOKEN = "XXXXXXXXXXXXXXXXXXXXXXX";

const express    = require('express');
const bodyParser = require('body-parser');
const request  = require("request");
var app = express();
app.use(log4js.connectLogger(logger));
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());

app.listen(1337);

//API
app.post('/tipslack', (req, res) => {

	if(req.body.token != SLACK_TOKEN){
		logger.info('invalid token:' + req.body.token);
		return false;
	}

	let text = req.body.text.match(/([\w]+)(@)*([\w\.-]+)*( +)*([0-9]+)*( +)*(\w+)*( +)*(.+)*/)
	let command = req.body.text.match(/^([a-zA-Z][\w-]*)(\s.*)?$/);

	if (command[1] == "deposit"){
		deposit(res,req.body.user_name);
	}
});

//実行結果アナウンス
function announce(message){

	var payload= {"text":message }	;
	payload = JSON.stringify(payload);

	request.post({
		url: SLACK_HOOK_URL,
		headers: {"content-type": "application/json"},
		body: payload
	}, function (error, response, body){

	});
}

//コマンド受付メッセージ
function reply(res,message){

	let data = {
	 	response_type: 'in_channel',
	 	text: message,
	};
	res.header('Content-Type', 'application/json; charset=utf-8')
	res.send(data);
}

//入金アドレス照会
function deposit(res,user_name){

	reply(res, "<@" +user_name + "> さんのTipSLACKアドレス照会中です。");
	const brainPassword =  new BrainPassword(SYSTEM_PRIVATE_KEY + user_name)
	const brainWallet = BrainWallet.create("TipSLACK", brainPassword);
	announce( "<@" +user_name + "> さんのTipSLACKアドレス:" + brainWallet.address.pretty());
}

```

Slack にて　/command deposit と打ち込むと自分のアカウントに割り振られたNEMアドレスを返信するプログラムです。
このNode.jsプログラムを実行するためにはSlack側の設定が少し必要です。
App管理->カスタムインテグレーションから Slack commandsと着信Webフックの登録を行ってください。

- Slack commands
    - command
        - /tipslack
    - URL
        - http://ipaddress:1337/tipslack
    - トークン
        - この部分に表示された文字列をプログラム上のSLACK_TOKENに記入

- 着信Webフック
    - Webhook URL
        - この部分に表示された文字列をSLACK_HOOK_URLに記入


もう一つ独自パラメータが必要になります。システム秘密鍵と呼んでいますが、運用者が他者に漏らさず設定しておくパスワードになります。これが漏れると全てのNEMアドレスが他者でも生成可能になりますのでご注意ください。秘密鍵とは言いましたがnem-libraryの仕様上スペース混じりの12個以上の単語という制限があるので今回は秘密鍵を4文字単位で分解しスペースを組み合わせています。（SYSTEM_PRIVATE_KEY）

さあ、これで準備完了です。Node.jsを実行してサーバを起動するとSlackからのコマンドを受け付けるようになります。

```
/tipslack deposit
```

このように入力された文字列は

```js
app.post('/tipslack', (req, res) 
```


にて受け付けられます。正規表現でコマンドとオプション引数が分離され、
コマンド名がdepositだった場合に

```js
function deposit(res,user_name){
```

が呼び出されます。ここではリクエスト受け付けメソッドから始まり、処理結果告知メソッドで終わる形式で記述されています。

```js
reply(res, "<@" +user_name + "> さんのTipSLACKアドレス照会中です。");
... 
announce( "<@" +user_name + "> さんのTipSLACKアドレス:" + brainWallet.address.pretty());
```

この間でSlackで使われるNEアカウントの生成処理を記述します。
といっても、nem-libraryを利用すればたったの２行で作れます。
今回利用するのはBrainWalletです。

「え？ブレインウォレットって危険なやつじゃなかった？大丈夫？」

そうです、BrainWalletはパスワードから秘密鍵を生成する仕様なので、暗号通貨をよく知らない人が安易に使用するのは大変危険なウォレットです。そのためNanoWalletでも廃止になりました。nem-libaryでも12語以上の単語を指定しないと作れないように制限がかかっています。ただし、その危険性さえ把握していれば大変有用な仕組みです。ランダム値を
生成するときのシード値のようにSlackのアカウント情報を放り込めばそのアカウント毎にユニークなウォレットが作成できます。もちろん他の人には作れないように運用者が独自に指定したパスワードを織り交ぜておく必要があります。

具体的には以下のようにしてウォレットが作成できます。作成できれば秘密鍵もアドレスも任意に出力可能です。

```js
const brainPassword =  new BrainPassword(SYSTEM_PRIVATE_KEY + user_name)
const brainWallet = BrainWallet.create("TipSLACK", brainPassword);
```

このようにして、Slackアカウント毎にユニークなNEMアカウントの生成することができました。

これで今回のTipSlack解剖講座を終えたいと思います。
それにしてもSNSと連携させることで暗号通貨が使えるのは便利ですね。これからもいろいろ試してみたいと思います。