【2019年3月版】LoomSDKのサンプルを動かしてみる

# はじめに
@kane-hiro 氏が [LoomSDKのTruffle DAppチェーンサンプルを動かしてみる](https://qiita.com/kane-hiro/items/47436f81beb147d3a134) の記事でうまくいかなかったLoomSDKのサンプルですが、この数日前に自分の似たような環境(macOS High Sierra)ではできていたのでその時のログを貼り付けておきます。
Truffleに行く前に寝落ちしているのでスマートコントラクトでのトークンの交換のチュートリアルの手順だけです。すいません。。。

# 環境

OS: macOS High Sierra (10.13.6)
node: v11.10.1
yarn: v1.13.0
npm: v6.7.0

# loomのインストールと起動
まず、こちらのページの手順の通りにインストールを行います。
https://loomx.io/developers/docs/en/basic-install-all.html

```shell
$ curl https://raw.githubusercontent.com/loomnetwork/loom-sdk-documentation/master/scripts/get_loom.sh | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   615  100   615    0     0   1713      0 --:--:-- --:--:-- --:--:--  1717
Downloading loom executable...
2.0.0+b789
All done.
```
バイナリが問題ないか確かめてみます。

```shell
$ ./loom 
Loom DAppChain

Usage:
  loom [command]

Available Commands:
  call              call a contract method
  callevm           Call am evm contract
  db                Database Maintenance
  deploy            Deploy a contract
  deploy-go         Deploy a go contract from json file
  dpos              call a method of the dpos contract
  env               Show loom config settings
  gateway           Transfer Gateway Administration
  genkey            generate a public and private key pair
  getblocksbynumber gets info for block or range of blocks number
  help              Help about any command
  init              Initialize configs and data
  karma             call a method of the karma contract
  nodekey           Show node key
  reset             Reset the app and blockchain state only
  resolve           call a method of the resolve contract
  run               Run the blockchain node
  spin              Spin a loom project from a github repository
  static-call-evm   Calls a read-only method on an EVM contract
  unsafe            call a method of the unsafe contract
  validators        call a method of the validators contract
  version           Show the Loom chain version
  yubihsm           generate or load YubiHSM ed25519/secp256k1 key

Flags:
  -h, --help   help for loom

Use "loom [command] --help" for more information about a command.
```
ヘルプが表示されました。ちゃんとバイナリしてるようです。

別ターミナルでこれを立ち上げておきます。

```shell
$ ./loom init
$ ./loom run
I[8036-03-08|00:45:12.816] Loading IAVL Store                           module=loom 
I[8036-03-08|00:45:12.835] Using simple log event dispatcher            
I[8036-03-08|00:45:12.891] Deployed contract                            vm=plugin location=coin:1.0.0 name=coin address=default:0xe288d6eec7150D6a22FDE33F0AA2d81E06591C4d
Init DPOS Params &dpos.DPOSInitRequest{Params:(*dpos.Params)(0xc000155180), Validators:[]*types.Validator{(*types.Validator)(0xc0001cd640)}, XXX_NoUnkeyedLiteral:struct {}{}, XXX_unrecognized:[]uint8(nil), XXX_sizecache:0}
I[8036-03-08|00:45:12.894] Deployed contract                            vm=plugin location=dpos:1.0.0 name=dpos address=default:0x01D10029c253fA02D76188b84b5846ab3D19510D
E[8036-03-08|00:45:12.927] Couldn't connect to any seeds                module=p2p 
I[8036-03-08|00:45:12.929] Starting RPC HTTP server on [::]:46658       module=query-server 
I[8036-03-08|00:45:12.929] Starting RPC HTTP server on 127.0.0.1:9999   module=query-server 
E[8036-03-08|00:45:42.929] Couldn't connect to any seeds                module=...
```
 
# サンプルプロジェクトを動かしてみる

## ダウンロード

続いてこちらのページを参考にサンプルプロジェクトのダウンロードを行います。
https://loomx.io/developers/docs/en/join-testnet.html

loomの取得はできているのでキーペアを生成します。

```shell
$ ./loom genkey -k priv_key -a pub_key
local address: 0xd027FfC9421E69c056af70fC6674831B2F42a528
local address base64: 0Cf/yUIeacBWr3D8ZnSDGy9CpSg=
```
続いて [PlasmaChain Testnets
](https://loomx.io/developers/docs/en/testnet-plasma.html)のページでテストネットのURL確認してね〜ってことなのでお好みのテストネットを確認しておきます。
以下はデフォルトの"extdev-plasma-us1.dappchains.com"に接続する手順で行きます。

さて、手順に従ってソースコードの取得とプライベートキーのコピーをします。

```shell
$ git clone https://github.com/loomnetwork/truffle-dappchain-example
Cloning into 'truffle-dappchain-example'...
remote: Enumerating objects: 30, done.
remote: Counting objects: 100% (30/30), done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 363 (delta 12), reused 22 (delta 8), pack-reused 333
Receiving objects: 100% (363/363), 471.02 KiB | 789.00 KiB/s, done.
Resolving deltas: 100% (198/198), done.
$ cd truffle-dappchain-example
$ cp ../priv_key extdev_private_key
```
## 依存関係のインストール
yarnコマンドで必要なライブラリをインストールします。

```shell
$ yarn
yarn install v1.13.0
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning " > request-promise@4.2.2" has unmet peer dependency "request@^2.34".
warning "request-promise > request-promise-core@1.1.1" has unmet peer dependency "request@^2.34".
[4/4] 🔨  Building fresh packages...
✨  Done in 181.28s.
```

## テストネットへのデプロイ

yarnでテストネットへデプロイします。

```shell
$ yarn deploy:extdev
yarn run v1.13.0
 \$ truffle deploy --network extdev_plasma_us1
Compiling ./contracts/Migrations.sol...
Compiling ./contracts/MyCoin.sol...
Compiling ./contracts/MyRinkebyCoin.sol...
Compiling ./contracts/MyRinkebyToken.sol...
Compiling ./contracts/MyToken.sol...
Compiling ./contracts/SimpleStore.sol...
Compiling openzeppelin-solidity/contracts/AddressUtils.sol...
Compiling openzeppelin-solidity/contracts/introspection/ERC165.sol...
Compiling openzeppelin-solidity/contracts/introspection/SupportsInterfaceWithLookup.sol...
Compiling openzeppelin-solidity/contracts/math/SafeMath.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/BasicToken.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol...
Compiling openzeppelin-solidity/contracts/token/ERC721/ERC721.sol...
Compiling openzeppelin-solidity/contracts/token/ERC721/ERC721Basic.sol...
Compiling openzeppelin-solidity/contracts/token/ERC721/ERC721BasicToken.sol...
Compiling openzeppelin-solidity/contracts/token/ERC721/ERC721Receiver.sol...
Compiling openzeppelin-solidity/contracts/token/ERC721/ERC721Token.sol...
Writing artifacts to ./src/contracts

⚠️  Important ⚠️
If you\'re using an HDWalletProvider, it must be Web3 1.0 enabled or your migration will hang.


Starting migrations...
======================
> Network name:    'extdev_plasma_us1'
> Network id:      9545242630824
> Block gas limit: 0


1_initial_migration.js
======================

   Deploying 'Migrations'
   ----------------------
   > transaction hash:    0x07ce0d5467a1ba1dee6e95b13680dc02d2e3fd93800c6c638cf1c3028a83d5f3
   > Blocks: 3            Seconds: 4
   > contract address:    0x7012De096B2dA247D0C0faCb54Ee8D3Eda17ca07
   > account:             0xD027fFC9421E69c056aF70Fc6674831B2F42a528
   > balance:             0
   > gas used:            0
   > gas price:           0 gwei
   > value sent:          0 ETH
   > total cost:          0 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:                   0 ETH


2_simple_store.js
=================

   Deploying 'SimpleStore'
   -----------------------
   > transaction hash:    0x181e23823a5c374c67e1aed4b0dd54ebfc7898968478ce765b6448c8e38262f6
   > Blocks: 0            Seconds: 0
   > contract address:    0x19Bd541C1779c7D389B0ADbF8535F233d6036b11
   > account:             0xD027fFC9421E69c056aF70Fc6674831B2F42a528
   > balance:             0
   > gas used:            0
   > gas price:           0 gwei
   > value sent:          0 ETH
   > total cost:          0 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:                   0 ETH


3_token_contracts.js
====================

   Deploying 'MyToken'
   -------------------
   > transaction hash:    0xeb9b9184ce366a7466b09185eee435467d331607354c59f2105c0c3652acbdc4
   > Blocks: 0            Seconds: 0
   > contract address:    0x4BB900a33E84aDf5933d983C9C17EeFAfC012334
   > account:             0xD027fFC9421E69c056aF70Fc6674831B2F42a528
   > balance:             0
   > gas used:            0
   > gas price:           0 gwei
   > value sent:          0 ETH
   > total cost:          0 ETH


   Deploying 'MyCoin'
   ------------------
   > transaction hash:    0x92ac16c07b0d1bb2263c81b8b433d6947da6a7177b7cc32f05e93d114721c9d3
   > Blocks: 9            Seconds: 4
   > contract address:    0xA6Eac7d5f61ec8199eEF09fDa4F8CEd0B4c2EC3A
   > account:             0xD027fFC9421E69c056aF70Fc6674831B2F42a528
   > balance:             0
   > gas used:            0
   > gas price:           0 gwei
   > value sent:          0 ETH
   > total cost:          0 ETH


*************************************************************************

MyToken Contract Address: 0x4BB900a33E84aDf5933d983C9C17EeFAfC012334
MyCoin Contract Address: 0xA6Eac7d5f61ec8199eEF09fDa4F8CEd0B4c2EC3A

*************************************************************************


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:                   0 ETH


4_rinkeby_contracts.js
======================

   > Saving migration to chain.
   -------------------------------------
   > Total cost:                   0 ETH


Summary
=======
> Total deployments:   4
> Final cost:          0 ETH

✨  Done in 160.80s.
```

# テストネットでの送金デモ

## Rinkebyでの口座作成
続いて以下の手順を参考に送金のデモを実行してみます。
https://loomx.io/developers/docs/en/extdev-transfer-gateway.html

loomのインストールとサンプルプロジェクトのclone、extdevでのデプロイテストは終わっているので  "2. Deploy token contracts to Rinkeby"の手順から行きます。

```shell
$ yarn gen:rinkeby-key
yarn run v1.13.0
 \$node ./scripts/gen-eth-key.js rinkeby
✨  Done in 0.94s.
$ cat rinkeby_account 
0xbaaf4ab20ee7a53f306d01b100164096cf24d0efAl
```

続いて https://faucet.rinkeby.io/ から上記のアカウント宛にテスト用のETHをもらいますが、スパム対策のため、TwitterやFacebookなどのSNSに**上記のアカウントを投稿したURL**を貼り付ける必要があります。

こんな感じのツイートを作成し、このURLを上記サイトで貼り付けました。

https://twitter.com/EthWizarth/status/1103672117596307456
<blockquote class="twitter-tweet" data-lang="ja"><p lang="in" dir="ltr"><a href="https://twitter.com/hashtag/Rinkeby?src=hash&amp;ref_src=twsrc%5Etfw">#Rinkeby</a> 0xbaaf4ab20ee7a53f306d01b100164096cf24d0ef</p>&mdash; wizarth_eth (@EthWizarth) <a href="https://twitter.com/EthWizarth/status/1103672117596307456?ref_src=twsrc%5Etfw">2019年3月7日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

しばらくするとETHが生成したアカウントに振り込まれます。
MetaMaskで"アカウントのインポート"から"秘密鍵をペースとしてください"の欄に上記のアカウントを貼り付けてアカウントを登録すれば、ネットワークの"Rinkebyテストネットワーク"からETHの額を確認できます。

## Rinkebyでの送金デモ

それではデモプログラムを動かしてみます。

```shell
$ export INFURA_API_KEY=13817170c63e49f1be5c1f85f8029da0
$ yarn deploy:rinkeby
yarn run v1.13.0
  \$ truffle deploy --network rinkeby
⚠️  Important ⚠️
If you\'re using an HDWalletProvider, it must be Web3 1.0 enabled or your migration will hang.


Starting migrations...
======================
> Network name:    'rinkeby'
> Network id:      4
> Block gas limit: 7312180


1_initial_migration.js
======================

   Deploying 'Migrations'
   ----------------------
   > transaction hash:    0xe9d05a98ba1ac4e3ae6c1a127ea2509f258bc7e30c50a7abc639fd83a75e8400
   > Blocks: 0            Seconds: 5
   > contract address:    0x230C5F3aF6B75033E57fEEB33AabDB2A5dc90b97
   > account:             0xBAaf4Ab20ee7a53f306d01b100164096cf24D0eF
   > balance:             2.995838069999722538
   > gas used:            277462
   > gas price:           15.000000001 gwei
   > value sent:          0 ETH
   > total cost:          0.004161930000277462 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:     0.004161930000277462 ETH


2_simple_store.js
=================

   > Saving migration to chain.
   -------------------------------------
   > Total cost:                   0 ETH


3_token_contracts.js
====================

   > Saving migration to chain.
   -------------------------------------
   > Total cost:                   0 ETH


4_rinkeby_contracts.js
======================

   Deploying 'MyRinkebyToken'
   --------------------------
   > transaction hash:    0x88d08219c64b5e0c509519294ed50b15ba623e2b1da8b6d9af58ab07adefbcd2
   > Blocks: 3            Seconds: 49
   > contract address:    0x50C4ac156C9ce02E7DD9aA071969b85daC4FCAd5
   > account:             0xBAaf4Ab20ee7a53f306d01b100164096cf24D0eF
   > balance:             2.961101114997406741
   > gas used:            2219773
   > gas price:           15.000000001 gwei
   > value sent:          0 ETH
   > total cost:          0.033296595002219773 ETH


   Deploying 'MyRinkebyCoin'
   -------------------------
   > transaction hash:    0x177b6f795a8d9da51b00a67e4ff47137d3deae8597406ceae5e73f7b21a9cd22
   > Blocks: 1            Seconds: 22
   > contract address:    0x18C5bd8FB86896CBB2fcD34b23Ae2987E1F94991
   > account:             0xBAaf4Ab20ee7a53f306d01b100164096cf24D0eF
   > balance:             2.938693274995912885
   > gas used:            1493856
   > gas price:           15.000000001 gwei
   > value sent:          0 ETH
   > total cost:          0.022407840001493856 ETH


*************************************************************************

MyRinkebyToken Contract Address: 0x50C4ac156C9ce02E7DD9aA071969b85daC4FCAd5
MyRinkebyCoin Contract Address: 0x18C5bd8FB86896CBB2fcD34b23Ae2987E1F94991

*************************************************************************


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:     0.055704435003713629 ETH


Summary
=======
> Total deployments:   3
> Final cost:          0.059866365003991091 ETH

✨  Done in 187.34s.
```

## ExtDevコインとRinkebyトークンの交換

続いで"3. Map extdev contracts to Rinkeby contracts"の手順に従ってトークンを交換するデモプログラムを動かしてみます。

```shell
$ node ./gateway-cli.js map-contracts token
Submitted request to map 0x4BB900a33E84aDf5933d983C9C17EeFAfC012334 to 0x50C4ac156C9ce02E7DD9aA071969b85daC4FCAd5
$ node ./gateway-cli.js map-contracts coin
Submitted request to map 0xA6Eac7d5f61ec8199eEF09fDa4F8CEd0B4c2EC3A to 0x18C5bd8FB86896CBB2fcD34b23Ae2987E1F94991
```

## アカウントの紐つけ

続いて"4. Map extdev account to Rinkeby account"の手順に従ってextdevアカウントとRinkebyアカウントを紐つけます。

```shell
$ node ./gateway-cli.js map-accounts
mapping eth:0xbaaf4ab20ee7a53f306d01b100164096cf24d0ef to extdev-plasma-us1:0xd027ffc9421e69c056af70fc6674831b2f42a528
Mapped extdev-plasma-us1:0xd027ffc9421e69c056af70fc6674831b2f42a528 to eth:0xbaaf4ab20ee7a53f306d01b100164096cf24d0ef
```

## トークンの送信

続いて"5. Token transfer"の手順に従ってトークンを行ってみます。

### [Rinkebyからextdev](https://loomx.io/developers/docs/en/extdev-transfer-gateway.html#from-rinkeby-to-extdev)

```sh
$ node ./gateway-cli.js mint-token 1
Token 1 minted, Rinkeby tx hash: 0x482fcfb0f599c17f370d1086f96cbcf30bf2028cdfd63eabe775c4ca04f9ec5a
$ node ./gateway-cli.js mint-token 2
Token 2 minted, Rinkeby tx hash: 0xfe3cc31639cec3374dc216fdd0a6b5b3ae0447c8304cff921d608a3e2cabf4b5
$ node ./gateway-cli.js mint-token 3
Token 3 minted, Rinkeby tx hash: 0x44fe12e060434d18905118a596b5528e733e913104b7041f336371191eb218f1
$ node ./gateway-cli.js deposit-token 1

Token 1 deposited, Rinkeby tx hash: 0xcc22a8c9fcb4cf85cae9b8c8ed3678ab478f4b83f53b0e478df40a1c209d087a

$ node ./gateway-cli.js token-balance -c eth

0xBAaf4Ab20ee7a53f306d01b100164096cf24D0eF owns 2 tokens.

First 2 token(s): 3,2

$ node ./gateway-cli.js token-balance

0xd027ffc9421e69c056af70fc6674831b2f42a528 owns 1 tokens.

First 1 token(s): 1

$ node ./gateway-cli.js token-balance -a gateway -c eth

0xb73C9506cb7f4139A4D6Ac81DF1e5b6756Fab7A2 owns 1 tokens.

First 1 token(s): 1
```

### MyRinkebyCoin トークンの送信

```sh
$ node ./gateway-cli.js deposit-coin 120
62009
120 tokens deposited to Ethereum Gateway.
Rinkeby tx hash: 0x7479fa086ad9ced62e2245085625fba9d6a92989b81b13f787ace3fa1ebf9806
$ node ./gateway-cli.js coin-balance -c eth
0xBAaf4Ab20ee7a53f306d01b100164096cf24D0eF balance is 999999880
$ node ./gateway-cli.js coin-balance
0xd027ffc9421e69c056af70fc6674831b2f42a528 balance is 120
$ node ./gateway-cli.js coin-balance -a gateway -c eth
0xb73C9506cb7f4139A4D6Ac81DF1e5b6756Fab7A2 balance is 120
```

### [extdevからRinkeby](https://loomx.io/developers/docs/en/extdev-transfer-gateway.html#from-extdev-to-rinkeby)
ERC721 tokensの戻し

```shell
$ node ./gateway-cli.js withdraw-token 1
Token 1 deposited to DAppChain Gateway...
Token 1 withdrawn from Ethereum Gateway.
Rinkeby tx hash: 0x8556dc5bc198997438e1d97e3badfc729772e1a338613ed9994573b7a1352747
$ node ./gateway-cli.js token-balance -c eth

0xBAaf4Ab20ee7a53f306d01b100164096cf24D0eF owns 3 tokens.

First 3 token(s): 3,2,1
$ node ./gateway-cli.js token-balance

0xd027ffc9421e69c056af70fc6674831b2f42a528 owns 0 tokens.

$ node ./gateway-cli.js token-balance -a gateway -c eth

0xb73C9506cb7f4139A4D6Ac81DF1e5b6756Fab7A2 owns 0 tokens.
```
 ERC20 tokens の戻し

```shell
$ node ./gateway-cli.js withdraw-coin 60
60 tokens deposited to DAppChain Gateway...
60 tokens withdrawn from Ethereum Gateway.
Rinkeby tx hash: 0xe7214c4216c720a452e5d36c30027f816b47368a426135138ca7d2c683707308
$ node ./gateway-cli.js coin-balance -c eth
0xBAaf4Ab20ee7a53f306d01b100164096cf24D0eF balance is 999999940
$ node ./gateway-cli.js coin-balance
0xd027ffc9421e69c056af70fc6674831b2f42a528 balance is 60
$ node ./gateway-cli.js coin-balance -a gateway -c eth
0xb73C9506cb7f4139A4D6Ac81DF1e5b6756Fab7A2 balance is 60
```
とりあえずここまでとします。

# まとめ

上記のデモでERC721とERC20のスマートコントラクトによるテストネット上でのコインとトークンの引き換えの動作確認が行えました。