Ethereum界隈が楽しそうなので、Solidityの開発環境を整えた。
mochaとganache-cliを使ったローカルテストと、truffle-hdwallet-providerとinfura.ioを使ったデプロイ。
利用するライブラリのバージョンなどは後述するpackage.json参照。作業環境のディレクトリ構成は以下の通り。
.
├── compile.js
├── contracts
│ └── Calc.sol
├── deploy.js
├── package.json
└── test
└── Calc.test.js
①アカウント等を準備
Metamaskをインストール。
KovanやRopstenの Test NetのfaucetからEtherをゲット。
Hi-EtherのSlackにも参加させて頂きました。
②コントラクトを実装
まずはSolidityで簡単なコントラクトを実装。remix便利だ。
contracts/Calc.sol
pragma solidity ^0.4.17;
contract Calc{
int32 public num;
function Calc(int32 initialNum) public{
num = initialNum;
}
function setNum(int32 newNum) public{
num = newNum;
}
function sqNum() public returns (int32){
return num * num;
}
}
③ローカルテスト
環境はmacOS version10.12.3、npm 5.6.0、node v9.6.1で、package.jsonは以下の通り。
package.json
{
"name": "calc",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "mocha"
},
"author": "",
"license": "ISC",
"dependencies": {
"ganache-cli": "^6.0.3",
"mocha": "^5.0.1",
"solc": "^0.4.20",
"truffle-hdwallet-provider": "0.0.3",
"web3": "^1.0.0-beta.26"
}
}
Solidityコンパイルは以下の通り行う。
compile.js
const path = require('path');
const fs = require('fs');
const solc = require('solc');
const calcPath = path.resolve(__dirname, 'contracts', 'Calc.sol');
const source = fs.readFileSync(calcPath, 'utf8');
module.exports = solc.compile(source, 1).contracts[':Calc'];
プロバイダーはganacheを使ってテストプログラムを下記のように作成。
test/Calc.test.js
const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const provider = ganache.provider();
const web3 = new Web3(provider);
const {interface, bytecode } = require('../compile');
let accounts;
let calc;
beforeEach(async () => {
accounts = await web3.eth.getAccounts();
calc = await new web3.eth.Contract(JSON.parse(interface))
.deploy({data: bytecode, arguments: [7]})
.send({from: accounts[0], gas: '1000000'});
calc.setProvider(provider);
});
describe('Calc', () => {
it('deploys a contract', () => {
assert.ok(calc.options.address);
});
it('has a default number', async () => {
const num = await calc.methods.num().call();
assert.equal(num, 7);
});
it('can change the number', async () => {
await calc.methods.setNum(3).send({from: accounts[0]});
const num = await calc.methods.num().call();
assert.equal(num, 3);
});
it('can square the number', async () => {
const squaredNum = await calc.methods.sqNum().call();
assert.equal(squaredNum, 49);
});
});
npm run testでテスト完了!
④デプロイ
infura.ioのAPI とtruffle-hdwallet-providerを使ってデプロイ。
deploy.js
const HDWalletProvider = require('truffle-hdwallet-provider');
const Web3 = require('web3');
const {interface, bytecode } = require('./compile');
const provider = new HDWalletProvider(
'xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx',
'https://kovan.infura.io/xxxxxxxxxxxxxxxxxxxx'
);
const web3 = new Web3(provider);
const deploy = async () => {
const accounts = await web3.eth.getAccounts();
console.log("account: ", accounts[0]);
const result = await new web3.eth.Contract(JSON.parse(interface))
.deploy({ data: bytecode, arguments: [7]})
.send({ gas: '1000000', from: accounts[0]});
console.log("address: ", result.options.address);
};
deploy();
node deploy.jsでデプロイしたら、トランザクションアドレスを表示するので、あとはremixなどから実際に動かしたりなどご自由に楽しむ感じで。
参考資料
Stephen Grider, “Ethereum and Solidity: The Complete Developer's Guide”