智能合约编译、部署、调用

〇、准备工作

安装node.js

安装solc

安装web3.js

安装mocha

启动私链或公网区块链节点

创建文件目录

......
mkdir	contract_workflow
cd contract_workflow
mkdir contracts		#存放智能合约.sol文件
mkdir compiled		#存放编译后的json文件
mkdir scripts			#存放脚本js文件
mkdir tests				#存放测试调用脚本js文件

一、智能合约开发

通过solidity语言,实现一份简单的智能合约.sol文件,示例:

pragma solidity ^0.4.22;

contract Car{
    
    string public brand;
    
    constructor(string _brand) public {
        brand = _brand;
    }
    
    function setBrand(string _brand)public {
        brand = _brand;
    }  
}

二、智能合约编译

源代码通过编译成字节码(Bytecode),同时会产生二进制接口规范(ABI);另外编译能够处理编译时抛出的错误,确保不会在包含错误的源代码上进行编译。

const fs = require('fs-extra');//fs-extra替换fs,目的是把编译结果保存在文件系统中
const solc = require('solc');
const path = require('path');

//改进2:每次编译前清空
const compiledPath = path.resolve(__dirname,'../compiled');
fs.removeSync(compiledPath);//同步移除目录
fs.ensureDirSync(compiledPath);//确保文件存在,不存在则新建

//对合约进行编译
const contractPath = path.resolve(__dirname,'../contracts','Car.sol');//解析路径
const contractSource = fs.readFileSync(contractPath,'utf-8');//从路径中读取合约源码
let compileResult = solc.compile(contractSource,1);//solc编译器同步编译,1表示打开solc中的优化器

// console.log(compileResult);//打印编译结果

//改进3:编译阶段处理异常
if(Array.isArray(compileResult.errors) && compileResult.errors.length){
	throw new Error(compiledResult.errors[0]);
}

//改进1:把编译结果保存在文件系统中
Object.keys(compileResult.contracts).forEach(name=>{//contracts中每个元素提出来
	let contractName = name.replace(/^:/,'');
	let filePath = path.resolve(__dirname,'../compiled',`${contractName}.json`);
	fs.outputJsonSync(filePath,compileResult.contracts[name]);//fs-extra中方法
	console.log("saving json file to ",filePath);
})

执行脚本成功后,会在对应目录生成Car.json文件。

node ./scripts/compile.js

compiled目录下会生成Car.json

三、部署智能合约

通过交易将字节码部署到以太坊网络,部署成功会产生一个智能合约账户,示例是部署在私链节点上

//1.0.0
const Web3 = require('web3');
const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
const path = require('path');

//1.拿到abi和bytecode
const filePath = path.resolve(__dirname,'../compiled/Car.json');
//{interface,bytecode}名称与文件内一致,不可自定义
const {interface,bytecode} = require(filePath);

(async () => {
	//2.获取钱包里的账户
	let accounts = await web3.eth.getAccounts();
	console.log('部署合约的账户:',accounts[0]);
	// console.time('deploy time');

	//3.创建合约实例并部署
	let result = await new web3.eth.Contract(JSON.parse(interface))//创建新合约
						.deploy({data: bytecode,arguments: ['BMW']})//部署操作-交易对象
						.send({from: accounts[0],gas: 5000000});
	// console.timeEnd('deploy time');					
	console.log("contract_address: ",result.options.address);					
})();


执行脚本

node ./scripts/deploy.js

四、调用测试合约

通过web3.js+ABI去调用智能合约中的函数来实现数据的读取和修改。

//mocha测试框架
const path = require('path');
const Web3 = require('web3');
const assert = require('assert');
const ganache = require('ganache-cli');

//1.配置provider
const web3 = new Web3(ganache.provider());

//2.拿到abi和bytecode
const contractPath = path.resolve(__dirname,'../compiled/Car.json');
const {interface,bytecode} = require(contractPath);

let accounts;
let contract;
const initBrand = 'BMW';

describe('contract',()=>{
	before(()=>{
		console.log('测试开始');
	});
	//3.每次跑单测时需要部署全新的合约实例,起到隔离的作用
	beforeEach(async()=>{//异步测试,保证顺序
		accounts = await web3.eth.getAccounts();
		contract = await new web3.eth.Contract(JSON.parse(interface))
					.deploy({data: bytecode,arguments: [initBrand]})//部署操作-交易对象
					.send({from: accounts[0],gas: 5000000});
		console.log('合约已部署');			
	});
	after(()=>{
		console.log('测试结束');
	});
	afterEach(()=>{
		console.log('当前测试完成');
	});
	it('deployed contract successfully',()=>{
		assert.ok(contract.options.address);
	});
	it('should has a initial brand',async()=>{
		let brand = await contract.methods.brand().call();
		assert.equal(brand,initBrand);
	});
	it('should set a new brand',async()=>{
		const newBrand = 'Audi';
		await contract.methods.setBrand(newBrand)
			.send({from: accounts[0]});
		let brand = await contract.methods.brand().call();
		assert.equal(brand,newBrand);	
	});

});

执行脚本

node ./tests/car.js
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值