使用ethers.js执行读函数与写函数

Posted sanqima

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用ethers.js执行读函数与写函数相关的知识,希望对你有一定的参考价值。

    ethers.js是一个简洁的以太坊操作库,使用它非常方便的执行读函数、写函数。下面介绍使用ethers.js执行CountOne.sol里的读写函数。

1、CountOne.sol智能合约

    // CountOne.sol

// SPDX-License-Identifier: MIT
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')

//use rinkeby
let network = getNetWork("4") 
let provider = new ethers.providers.JsonRpcProvider(network)


function getNetWork(netId) 
    let infuraKey = fs.readFileSync(".infuraKey").toString().trim();

    //default network is rinkeby
    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,更新成功。

以上是关于使用ethers.js执行读函数与写函数的主要内容,如果未能解决你的问题,请参考以下文章

我如何将 eth 值发送到在 ethers.js 中支付的特定智能合约功能?

ethers计算函数选择器与事件选择器

在视图/只读区块链函数上调用 ethers web3js 时出现气体限制错误

Ethers.js,向智能合约汇款(接收功能)

ReentrantReadWriteLock场景应用

js写在head与写在body有什么区别