IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 区块链 -> 以太坊Dapp 编译脚本 + 部署脚本 + 测试脚本 -> 正文阅读

[区块链]以太坊Dapp 编译脚本 + 部署脚本 + 测试脚本

目录

目录结构

创建包管理

安装依赖

编译脚本

安装依赖

准备合约源码

准备编译脚本

执行编译脚本

部署脚本?

安装依赖

准备部署脚本

执行部署脚本?

测试脚本

安装依赖

准备测试脚本

执行测试脚本

测试例子

?测试脚本

执行测试脚本?

将以上工作流步骤串起来

修改 package.json??

?执行命令


目录结构

手动创建 contract_workflow 文件夹

并在其目录下创建 compiled、contracts、scripts、test 四个文件夹

  • contracts 存放源代码
  • scripts 存放编译脚本
  • compiled 存放编译结果
  • test?存放测试文件

创建包管理

在 contract_workflow 目录下,执行以下命令

会生成 package.json 文件

npm init

安装依赖

在 contract_workflow 路径下,执行以下命令

安装ganache-cli,附加生成 node_modules 和 package-lock.json 文件

npm install ganache-cli@6.1.8 --save-dev

ganache-cli 仅仅用作测试用,每一次重新运行都会重新生成10个新的账号

运行 ganache-cli 后面用作测试用

./node_modules/.bin/ganache-cli

编译脚本

安装依赖

在 contract_workflow 路径下,执行以下命令

npm install solc@0.4.25

准备合约源码

contracts 目录下 新建合约?Voting.sol

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.4.25 <0.9.0;

contract Voting{
    bytes32[] public candidateList;
    mapping(bytes32 => uint8) public votesReceived;
    constructor(bytes32[] memory candidateListName) public{
        candidateList = candidateListName;
    }

    function validateCandidate(bytes32 candidateName) internal view returns(bool){
        for (uint8 i = 0; i < candidateList.length; i++){
            if(candidateName == candidateList[i]){
                return true;
            }
        }
        return false;
    }

    function vote(bytes32 candidateName) public{
        require(validateCandidate(candidateName));
        votesReceived[candidateName] += 1;
    }

    function totalVotesFor(bytes32 candidateName) public view returns(uint8){
        require(validateCandidate(candidateName));
        return votesReceived[candidateName];
    }
}

准备编译脚本

scripts 目录下 新建脚本 compile.js

const fs = require('fs-extra');
const solc = require('solc');
const path = require('path');

// resolve 将后面的路径拼接起来
// __dirname 表示当前目录, 两个下划线_

// 清除编译结果, 保留最新编译结果, 保障一致性
const compiledDir = path.resolve(__dirname, '../compiled');
fs.removeSync(compiledDir);
fs.ensureDirSync(compiledDir);

const contractDir = path.resolve(__dirname, '../contracts', 'Voting.sol')
// 同步读取文件
const contractSource = fs.readFileSync(contractDir,'utf-8');
let compiledResult = solc.compile(contractSource, 1);

console.log(compiledResult);

// solidity合约, 如果报错, 错误定位
if(Array.isArray(compiledResult.errors) && compiledResult.errors.length){
	throw new Error(compiledResult.errors[0])
}

// 导出编译后结果 compiledResult, 也可以使用 module.export
Object.keys(compiledResult.contracts).forEach(name=>{
	// 正则表达式取:开头之后的字符串
	let contractName = name.replace(/^:/,'');
	let filePath = path.resolve(__dirname, '../compiled', `${contractName}.json`);
	// 输出
	fs.outputJsonSync(filePath, compiledResult.contracts[name]);
	console.log("Saving json file to ",filePath);
})

执行编译脚本

在 contract_workflow 路径下,执行以下命令

node ./scripts/compile.js


部署脚本?

安装依赖

在 contract_workflow 路径下,执行以下命令

npm install web3@1.7.0

准备部署脚本

scripts 目录下 新建脚本 deploy.js

const Web3 = require('web3');
let web3;
if (typeof web3 !== 'undefined') {
	//当你之前如果使用过MetaMask钱包等时,你的provider可能已经设置好了,web3.currentProvider就是你目前的provider
	web3 = new Web3(web3.currentProvider);
} else {
	// set the provider you want from Web3.providers
	web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}


const fs = require('fs-extra');
const path = require('path');

const contractDir = path.resolve(__dirname, '../compiled', 'Voting.json');
const {interface, bytecode} = require(contractDir);
let arguments = [[web3.utils.fromAscii('Alice'),web3.utils.fromAscii('Bob'),web3.utils.fromAscii('Cary')]]
let gas = 5000000;

(async () => {
	let accounts = await web3.eth.getAccounts();
	console.time("deploy time");
	let result = await new web3.eth.Contract(JSON.parse(interface))
				.deploy({
					data:bytecode,
					arguments:arguments
				})
				.send({
					from:accounts[0],
					gas:gas
				})
	console.timeEnd("deploy time")
	
	// 输出合约地址
	console.log("contract address: ",result.options.address);
})();

执行部署脚本?

在 contract_workflow 路径下,执行以下命令

执行前确定你的私链正在运行

node ./scripts/deploy.js

?


测试脚本

mocha 是一个 JavaScript 的测试框架

既可以在浏览器环境中运行,也可以在 node.js 环境下运行

mocha 主要特点有:

  • 既可以测试简单的 JavaScript 函数,又可以测试异步代码
  • 可以自动运行所有测试,也可以只运行特定的测试
  • 可以支持 before、after、beforeEach 和 afterEach 来编写初始化代码

安装依赖

npm install mocha@8.4.0 --save-dev

准备测试脚本

在 test 目录下,新建脚本 VotingTest.js

const assert = require('assert');
const path = require('path');
const ganache = require('ganache-cli');
const Web3 = require('web3');

const web3 = new Web3(ganache.provider());

const contractDir = path.resolve(__dirname, '../compiled', 'Voting.json');
const {interface, bytecode} = require(contractDir);
let contract;
let accounts;
let arguments = [[web3.utils.fromAscii('Alice'),web3.utils.fromAscii('Bob'),web3.utils.fromAscii('Cary')]]
let gas = 5000000;



describe('#contract',()=>{
	before(()=>{
		console.log('test start')
	})
	
	after(()=>{
		console.log('test end')
	})
	
	afterEach(()=>{
		console.log('current test completed')
	})
	
	// beforeEach:使每一次测试的环境都是干净的, 每次合约执行前都执行
	beforeEach(async()=>{
		accounts = await web3.eth.getAccounts();
		contract = await new web3.eth.Contract(JSON.parse(interface))
					.deploy({
						data:bytecode,
						arguments:arguments
					})
					.send({
						from:accounts[0],
						gas:gas
					})
		console.log('current test start')
	});
	
	it('deployed contract successfully',()=>{
		assert.ok(contract.options.address);
	})
	it('should be able to check the number of votes',async()=>{
		let aVoter = web3.utils.fromAscii('Alice');
		assert.ok(contract.methods.totalVotesFor(aVoter).call({from:accounts[0]}));
	})
	it('should be able to vote',async()=>{
		let voteTo = web3.utils.fromAscii('Bob')
		let BeforeNumOfVote = parseInt(await contract.methods.totalVotesFor(voteTo).call({from:accounts[0]}));
		await contract.methods.vote(voteTo).send({from:accounts[0]});
		let AfterNumOfVote = parseInt(await contract.methods.totalVotesFor(voteTo).call({from:accounts[0]}));
		assert.equal(BeforeNumOfVote + 1,AfterNumOfVote);
	})
})

执行测试脚本

在 test 目录下执行,以下命令

../node_modules/mocha/bin/mocha VotingTest.js

测试例子

?测试脚本

在 test?下创建 sum.js 和 testSum.js

执行测试脚本?

在 contract_workflow 目录下,执行以下命令?

mocha 会自动寻找目录下叫 test 的文件夹,并执行其中 所有的 js 文件

./node_modules/mocha/bin/mocha

在 test 目录下,执行以下命令

测试特定的? js 文件 或 文件夹

../node_modules/mocha/bin/mocha testSum.js


将以上工作流步骤串起来

?参考链接:

npm scripts 使用指南 - 阮一峰的网络日志https://www.ruanyifeng.com/blog/2016/10/npm_scripts.html

修改 package.json??

我们可以通过 npm script 机制,将这些智能合约的工作流串起来

修改 package.json 如下图

?./node_modules/mocha/bin/ 可以省略 ,因为npm scripts 在执行是将./node_modules/中的包暂时加入了环境变量中

  "scripts": {
    "compile": "node scripts/compile.js",
    "predeploy": "npm run compile",
    "deploy": "node scripts/deploy.js",
    "pretest": "npm run compile",
    "test": "mocha test/"
  },

?执行命令

npm run test

  区块链 最新文章
盘点具备盈利潜力的几大加密板块,以及潜在
阅读笔记|让区块空间成为商品,打造Web3云
区块链1.0-比特币的数据结构
Team Finance被黑分析|黑客自建Token“瞒天
区块链≠绿色?波卡或成 Web3“生态环保”标
期货从入门到高深之手动交易系列D1课
以太坊基础---区块验证
进入以太坊合并的五个数字
经典同态加密算法Paillier解读 - 原理、实现
IPFS/Filecoin学习知识科普(四)
上一篇文章      下一篇文章      查看所有文章
加:2022-03-24 00:37:21  更:2022-03-24 00:37:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:23:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码