Truffle
Truffle(トリュフ)は、スマートコントラクトの開発に必要となる、コンパイル、リンク、デプロイ、バイナリ管理の機能を持つ統合開発環境フレームワークです。
デプロイやマイグレーションもスクリプトで管理することができます。
Solidityを使用したスマートコントラクト開発のデファクトスタンダートになり得ます(※2018/04/13時点)。
インストール方法
Truffleはnpmでインストールすることができます。
$ npm install -g truffle
プロジェクト作成
$ truffle init
を実行するとプロジェクトを作成することができます。
$ truffle init Downloading... Unpacking... Setting up... Unbox successful. Sweet! Commands: Compile: truffle compile Migrate: truffle migrate Test contracts: truffle test
コマンドの実行が完了すると、以下のディレクトリとファイルが作成されます。
名前 | 説明 |
---|---|
contracts/ | スマートコントラクトのディレクトリ |
migrations/ | スクリプトを記述できるデプロイメントファイルのディレクトリ |
test/ | テストファイルのディレクトリ |
truffle-config.js | Truffleの設定ファイル |
truffle.js | Truffleの設定ファイルの雛形 |
Ganache
アプリケーションがブロックチェーンに与える影響をGUIで確認することができる。
Truffle Develop
Truffleには、開発用のブロックチェーンとしてTruffle Developが組み込まれています。
$ truffle develop
で実行することができます。
インタラクティブなプロンプトが表示され、対話式でコマンドを実行することができます。
コントラクトのコンパイル
$ truffle compile
truffle(develop)> compile
Truffle Developからコンパイルすることも可能です。
Truffleはコンパイル時間を短くするため、差分コンパイルが採用されています。
差分コンパイルではなく、全ファイルをコンパイルし直したい場合は、allオプションを付けます。
$ truffle compile --all
マイグレーション
マイグレーションファイルは、イーサリアムネットワークにコントラクトをデプロイする際に使用されます。
プロジェクトに新たなコントラクトを追加する際には、新規でスクリプトを追加します。
実行されたマイグレーションの履歴は、マイグレーションコントラクトによってブロックチェーン上に記録されます。
$ truffle migrate
上記のコマンドでマイグレーションが実行されます。
以前にマイグレーションが正常に実行されている場合、truffle migrate
は最後に実行されたマイグレーションから実行を開始し、新たに作成されたマイグレーションのみを実行します。
新たなマイグレーションが存在しない場合は何も実行しません。
全マイグレーションを最初から実行したい場合は、resetオプションを付けます。
$ truffle migrate --reset
公式サンプルMetaCoin
Truffleフレームワークには、独自コインを作成してアカウント間でやり取りするコントラクトのサンプルが用意されています。
サンプルプロジェクトのダウンロード
ディレクトリを作成して、その中でtruffle unbox
コマンドを実行することでサンプルを取得することができます。
$ mkdir metacoin $ cd metacoin $ truffle unbox metacoin
truffle unbox
コマンドは、Truffleフレームワークが定期ィオうするサンプルをローかつ環境に展開するコマンドです。
こちらに様々なサンプルが用意されています。
コンパイルとマイグレーションの実行
$ truffle develop truffle(develop)> migrate Using network 'develop'. Running migration: 1_initial_migration.js Deploying Migrations... ... 0xe993a882da8ba0d176a7feffe95e0f5fb2b417d0a8f07320bdfa722004360851 Migrations: 0x8cdaf0cd259887258bc13a92c0a6da92698644c0 Saving successful migration to network... ... 0xd7bc86d31bee32fa3988f1c1eabce403a1b5d570340a3a9cdba53a472ee8c956 Saving artifacts... Running migration: 2_deploy_contracts.js Deploying ConvertLib... ... 0xb097805eae8952a028f633d8eb76256fb00782cac3a4989c59615f571f83add8 ConvertLib: 0x345ca3e014aaf5dca488057592ee47305d9b3e10 Linking ConvertLib to MetaCoin Deploying MetaCoin... ... 0x678ce1cfd0903e0fb7ec5d293858c32f428184c18ccaea408e64f20ef1194e82 MetaCoin: 0xf25186b5081ff5ce73482ad761db0eb0d25abfbf Saving successful migration to network... ... 0x059cf1bbc372b9348ce487de910358801bbbd1c89182853439bec0afaee6c7db Saving artifacts... truffle(develop)> m = MetaCoin.at("0xf25186b5081ff5ce73482ad761db0eb0d25abfbf")
マイグレーションの実行が完了すると、上記のようなログが出力されます。
実行環境によって、出力される値は違います。
MetaCoinコントラクトの参照
マイグレーション時に出力されたログのMetaCoin: 0xf25186b5081ff5ce73482ad761db0eb0d25abfbf
というところから、MetaCoinのアドレスを取得することができます。
at()にMetaCoinのアドレスを指定することで、MetaCoinのコントラクトを変数から参照できます。
truffle(develop)> m = MetaCoin.at("0xf25186b5081ff5ce73482ad761db0eb0d25abfbf")
getBalanceの呼び出し
truffle(develop)> m.getBalance(web3.eth.accounts[0]) { [String: '10000'] s: 1, e: 4, c: [ 10000 ] } truffle(develop)> m.getBalance(web3.eth.accounts[1]) { [String: '0'] s: 1, e: 0, c: [ 0 ] }
sendCoinでコインを送る
truffle(develop)> m.sendCoin(web3.eth.accounts[1], 1000) { tx: '0x6b650d826e20aba52c82636f3f2947a263a66714f0684975253527e6f810d1ea', receipt: { transactionHash: '0x6b650d826e20aba52c82636f3f2947a263a66714f0684975253527e6f810d1ea', transactionIndex: 0, blockHash: '0xd27c08f5cf5efd1c47ba15b451ac78643dba5af026812de3b77e51eddf038e5a', blockNumber: 6, gasUsed: 51024, cumulativeGasUsed: 51024, contractAddress: null, logs: [ [Object] ], status: '0x01', logsBloom: '0x00000000000000000000000000000000010000000000000000000010000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000008000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000010000000000000000000010000000000000000000000000000000000000000010000000002000000000000000000000000000000000000002000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' }, logs: [ { logIndex: 0, transactionIndex: 0, transactionHash: '0x6b650d826e20aba52c82636f3f2947a263a66714f0684975253527e6f810d1ea', blockHash: '0xd27c08f5cf5efd1c47ba15b451ac78643dba5af026812de3b77e51eddf038e5a', blockNumber: 6, address: '0xf25186b5081ff5ce73482ad761db0eb0d25abfbf', type: 'mined', event: 'Transfer', args: [Object] } ] } truffle(develop)> m.getBalance(web3.eth.accounts[0]) { [String: '9000'] s: 1, e: 3, c: [ 9000 ] } truffle(develop)> m.getBalance(web3.eth.accounts[1]) { [String: '1000'] s: 1, e: 3, c: [ 1000 ] }
残高を確認する
truffle(develop)> m.getBalance(web3.eth.accounts[0]) { [String: '9000'] s: 1, e: 3, c: [ 9000 ] } truffle(develop)> m.getBalance(web3.eth.accounts[1]) { [String: '1000'] s: 1, e: 3, c: [ 1000 ] }
truffle(develop)> m.sendCoin(web3.eth.accounts[1], 10000) { tx: '0x175c04f4e568c865ef3735bc5ffd041b8e03b7832889ac4f9b7547cecdc2c3da', receipt: { transactionHash: '0x175c04f4e568c865ef3735bc5ffd041b8e03b7832889ac4f9b7547cecdc2c3da', transactionIndex: 0, blockHash: '0x529962199f9efb27c9111da7d4340df033b0eb659cb3a20a5f2949ca57cb7df4', blockNumber: 7, gasUsed: 23561, cumulativeGasUsed: 23561, contractAddress: null, logs: [], status: '0x01', logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' }, logs: [] } truffle(develop)> m.getBalance(web3.eth.accounts[0]) { [String: '9000'] s: 1, e: 3, c: [ 9000 ] } truffle(develop)> m.getBalance(web3.eth.accounts[1]) { [String: '1000'] s: 1, e: 3, c: [ 1000 ] }
テストコード
テストコードは以下になります。
metacoin/metacoin.js at master · akifumi/metacoin · GitHub
truffle(develop)> test
testコマンドでテストを実行することができます。
テストを記述しておけば、正常に動作することをチェックすることができます。
お金を取り扱うコントラクトを作成するのであれば、十分すぎるほどテストを実行しておくことをおすすめします。