上一篇我们讲到使用以太坊官方的web3.js第三方工具和以太坊的truffle框架,使用nodejs express框架实现对以太坊智能合约方法的调用。在这篇文章中,我们将学习使用以太坊的另一个第三方工具ethers和以太坊的hardhat框架来编译和部署合约,并实现对以太坊智能合约方法的调用。我们还是以前面提到的ERC20合约为例。
1. 首先我们创建一个基本的目录结构,选择创建一个javascript项目。
npx安全帽
2.将我们的合约放在contracts目录下,合约名称为MyToken.sol。
3.配置hardhat.config.js文件
require(\'@nomicfoundation/hardhat-toolbox\');
const fs=require(\'fs\');
const privateKey=fs.readFileSync(\'.secret\').toString().trim();
模块.exports={
defaultNetwork: \'goerli\', //指定哪个网络
网络: {
goerli: {
url:\'https://goerli.infura.io/v3/9df29b35c83d4e4c87a8cde2034794f1\',
accounts: [私钥],
}
},
solidity: {
version:\'0.8.0\',
设置: {
优化器: {
enabled: 真,
运行: 200
}
}
},
paths: {
sources: \'./contracts\',
tests: \'./test\',
cache: \'./cache\',
artifacts: \'./artifacts\'
},
mocha: {
超时: 40000
}
};
4.编写部署合约文件scripts/deploy.js
const hre=require(\'安全帽\');
异步函数main() {
const MyToken=await hre.乙醚。 getContractFactory(\'MyToken\');
常量myToken=等待MyToken。部署(\'第一个令牌\',\'FT\');
等待我的令牌。部署();
console.log(\'MyToken部署到:\', myToken.address);
}
//我们推荐这种模式,以便能够在任何地方使用async/await
//并正确处理错误。
main().catch((错误)={
安慰。错误(错误);
process.exitCode=1;
});
5.添加依赖package.json
{
\'名称\':\'安全帽项目\',
\'依赖\' : {
\'@nomicfoundation/hardhat-toolbox\' : \'^2.0.2\',
\'@openzeppelin/contracts\' : \'^4.8.3\',
\'
;bignumber.js": "^9.1.1",
"hardhat": "^2.14.0"
},
"devDependencies": {
"body-parser": "^1.20.2",
"chai": "^4.3.7",
"ethereumjs-tx": "^2.1.2",
"ethers": "^6.3.0",
"express": "^4.18.2",
"fs": "^0.0.1-security",
"web3": "^1.9.0"
}
}
const {expect} = require("chai");
const {ethers} = require("hardhat");
describe("Test MyToken", function () {
it("Should return the same name and same symbol", async function () {
const myToken = await ethers.getContractFactory("MyToken");
const mt = await myToken.deploy("FIRST-TOKEN","FT");
await mt.deployed();
// name
expect(await mt.name()).to.equal("FIRST-TOKEN");
console.log("name true!");
// symbol
expect(await mt.symbol()).to.equal("FT");
console.log("symbol true!");
});
});
7.配置好上面的代码后,我们安装依赖,之后再依次编译,部署,测试
npm install
npx hardhat compile
npx hardhat run ./scripts/deploy.js --network goerli
npx hardhat test
此时项目目录为
MyToken
- contracts
- MyToken.sol
- scripts
- deploy.js
- test
- MyToken.t.js
- hardhat.config.js
- package.json
- cache
- ...
- artifacts
- ...
- .secret
上面,我们完成了对代码的编译部署以及测试,接下来,我们使用ethers来调用合约的接口。在上面的代码目录基础上,我们再往下添加目录代码。
我们首先将编译后在artifacts/contracts/MyToken.sol/MyToken.json里的abi文件复制粘贴到我们新建的abis/abi文件中。如下:
abis/abi
[
{
"inputs": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
...
...
...
"stateMutability": "nonpayable",
"type": "function"
}
]
其次,我们编写调用合约的接口文件apis/api.js
const ethers = require('ethers');
const fs = require('fs');
const Tx = require("ethereumjs-tx");// 这个版本一定要1.3.7
const BigNumber = require("bignumber.js");
const abi = JSON.parse(fs.readFileSync("./abis/abi"));
const provider = new ethers.getDefaultProvider('https://goerli.infura.io/v3/9df29b35c83d4e4c87a8cde2034794f1');
const privateKey = fs.readFileSync(".secret").toString().trim();
const wallet = new ethers.Wallet(privateKey, provider);
const ContractAddr = '0xE15d4d98543a2C8847BeFeFB332fe91459B0eC83';
const contract = new ethers.Contract(ContractAddr, abi, provider);
const contractWithSigner = contract.connect(wallet);
module.exports = {
name: async (req, res) => {
let result = await contractWithSigner.name();
console.log("name:" + result + "\\n");
// 发送响应数据
res.send({
"msg": "ok",
"name": result,
});
},
// 查询token数量剩余多少
balanceOf: async (req, res) => {
const owner = "0xF8600a900fF30c76807C155bf6B07ba5BE8190A7";
let result = await contractWithSigner.balanceOf(owner);
console.log("balanceOf:" + result + "\\n");
const bal = new BigNumber(result);
// 发送响应数据
res.json({
"msg": "ok",
"balanceOf": bal.toFixed(),
});
},
}
最后,我们编写路由文件routers/router.js
const express = require('express');
const app = new express();
const call = require('../apis/api');
const router = express.Router();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extend: false}));
app.use(bodyParser.json());
app.use(router);
router.get('/name', call.name);
router.get('/balanceOf', call.balanceOf);
app.listen(7070, '127.0.0.1', () => console.log("正在监听端口"));
最终,项目的目录长这样
MyToken
- abis
- abi
- apis
- api.js
- routers
- router.js
- contracts
- MyToken.sol
- scripts
- deploy.js
- test
- MyToken.t.js
- hardhat.config.js
- package.json
- cache
- artifacts
- .secret
所有代码完成后,我们运行 node ./routers/router.js 就可以访问我们的合约接口了。
至此,关于ethers调用和合约接口,以及使用hardhat编译部署合约到以太坊的测试网络,我们就讲完了。下一节,带着大家使用go语言来调用我们的以太坊合约接口。我们下一期再见!