Monacoinオンラインウォレットを作ってみよう

[アイスタイル Advent Calendar 2017](https://qiita.com/advent-calendar/2017/istyle)、10日目の記事です。

みなさん、仮想通貨持ってますか？
仮想通貨の中でも[Monacoin（モナーコイン）](https://monacoin.org/)は日本初のもので、1MONA=1600円近くで取引されています。（2017年12/11月現在）

この記事ではMonacoinのオンラインウォレットを作成してみます。

## 環境
OS: Ubuntu 14.04.5 LTS (vagrantのゲストOSとして使用しました)
monacoin: v0.14.2

## monacoin インストール
```
sudo add-apt-repository -y ppa:visvirial/monacoin
sudo apt update -y
sudo apt install -y monacoind
```
インストールが完了すると`~/.monacoin`が作成され、以下のコマンドが有効になります。

```
$ which monacoind
/usr/bin/monacoind

$ which monacoin-cli
/usr/bin/monacoin-cli
```

monacoinの起動には`monacoind`コマンドを、アドレスの作成や送金といったコマンドは`monacoin-cli`を使って操作していくことになります。


## 設定ファイルの作成
`~/.monacoin/monacoin.conf` を作成します。以下はサンプルです。

```
# 1にすることでJSON-RPC APIが叩けるようになる
server=1

# デーモンとして起動
daemon=1

# RPCユーザ・ポート設定（適宜変更してください）
rpcuser=username
rpcpassword=password
rpcport=9332

# RPC接続許可設定（ローカルのみ）
rpcallowip=127.0.0.1/24
# 全許可
# rpcallowip=0.0.0.0/0

# マイニングするか（今回はウォレット機能のみ使うので0）
gen=0

# testnet設定
testnet=4
```

## testnetについて
testnetとは開発のためのBlockchainネットワークです。
testnet内の仮想通貨には価値がなく、ネット上で無料で手に入れることが可能です。仮想通貨を利用したアプリケーションを開発する際はtestnetを利用するのが普通です。
[リリースノート](https://github.com/monacoinproject/monacoin/blob/master-0.14/doc/release-notes-monacoin.md)を見ると

>Testnet3 has been deprecated and replaced with Testnet4. The server port has been changed to 19403 however the RPC port remains the same (19402).

とあるので、4を指定します。

## monacoind起動
それでは起動してみましょう。

```
$ monacoind
Monacoin server starting
```

これだけでOKです。
正常に起動されているか確認してみましょう。

```
$ monacoin-cli getinfo
{
  "version": 140200,
  "protocolversion": 70015,
  "walletversion": 130000,
  "balance": 0.00000000,
  "blocks": 256,
  "timeoffset": 0,
  "connections": 1,
  "proxy": "",
  "difficulty": 0.0009979965449690071,
  "testnet": true,
  "keypoololdest": 1512289024,
  "keypoolsize": 100,
  "paytxfee": 0.00000000,
  "relayfee": 0.00100000,
  "errors": ""
}
```

ちゃんとtestnetが有効になっていますね。
実際に取引を開始するにはBlockchainネットワークに存在するブロックを全て入手する必要があります。

>  "blocks": 256,

このブロック数は起動直後だと少ないかもしれませんが、testnetなら数分で安定します。

## monacoin-cliについて
monacoinに関する様々な操作を行うことができる`monacoin-cli`ですが、コマンドの種類はbitcoinと同様なので
こちらのコマンドリストを参照すると良いでしょう。
[https://en.bitcoin.it/wiki/Original_Bitcoin_client/API_calls_list](https://en.bitcoin.it/wiki/Original_Bitcoin_client/API_calls_list)

## 新規アドレスを発行する
`getnewaddress <account>` で、アカウント名を指定してアドレスを新規作成できます。

```
$ monacoin-cli getnewaddress alice
mvoKjf93xPmqgaUPe3jiCvR9AAbuetWjiu
```

指定したアカウント名が存在しなければ作成されます。
一つのアカウントに複数のアカウントを作成することも可能です。`alice` にもうひとつアドレスを作成してみましょう。

```
$ monacoin-cli getnewaddress alice
migTzrD7Ac78nQ148HD5jFNf5T2cqu7T2h
```

これで、`mvoKjf93xPmqgaUPe3jiCvR9AAbuetWjiu` と `migTzrD7Ac78nQ148HD5jFNf5T2cqu7T2h` の2つのアドレスが`alice`アカウントに作成されました。
Monacoinのアドレスは`M`から始まりますが、testnetの場合は`m`から始まります。

## アカウント一覧を確認する

```
$ monacoin-cli listaccounts
{
  "": 0.00000000,
  "alice": 0.00000000
}
```

`alice`のみ確認できます。数字はそのアカウントに紐づくアドレスの残高の合計を示しています。

## アカウントを指定して残高を確認する

```
$ monacoin-cli getbalance alice
0.00000000
```

## アカウントに紐づくアドレスを確認する

```
$ monacoin-cli getaddressesbyaccount alice
[
  "migTzrD7Ac78nQ148HD5jFNf5T2cqu7T2h",
  "mvoKjf93xPmqgaUPe3jiCvR9AAbuetWjiu"
]
```

先程作成したアドレス2つが確認できます。

## testnet用のコインを入手する
今回はtestnet4用のFaucetを提供している[こちらのサイト](https://monacoin-testnet-faucet.torifuku-kaiou.tokyo/)を利用します。
ちゃんとバナークリックしてあげましょうね。
「Address」欄に先ほど作成したアドレスのうちのひとつを入力し、「Send」ボタンを押します。

<img width="1190" alt="スクリーンショット 2017-12-03 17.45.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/6287/f58bef6a-095a-1644-111e-a3470265da8c.png">


合計`127.88 MONA`が送金されたようです。
トランザクションがBlockchainネットワークにより承認され、自分のアカウントに反映されるには時間がかかる場合もありますが、testnetなら数分で反映されるはずです。

## 残高を確認する
```
$ monacoin-cli getbalance alice
127.88000000
```
ちゃんと反映されてますね！

## 送金する
先に送金先のアカウント`bob`を作っておきましょう。

```
$ monacoin-cli getnewaddress bob
mxzLyPYfXYc2RePDqYF43xKgAQcJBzvqjC
```

これで、このウォレット内には`alice`と`bob`の2アカウントが存在することになります。

```
$ monacoin-cli listaccounts
{
  "": 0.00000000,
  "alice": 127.88000000,
  "bob": 0.00000000
}
```

`alice`から`bob`に`7.88 MONA`だけ送金してみます。
同一ウォレットの場合`move`コマンドが使えます。
同一ウォレット内でのMONAを移動させるだけなので、手数料は不要です。

`move`コマンドの引数は以下になります。

```
move <送金元アカウント> <送金先アカウント> <送金額> [最低承認数=1] [コメント]
```

それでは送金します。

```
$ monacoin-cli move alice bob 7.88
true
```

アカウント毎の残高を確認しましょう。

```
$ monacoin-cli listaccounts
{
  "": 0.00000000,
  "alice": 120.00000000,
  "bob": 7.88000000
}
```

想定した通りの結果になりましたね。
今回は触れませんが、別のウォレットのアドレスを指定して送金するには `sendfrom`コマンドを使います。

## curlから叩いてみる
monacoinはJSON-RPCを提供しているため、HTTPリクエストすることでリモートからの操作が容易に可能です。
先程の`move`操作をcurlでやってみます。
`alice`から`bob`へ`1 MONA`移動させましょう。

```
$ curl -s --data-binary '{"jsonrpc":"1.0","id":"curltext","method":"move","params":["alice","bob","1"]}' -H 'content-type:text/plain;' http://username:password@127.0.0.1:9332
```

以下のようなJSONが返ってくればOKです。

```
{
  "id": "curltext",
  "error": null,
  "result": true
}
```

アカウント毎の残高を確認してみましょう。

```
$ curl -s --data-binary '{"jsonrpc":"1.0","id":"curltext","method":"listaccounts","params":[]}' -H 'content-type:text/plain;' http://username:password@127.0.0.1:9332 | jq .
{
  "id": "curltext",
  "error": null,
  "result": {
    "bob": 8.88,
    "alice": 119,
    "": 0
  }
}
```
うまくいってるようです。
今回はローカルにたてたmonacoinウォレットに対してリクエストしましたが、`monacoin.conf`の`rpcallowip`で許可するIPを適切に指定してあげれば、リモートから叩くことも可能です。

## monacoindを停止する
最後に、停止する方法です。

```
$ monacoin-cli stop
Monacoin server stopping
```

## まとめ
今回はMonacoinでしたが、Bitcoinや、Bitcoinを元にしたLitecoin系の仮想通貨はほとんど似たような操作でオンラインウォレットを立ち上げることが可能なはずです。
JSON-RPCでやり取りできるためアプリケーションにも組み込みやすいのではないかと思います。