? ? ethers.js是一个简洁的以太坊操作库,使用它非常方便的执行读函数、写函数。下面介绍使用ethers.js执行CountOne.sol里的读写函数。
1、CountOne.sol智能合约
? ? // CountOne.sol
pragma solidity ^0.6.0;
contract CountOne {
uint public count;
address public owner;
constructor() public {
count = 0;
owner = msg.sender;
}
function getCount() public view returns(uint) {
return count;
}
function increaseCount() public {
require(count + 1 > count,"add is overflow");
count = count + 1;
}
function decreaseCount() public {
require(count >= 1,"sub is overflow");
count = count - 1;
}
function clearCount() public onlyOwner {
count = 0;
}
modifier onlyOwner() {
require(owner == msg.sender,"info: caller is not owner");
_;
}
}
? ? 使用Remix将这个合约部署到Rinkeby测试网,然后编写JS测试脚本,通过contract.count()函数读取值,contract.increaseCount()函数更新值。 ? ? Remix合约部署请参考这篇文章
2、创建测试工程ethersDemo
2.1 创建文件夹并初始化
## 创建工程并初始化
mkdri ethersDemo
cd ethersDemo
npm init -y
truffle init
## 创建2个文件
touch .infuraKey
touch .secret
2.2 修改package.json文件
? ? 修改好的package.json文件如下:
{
"name": "ethersDemo",
"version": "1.0.0",
"description": "",
"main": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@truffle/hdwallet-provider": "^1.7.0",
"web3": "^1.6.1",
"@ethereumjs/tx": "^3.4.0",
"ethers": "^5.5.1"
},
"devDependencies": {
"@babel/core": "^7.12.3",
"@babel/preset-env": "^7.12.1"
}
}
2.3 安装依赖包
npm install
2.4 修改solidity的版本
? ? 在truffle-config.js文件里,将solidity的版本修改为0.6.6,并开启development字段,如下:
networks: {
development: {
host: "127.0.0.1", // Localhost (default: none)
port: 8545, // Standard Ethereum port
network_id: "*", // Any network (default: none)
},
compilers: {
solc: {
version: "0.6.6",
}
}
2.5 启动ganache
? ? 在ganache里设置IP为127.0.0.1,端口为8545,重启ganache
2.6 拷贝合约
? ? 将第1章的CountOne.sol拷贝到ethersDemo/contracts目录下
3 编译合约,并导出abi
3.1 使用truffle编译合约
cd ethersDemo
truffle console
compile
3.2 导出abi
? ? 在build/contracts目录下,找到CountOne.json,找到abi:字段,在[ 坐标,按Ctrl+Shift+→ 快捷键,即可拷贝整个abi,具体请看这篇文章[json压缩成一行],将其保存到ethersDemo/myabi/countOne_abi.json文件里。
? ? //countOne_abi.json
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"count","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"increaseCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decreaseCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clearCount","outputs":[],"stateMutability":"nonpayable","type":"function"}]
4、设置infuraKey和私钥
? ? a) 在 infura.io里创建一个工程,在【设置】页面,就得到Project ID,这个Project ID就是infuraKey,如图(2)所示,把它拷贝到ethersDemo/.infuraKey文件里;
图(2) 在infura.io里获取Project ID
? ? b) 点击MEtaMask --> 选中某个Account ----> 详情 —> 导出私钥,将其拷贝ethersDemo/.secret文件里
5、工程目录结构
? ? 整个工程目录结构如下:
图(1) ethersDemo的目录结构
6、执行读写函数
6.1 编写测试脚本
? ? 在ethersDemo/test目录,创建一个脚本: 1.getCount.js
cd ethersDmeo
touch 1.getCount.js
? ? //1.getCount.js
const {ethers} = require("ethers")
const fs = require('fs')
let network = getNetWork("4")
let provider = new ethers.providers.JsonRpcProvider(network)
function getNetWork(netId) {
let infuraKey = fs.readFileSync(".infuraKey").toString().trim();
let net = 'https://rinkeby.infura.io/v3/'+infuraKey
if (netId == "4") {
return net
}
switch (netId) {
case "1":
net = 'https://mainnet.infura.io/v3/'+infuraKey;
break;
case "3":
net = 'https://ropsten.infura.io/v3/'+infuraKey;
break;
case "5":
net = 'https://goerli.infura.io/v3/'+infuraKey;
break;
case "42":
net = 'https://kovan.infura.io/v3/'+infuraKey;
break;
}
return net;
}
function getString(prikeyPath) {
const privKeyFile = fs.readFileSync(prikeyPath).toString().trim();
const privKey = '0x' + new Buffer.from(privKeyFile);
return privKey
}
async function preGetValue(contract) {
let value = await contract.count()
let valone = ethers.BigNumber.from(value).toNumber()
console.log("curValue=",valone)
}
async function preSetValue(contract) {
let tx = await contract.increaseCount()
console.log('tx=',tx.hash)
await tx.wait()
}
async function doValue(){
var privKey = getString(".secret")
let wallet = new ethers.Wallet(privKey,provider)
var contractAddr = '0x2F70e8A246350ED1fD7b798F7CeDFdc4E645123D'
var jsonStr = fs.readFileSync('./myabi/countOne_abi.json')
var jsonAbi = JSON.parse(jsonStr)
let contract = new ethers.Contract(contractAddr,jsonAbi,wallet)
await preGetValue(contract)
await preSetValue(contract)
await preGetValue(contract)
}
doValue()
6.2 执行脚本
node test/1.getCount.js
? ? 效果如下:
? ? count值从3变成4,更新成功。
|