EOS の truffle を目指す js4eos  の紹介

イーサリアムでスマートコントラクトを開発する時、Truffle フレームワークが便利なツールを提供してくれます。
参考　[SolidityのフレームワークTruffle入門](https://qiita.com/blueplanet/items/0c73f22cd49c7ec0cc99) 

EOS の場合は、まだそれほど完全になってないですが、EOS の Truffle を目指すライブラリが出ていているので、紹介します。
こちらのリポジトリになります。
[github.com/itleaks/js4eos](https://github.com/itleaks/js4eos)

## 機能
npm パッケージなので、インストール自体は、`npm install js4eos -g`になります。

- EOS をインストールせずに、各コマンドを実行できる
    - プロジェクトは、EOSをインストールせずに、便利に `EOS` コマンドを実行できるようにしたいところから始まった
    - ほぼ `cleos` 互換できるぐらい、 `wallet / get / push action / set / system` のサブコマンドを実行できる
- EOS のスマートコントラクト開発にあたって、 `EOS の　Truffle` を目指して、開発・テスト・デプロイ周りの機能を追加されました
    - `compile` でスマートコントラクトをコンパイルできる
    - `config` で接続するネットワークを選択できる、 `kylin / jungle / mainnet` サポートされている
    - `create` でアカウントまたはキーペアを作成できる
    - `dapp create / compile / deploy / test` でスマートコントラクトの作成・コンパイル・デプロイ・テストできる
    - `faucet` でテストネットの無料 EOS を貰える

## `test` 周りの機能
各コマンドの使い方は、`EOS`開発者であれば、`--help`を見ればすぐできるので、テスト周りを紹介します。

作業ディレクトリを作成し、`js4eos dapp init`実行するとテンプレートが展開され、下記の構造になっています。

<img width="1552" alt="Screen Shot 2018-12-14 at 6.28.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/4777/39a94635-27bf-ab1a-cac3-dd44d0969b0f.png">

テンプレートにテストファイルがあります。たとえ `eosio.token`のテストは下記になっています

```javascript
var options = {
    keyProvider:[
        '5JnzYUtJMGhnC4kzU5RTQza8EbaX1LHm4CGXoM3ppm1RBunKUvN',
    ]
}

Js4eos = require("js4eos")(options)
var assert = require('chai').assert;

describe("eosio.token contract test", function() {
    //Must set a large timeout
    this.timeout(10000);
    var eosio_token;
    before(async function(){
        eosio_token = await Js4eos.Contract("eosio.token") //use contract account to import contract
        await eosio_token.setActor("js4eostest11")
    });

    it('should success js4eostest11 transfer 0.0001 EOS to testtest1113', async function(){
        let data = await eosio_token.transfer("js4eostest11", "testtest1113", "0.0001 EOS", "js4eos truffle test")
        assert.equal(Js4eos.okTransaction(data), true)
    });
    it('should succcess get accounts table of eosio.token for js4eostest11', async function(){
        let data = await eosio_token.table("accounts", "js4eostest11")
        console.log(data.rows[0].balance)
    });
});
```

`js4eos dapp test test/eosio-token.js`で実行すると、テスト結果が表示されます

```shell
$ npx js4eos dapp test test/eosio-token.js


  eosio.token contract test
    ✓ should success js4eostest11 transfer 0.0001 EOS to testtest1113 (473ms)
999.4172 EOS
    ✓ should succcess get accounts table of eosio.token for js4eostest11 (42ms)


  2 passing (649ms)
```

このテストを参考して、自分のスマートコントラクトのテストも書けるようになると思います。

## 裏側の動き
`EOS` インストールせずにコンパイル・テストできるのがどんな仕組みなのかはすごく気になってちょっと調べてみました。
結論はシンプルで

- コンパイルは、ちょっと特別で、下記通りに、とあるサーバーにリクエストして結果をもらうようになっています

    ```javascript
    // https://github.com/itleaks/js4eos/blob/d2635eb2f9c29140818a7e101f1beda4a019a520/lib/compile.js#L26
    var req = request.post(Config.serviceUrl + "/newcompile", function (err, response, data) {
    ...
    ```

    **`serviceUrl` は`http://api.eosfavor.com`になっています**

- すべてのコマンドを全部確認出来たわけではないですが、コンパイル以外の機能は、設定されているAPIエントリポイントに投げて結果を解析し表示するようになっています。`js4eos_config.js` に使うネットワーク、プライベートキー、デプロイ時どのコントラクトをどのアカウントにデプロイするなど、全部設定できます。
    - 特に、テストは、実際にテストネットワークにスマートコントラクトをデプロイしてアクションを送信するようになっています
    - 上記の `eosio.token`送金テストのメモを`from EOS Advent Calendar 2018` に変更して、実行したら、CryptoKylin テストネット上でこのトランザクションが出来ました　⇒　https://tools.cryptokylin.io/#/tx/988794329c8b5683571691a4f4735c52060d48a9a579ef83582b297f4c6bd6a2

## 注意点
- テストは実際にテストネット（メインネットに設定するのもできる）で本物のトランザクションが発行されるので
    - メリットとしては、疑似テストではないので、成功の場合は、より安心できる
    - デメリットとしては
        - テストがテストネットの EOS が必要になります。テストネットのEOSは無料でもらえますが、テストする時気をつける必要があるのと、もらえるには手間があります
        - テストネットの状況次第、テストが落ちってしまったり、CIで回す場合失敗する確率がより高い恐れがある
- コントラクトのコンパイルですが、コントラクトソースをそのサーバーにアップロードしてそのサーバー上でコンパイルしてくれる流れなので、コンパイル環境が制御できないのと、スマートコントラクトのソースコードにこだわりがある場合は要注意

## まとめ
EOS の開発周りのツールもだんだん健全になってきたので、スマートコントラクトの開発はどんどんやりやすくなりました。