[Tech] ブロックチェーンサービス開発環境構築
はじめに
MCHでは、リモートのメンバーを含め複数のメンバーで1つのブロックチェーンアプリケーションを開発しています。
ブロックチェーン特有の部分はありますが、一般的なWeb開発の現場と変わらずチーム内の環境を揃えることが非常に重要です。
この記事では、主にスマートコントラクトとフロントエンドまわりについてMCHの開発環境を紹介します。
MCHで採用している主な言語とフレームワークは、Solidity (Truffe) / JavaScript (Nuxt.js) / Golang (gRPC / Loom SDK)です。スペースの関係上、Golang (gRPC / Loom SDK)の部分には言及しません。
お品書き
- nodenvによるNode.jsの管理
- direnvによる開発環境分離
- リポジトリ構成
- truffle-config.js方針
nodenvによるNode.jsの管理
今日のブロックチェーンアプリケーションは、truffleを始めとしてnpm上でエコシステムが形成されています。(2019/04/08編集 記事公開時にndenvを採用していましたがndenv開発終了に伴いnodenvに移行しております)
個人で開発する場合には、brewなどでNode.jsをインストールすることで十分です。チーム開発をする場合、小さな差異が時間のロスになることがあるため、予め利用するNode.jsのバージョンを管理しておくことにしました。
後述するdirenvと相性がよく、他の言語でも使われている*envであるnodenvでNode.jsのバージョン管理をしています。同時にNode.jsのビルドのため、node-buildも利用しています。
インストール方法は次の通りです。
$ git clone https://github.com/nodenv/nodenv.git ~/.nodenv
PATHと設定のためbash_profileなどに次のコードを追加します。
# nodenv
export NODENV_ROOT="$HOME/.nodenv"
if [ -d "${NODENV_ROOT}" ]; then
export PATH=${NODENV_ROOT}/bin:$PATH
eval "$(nodenv init -)"
fi
direnvによる開発環境分離
direnvを使った環境の分離をしています。MCHでは開発フェーズによりGitリポジトリを使い分けています。また、Ethereumの鍵情報や開発環境や本番環境への接続情報は環境変数経由で受け渡すようにしているため、direnvによる環境分離が非常に役立ちます。
ローカル開発環境は全員Macのためbrewでインストールしてしまいます。
$ brew install direnv
nodenvと同様に設定コードをbash_profileなどに記述します。
eval "$(direnv hook bash)"
Gitリポジトリには、sample.envrcを置いておき、
layout nodeexport PRIVATE_KEY="your eth private key"
export INFURA_API_KEY="your infura key"
各自が値を入れて.envrcにリネームします。.envrcには秘密鍵情報などが書かれているため、Gitにはコミットしません。
layout nodeの効果により、npmでインストールした実行ファイル場所であるnode_modules/.binに自動的にPATHが通るため、グローバルなnpm空間を汚すことなくCLIツールを導入することができます。
また、.node-versionファイルをコミットすることで、nodenvと合わせてNode.jsのバージョンをGitリポジトリ内で管理することができ、direnvにより自動的に切り替わるようになります。
リポジトリ構成
基本的なリポジトリ構成は次のようにしています。
.
├── .envrc
├── .node-version
├── Makefile
├── README.md
├── build/ # truffleのビルド結果
├── contracts/ # Solidityのコード
├── migrations/ # truffle migrate定義ファイル
├── node_modules/
├── nuxt.config.js
├── package.json
├── sample.envrc
├── src/ # Nuxt root
│ ├── assets/
│ │ └── build/ # ../../build へのリンク
│ ├── components/
│ ├── layouts/
│ ├── locales/
│ ├── middleware/
│ ├── pages/
│ ├── plugins/
│ ├── static/
│ └── store/
├── test/ # Solidityのテスト
├── truffle-config.js
└── yarn.lock
まだまだ試行錯誤中ではありますが、スマートコントラクトとフロントエンドのコードは同じリポジトリで管理しています。
基本方針として、リポジトリ直下はtruffleが標準のもの、src以下にNuxt標準のものを配置しています。
truffleがデプロイしたあとのABIおよびコントラクトアドレスをbuildディレクトリ以下に出力するため、このビルド結果ファイルをフロントエンドと共有したいという理由でこのようにしています。
src/assets/buildをbuildへのシンボルリンクにすることにより、Nuxt.jsでは、@/assets/buildでABIおよびコントラクトアドレスにアクセスできます。
truffle-config.js方針
MCHでは、スマートコントラクトのデプロイや初期データの挿入にtruffleを採用しています。ある程度以上の規模の運用知見はあまりなく、MCHでも試行錯誤しています。
次のコードはtruffle.config.jsの方針を示すコードです。
コントラクトをデプロイするときに使った秘密鍵は、共有したいもののみんなが知っていてはまずいという性質があります。(消失すると売上などが引き出せないが、関係者全員が引き出せる必要もない)
また、本番デプロイ可能な特定Walletの暗号鍵をペーパーウォレット2枚(keystoreファイルとパスワードを別々に印刷したもの)に分けて別の金庫で保管しています。
このような秘密鍵管理の前提から、よく見かけるtruffle-hdwallet-providerは利用しずらくtruffle-wallet-providerを利用して環境変数経由で直接秘密鍵を指定しています。
この環境変数経由の管理を徹底することで、前述したdirenvと合わせて、開発者全員が自分の鍵を利用してテストネット等にデプロイをすることができます。
おわりに
本記事ではMCHの開発環境とtruffleの方針を紹介しました。double jump.tokyoでは、ブロックチェーンアプリケーションの発展に少しでも寄与できるよう技術情報を発信していきます。
スマートコントラクトを中心とした開発環境の事例はまだまだ少なく、日々試行錯誤が中心です。この記事を見て、自分たちはこうやっているなどのフィードバックがあれば非常に嬉しいです。
また、ブロックチェーンで本格的に開発を行っていきたいという方を随時募集しておりますので、興味のある方はぜひお声掛けください!