Solidityプログラムをローカルで開発する
ローカルでの開発について
前節でInboxのコントラクトを作成しました。Remixで開発した内容をローカルで作成してwebで利用するには、ローカルでも開発できる環境にする必要があります。macの場合は「ターミナル」,windowsの場合は「コマンドプロンプト」または、「windows Power Shell(PS)」を開き進めていきます。 コマンドが異なる場合があるので、windowsはPSモードだと良いと思います。
Nodeのバージョン確認
nodejsのバージョンに注意してください。node -v
でv8.0.0
以上であれば良いはずです。まだnodejsをインストールしていない方は、https://nodejs.org/en/download からダウンロードとインストールしてください。
開発フォルダ作成
作業スペース(フォルダ)を作成しましょう。
mkdir ethereum-solidity
で ethereum-solidityフォルダを作成した後、その中にmkdir Inbox
でInboxフォルダを作成します。
フォルダ内で初期設定を行います。Inboxフォルダの中で npm init
と入力しましょう。
するとパッケージの名前などを聞かれるので下記のように最初だけ「inbox」と入力して進めます。あとは、エンターを入力し続けて大丈夫です。
name: (Inbox) inbox
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
入力が完了すると下記のように作成されたパッケージの内容が「package.json」にあることを知らせてくれます。
About to write to /作成場所までのパス/ethereum-solidity/Inbox/package.json:
{
"name": "inbox",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
するとフォルダの中に「package.json」作成されています。
フォルダ構成を下記のようにします。段落下げは、フォルダの中にあるという表記です。
Inbox/
contracts/
Inbox.sol
test/
Inbox.test.sol
package.json
compile.js
deploy.js
まずは、contractsフォルダを作成します。 mkdir contracts
と入力しましょう。
次に、contractsフォルダの中にInbox.solを作成します。vi Inbox.sol
または、AtomなどのIDEで作成していきましょう。Atomのインストールは、https://atom.io/です。
solデータの作成
Inbox.solが作成できたら前節のRemixで作成したInboxの内容をコピーして貼り付けましょう。
pragma solidity ^0.4.0;
contract Inbox {
string public message;
function Inbox(string initialMessage) public{
message = initialMessage;
}
function setMessage(string newMessage) public{
message = newMessage;
}
function getMessage() public view returns(string){
return message;
}
}
コンパイル用のモジュールを利用するために、npmでインストールします。npm install --save solc
と入力しましょう。すると新しく node_modules というフォルダが作成されます。
次に、compile.jsを作成していきます。
const path = require('path');
const fs = require('fs');
const solc = require('solc');
const IndexPath = path.resolve(__dirname,'contracts', 'Inbox.sol');
const source = fs.readFileSync(IndexPath, 'utf8');
console.log(solc.compile(source,1));
Solデータのコンパイル
compile.jsを実行してcontractsを生成します。node compile.js
と入力しましょう。英数字がたくさん流れるはずです。console.log()によりcontractsのコンパイルした内容が表示されています。中身をみるとまだ実装していない機能もたくさんありそうです。
最後にこのファイルを他のファイルから利用できるようにmodule.exportsします。
module.exports = solc.compile(source,1);
しかし、このままではconsole.logで出したように中身が全部出てしまっています。そのため内容を絞って利用できるようにします。
module.exports = solc.compile(source,1).contracts[':Inbox'];
web3.jsをインストールする
web3.jsは、ethereumの中身にアクセスするためのjavascript APIです。まずは、インストールしていきます。下記をコマンドプロンプトで入力しましょう。
npm install --save mocha ganache-cli
npm install web3
少しインストールに時間がかかるため、その間まだ作っていないフォルダを作成していきます。(エラーの場合npm と nodeのバージョンのアップデートにて解決することが多いです。)web3.jsはv0.x.xと v1.x.xで扱いが大きく異なるため注意してください。今回はv1.x.xを利用します。
testフォルダとtest/Inbox.test.jsを作成しましょう。
mochaはjavascriptの単体テスト用のパッケージで、 ganache-cliは、ethereumのローカル環境です。
簡単なテストコードを作成する
テストコードを書いていきますが、まずはどんな風に書くかを確認していきます。まずは、コントラクトに関係ないクラスを作成し正常系のみをテストします。
const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());
class Tag{
agile(){
return 'hoge';
}
guild(){
return 'fuga';
}
}
describe('Tag', () => {
it('say hoge', () => {
const tag = new Tag();
assert.equal(tag.agile(),'hoge');
});
});
その後、package.jsonの中でtestのscriptsを「mocha」で指定します。
{
"name": "inbox",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "mocha"
},
"author": "",
"license": "ISC"
}
テストコードを実行する
テストコードが書けましたら、実行しましょう。コマンドプロンプトで npm run test
を入力してください。テストが無事通った場合、下記が表示されるはずです。
>mocha
Tag
say fuga
1 passing
コントラクトを含めたテストコードを作成する
先ほど、作成したInbox.test.jsのconst部分以外を削除します。その後、web3を利用してアカウントリストを取得するまでのテストコードを作成します。
beforeEach(() => {
//Get a list of all accounts
web3.eth.getAccounts().then(fetchedAccounts => {
console.log(fetchedAccounts);
});
//Use one of those accounts to deploy
//the contract
});
describe('Inbox', () => {
it('deploy a contract', () => {});
});
非同期処理を書く
アカウントが作られる時間が少しだけかかるため、非同期処理に変更します。
let accounts;
beforeEach(async() => {
//Get a list of all accounts
accounts = await web3.eth.getAccounts();
});
describe('Inbox', () => {
it('deploy a contract', () => {
console.log(accounts);
});
});
Inboxのテストコードを作成する STEP1
const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());
const { interface, bytecode } = require('../compile'); //追記
let accounts;
let inbox; //追記
beforeEach(async() => {
//Get a list of all accounts
accounts = await web3.eth.getAccounts();
//Use one of those accounts to deploy
//the contract 以下追記
inbox = await new web3.eth.Contract(JSON.parse(interface))
.deploy({ data: bytecode, arguments: ['Hi there!'] })
.send({ from: accounts[0],gas:'1000000' });
});
describe('Inbox', () => {
it('deploy a contract', () => {
console.log(inbox); //追記
});
});
console.logで出力された中で「method」という部分があります。その中に今回作成したInboxのsetMessageなどが含まれているはずです。このmessage内容が正常かテストしましょう。下記のようにInbox.test.jsをのdescribe部分を変更します。
describe('Inbox', () => {
it('deploy a contract', () => {
assert.ok(inbox.options.address);
});
it('has a default message', async() => {
const message = await inbox.methods.message().call();
assert.equal(message, 'Hi there!');
});
});
Inboxのテストコードを作成する STEP2
messageが正常に動いていることが確認できました。次にsetMessageメソッドが正常に動いているかをテストします。Inbox.test.jsのdescribeに追記します。
describe('Inbox',() =>{
ー略ー
it('can change the message', async(){
await inbox.methods.setMessage('bye').send({ from: accounts[0]});
const message = await inbox.methods.message().call();
assert.equal(message, 'bye');
});
});
Last updated
Was this helpful?