目的:利用solc更方便的执行合约,不必在命令行中拷贝粘贴abi等内容。
首先建立一个文件夹contract_workflow,然后项目进行初始化和安装solc
npm init
npm install solc
然后在里面新建四个子文件夹(主要是为了便于管理文件)
contracts:放置合约
tests:用于测试
scripts:放置js脚本
compiled:放置输出内容
然后一份简单的测试源码(car.sol),放置在contracts中
pragma solidity >0.4.22;
contract Car{
string public brand;
constructor(string memory initialBrand) public{
brand = initialBrand;
}
function setBrand(string memory newBrand) public{
brand = newBrand;
}
function getBrand()public view returns(string memory){
return brand;
}
}
开始编辑脚本(compile.js),放置于scripts中
//引入所需要的工具
const fs = require('fs');
const solc = require('solc');
const path = require('path');
//清空compile文件
// const compilePath = path.resolve(__dirname,'../compiled');
// fs.removeSync(compilePath);
// fs.ensureDirSync(compilePath);
//拼接路径
const contractPath = path.resolve(__dirname, '../contracts', 'Car.sol');
console.log("路径:" + contractPath);
//读取源文件
const contractSource = fs.readFileSync(contractPath, 'utf-8');
//预先定义好编译源json对象
let jsonContractSource = JSON.stringify({
language: 'Solidity',
sources: {
'Car.sol': { // 指明编译的文件名
content: contractSource, // solidity 源代码
},
},
settings: { // 自定义编译输出的格式。以下选择输出全部结果。
outputSelection: {
'*': {
'*': ['*']
}
}
},
});
// 编译得到结果
let output = JSON.parse(solc.compile(jsonContractSource));
console.log("json对象源文件:" + output);
compileJson = {
'abi': {},
'bytecode': ''
};
// output 为json对象,根据json结构保存对应的abi和bytecode
for (var contractName in output.contracts['Car.sol']) {
compileJson.abi = output.contracts['Car.sol'][contractName].abi;
compileJson.bytecode = output.contracts['Car.sol'][contractName].evm.bytecode.object;
}
console.log(compileJson);
// 将compileJson数据输出到compile.json文件
const compileJsonPath = path.resolve(__dirname,'../compiled','compile.json');
fs.writeFile(compileJsonPath, JSON.stringify(compileJson), function(err){
if(err)
console.error(err);
console.log("Car contract compiled sucessfully.")
})
这样就完成了简本编辑,然后开始编辑部署脚本deploy.js,放置在scripts文件夹中。
const Web3 = require('web3');
const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
const fs = require('fs-extra');
const path = require('path');
//读取abi和code
const filePath = path.resolve(__dirname, '../compiled', 'compile.json');
const compileJson = JSON.parse(fs.readFileSync(filePath));
//
(async () => {
//异步获取账户
let accounts = await web3.eth.getAccounts();
//直接创建合约,链式调用
let result = await new web3.eth.Contract(compileJson.abi)
.deploy({ data: compileJson.bytecode, arguments: ['BMW'] })
.send({ from: accounts[0], gas: 5000000 });
//返回合约地址
console.log('contractAddress:', result.options.address);
})();
此时在terminal中,cd至scripts文件夹使用命令
node deploy.js
就会返回合约地址
接着使用mocha框架进行测试,先在contract_workflow中安装mocha
//安装到本地开发环境依赖中去,会在package.json中显示
//dependencies:运行环境依赖,需要随项目打包(--save实现)
//devDependencies:开发环境依赖(--save-dev实现)
npm install mocha --save-dev
//本地安装ganache-cli
npm install ganache-cli --save-dev
编辑测试文件Car.spec.js代码,放置于tests文件夹中:
const assert = require('assert');
const path = require('path');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());
const contractPath = path.resolve(__dirname, '../compiled','compile.json');
const compileJson = require(contractPath);
// const fs = require('fs');
// const compileJson = JSON.parse(fs.readFileSync(contractPath));
let contract;
let accounts;
const initialBrand = 'BMW';
//describe 是测试套件,it是测试用例,第一个参数都是名称,第二个参数是实际执行的函数
describe('#contract', () => {
//每次执行测试之前都会执行一遍
beforeEach(async () => {
accounts = await web3.eth.getAccounts();
contract = await new web3.eth.Contract(compileJson.abi)
.deploy({ data: compileJson.bytecode, arguments:[initialBrand]})
.send({ from: accounts[0], gas: 5000000});
});
it('deploy contract successfully', () => {
assert.ok(contract.options.address);
});
//1.0全部都是异步调用
it('should has a initial brand',async()=>{
let brand =await contract.methods.brand().call();
assert.equal(brand,initialBrand);
})
it('should set a new brand',async()=>{
const newBrand = 'Audi';
await contract.methods.setBrand(newBrand)
.send({from:accounts[0]});
const brand = await contract.methods.brand().call();
assert.equal(brand,newBrand);
});
});
但是当使用node执行时会出现describe未定义问题,查询后改为全局安装,用mocha执行test文件
//全局安装
npm install -g mocha
//执行
mocha Car.spec.js
通过npm机制,将整个自动化流程串起来。
修改package.json中的scripts
"scripts": {
"compile":"node scripts/compile.js",
"predeploy":"npm run compile",
"deploy":"node scripts/deploy.js",
"pretest":"npm run compile",
"test": "mocha tests"
},
之后在terminal中contract_workflow目录下执行
npm run test
网友评论