//tips
//smart contract
ついに同じ悩みを持つ人を発見し解決方法を入手した。vscode内でもコンパイルバージョンを変更しなければいけなかったよう。
Source file requires different compiler version (current compiler is 0.8.10+commit.fc410830.Emscripten.clang)
助かった。
Truffleを使わずにカスタムで作成していく。
フォルダ構造としては
Contracts
-Inbox.sol
Test
-inbox.test.js
Package.json
Compile.js
Deploy.js
となる。
フォルダにnpm install solc@0.4.17で0.4.17バージョンでのコンパイル方式をインストールしておく。
Compile.jsから確認。
// compile code will go here
const path=require('path');
const fs=require('fs');//file system module
const solc=require('solc');
//windowsなどのplatformなどにより呼び方が違うのでrequire('./...')などと書かない方がいいよう
//.solファイルへのパスを通す
const inboxPath=path.resolve(__dirname,'contracts','Inbox.sol');
//パス先のファイルの中身、ソースコード
const source=fs.readFileSync('inboxPath','utf8');
console.log(solc.compile(source,1));
これをターミナルから実行する。
node compile.jsを実行するもエラー。
Error: ENOENT: no such file or directory, open 'inboxPath'
こちらの問題を探してみるも解決せず。
41.the compile script、ここは質問中。
進められるところを進めておく。
デプロイの流れとして、コンパイルされたものはbytecodeとabiに分岐し、bytecodeがネットワーク上のcontract instanceになることは前にも触れたがabiの方をローカルネットワークで使う際にはabiを通して、ブロックチェーンにアクセスできるコードライブラリのweb3にわたり、ganacheなどのローカルネットワークに合流することになる。web3はjsとイーサリアムネットワークの橋渡しをするもの。v0とv1があり、v1系統はpromisesとawaitが使えるようになったよう。
テスト環境を作っていく。
npm install mocha ganache-cli web3
Web3インスタンスとGanacheはprovaiderと呼ばれる層を通じてコミュニケーションを行うことになる。
Mochaはjsをテストするフレームワーク。実は今まで使ってきた下記メソッドは全てmochaのフレームワークのものだった。
テストの際に使用する
It:
テストや前提条件の確認に使用
Describe:
Itを塊としてグループ単位でテストする場合に使用
beforeeach:一度だけ実行されるセットアップ用の条件
実際に書いてみると、
// contract test code will go here
const assert=require('assert');
const ganache=require('ganache-cli');
const Web3=require('web3');
const web3=new Web3(ganache.provider());
class Car{
park(){
return 'stopped';
}
drive(){
return 'vroom';
}
}
describe('Car',()=>{
it('can park',()=>{
const car=new Car();
assert.equal(car.park(),'stopped');
});
});
Package.jsonも下記に修正。
"scripts": {
"test": "mocha"
},
テストの準備が整ったので実行。
npm run test
無事に下記のように成功した。
> inbox@1.0.0 test
> mocha
Car
✔ can park
1 passing (16ms)
さらに加筆してbeforeEachを使用し、そちらに移した変数はitからはアクセスできないのでグローバル変数としている。
//どこからもアクセスできるように
let car;
beforeEach(()=>{//他のitテストの前にsetupとして実行される
//const car=new Car();これではscopeの問題でitの中からアクセスできないので
car=new Car();
});
//これを実行する時にはpackage.jsonも編集
describe('Car',()=>{
it('can park',()=>{
//const car=new Car();
assert.equal(car.park(),'stopped');
});
it('can drive',()=>{
//const car=new Car();
assert.equal(car.drive(),'vroom');
});
});
ここからweb3を使用してganacheのローカルネットワークにあるロックされていないアカウントにアクセスしていく。
// contract test code will go here
const assert=require('assert');
const ganache=require('ganache-cli');
const Web3=require('web3');
const web3=new Web3(ganache.provider());
beforeEach(()=>{
//Get a list of all ccounts
web3.eth.getAccounts()
.then(fetchedAccounts=>{
console.log(fetchedAccounts);
});
//Use one of those accounts to deploy
//the contract
});
describe('Inbox',()=>{
it('deploys a contract',()=>{
});
});
これをnpm run testで実行すると、アカウントが表示され、Ganacheが自由に使って良い10個のアカウントをくれていることがわかる。
これを最新の構文に直していく。.thenではなくasyncを使うことにする。
// contract test code will go here
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 ccounts
accounts = await web3.eth.getAccounts();
/*
.then(fetchedAccounts=>{
console.log(fetchedAccounts);
});
*/
//Use one of those accounts to deploy
//the contract
//ここではcompile.jsコードからbytecodeをimportする必要がある
//最初のデプロイの実施
inbox=await new web3.eth.Contract(JSON.parse(interface))
.deploy({data:bytecode,arguments:['Hi,there!']})
.send({from:accounts[0],gas:'1000000'});
});
describe('Inbox',()=>{
it('deploys a contract',()=>{
console.log(inbox);
});
});
ついに先のパスが通らない問題が解決。要因はfs.readFileSync部分の不要な’’とmoduleのtypo。
//console.log(inboxPath);//取得している絶対パス
//console.log(process.cwd());//現在の相対パス
Console.logは有能だった。