react + ethers.js 简单demo

1,106 阅读2分钟

使用到的技术栈和工具

源码地址:github.com/luopeihai/e…

项目环境构建

  1. create-react-app 创建react项目 npx create-react-app ethers-example

  2. Hardhat 配置项目区块链开发环境 安装hardhat 依赖包npm install --save-dev hardhat
    配置启动hardhat的script并执行该指令

// package.json
scripts:{
    "start:hardhat": "hardhat node"
}

运行 hardhat node 后生成文件:

  • hardhat.config.jshard配置文件
  • deploy.js部署智能契约文件
  • Lock.sol智能契约
  • Lock.js Lock.sol ut

再次运行npm run start:hardhat 启动 hardhat 服务并列出测试账号,拿到Private Key 导入Metamask账号

image.png

  1. ethers.js 引入和链接Metamask钱包 首先 npm install ethers --save 我安装的是 ethers.js v6的版本

链接 Metamask钱包

通过 ethers.js 链接 Metamask

// app.js
import { ethers } from "ethers";
import "./App.css";

function App() {
  const connect = async () => {
    let signer = null;
    let provider;

    if (window.ethereum == null) {
      console.log("MetaMask not installed; using read-only defaults");
      provider = ethers.getDefaultProvider();
    } else {
      provider = new ethers.BrowserProvider(window.ethereum);
      signer = await provider.getSigner();
    }
    // 当前访问人address
    const addr = await signer.getAddress();
    console.log("addr", addr);
  };

  return (
    <div className="App">
      <p>
        <button onClick={connect}>connect wallet</button>
      </p>
    </div>
  );
}

export default App;

点击 “connect wallet” 链接钱包,授权成功后 控制台将打印出当前访问用户的address

调用Lock.sol智能合约

在Lock.sol添加 成员message 和 事件SetMessage代码

// contracts/Lock.sol

    string public message = "hello world";
    event SetMessage(string new_msg);

    function setMessage(string memory _msg)external{
        message = _msg;
        emit SetMessage(_msg);
    }

修改完契约后需要依次执行compiledeploy操作, 先把对应script配置上

 // package.json
 script:{
   ...
   "build:hardhat": "hardhat compile",
   "deploy:hardhat": "hardhat run ./scripts/deploy.js --network localhost"
 }
 

依次执行指令
npm run build:hardhat 生成编译文件artifacts , cache
npm run deploy:hardhat 将生成智能契约 address

image.png

app.js 中引入 compile 后的 Lock.json

// app.js

import Lock from "../artifacts/contracts/Lock.sol/Lock.json";

react server将报错,

Module not found: Error: You attempted to import ../artifacts/contracts/Lock.sol/Lock.json which falls outside of the project src/ directory. Relative imports outside of src/ are not supported.
You can either move it inside src/, or add a symlink to it from project's node_modules/.

报错原因是 create-app-react 有效代码需要在 src目录下,那就设置hardhat.config.js编译后的文件导出到src/下,修改配置如下:

// hardhat.config.js

require("@nomicfoundation/hardhat-toolbox");

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
  solidity: "0.8.19",
  paths: {
    artifacts: "./src/artifacts",
  },
};

保存修改,再次npm run build:hardhat npm run deploy:hardhat,运行成功后 src 中将多出契约编译后文件artifacts

app.js 中引入编译后的契约json信息

// app.js

import Lock from "./artifacts/contracts/Lock.sol/Lock.json";

添加 readMessage读取Lock.sol中的成员messagesetMessage触发Lock.sol中 SetMessage事件

// app.js

 const readMessage = async () => {
    const provider = new ethers.BrowserProvider(window.ethereum);
    
    const lock = new ethers.Contract(
      YOUR_DEPLOY_ADDRESS, 
      Lock.abi,
      provider
    );
    const message = await lock.message();
    alert(message);
  };

  const setMessage = async () => {
    const provider = new ethers.BrowserProvider(window.ethereum);
    const signer = await provider.getSigner();
    let lock = new ethers.Contract(
      YOUR_DEPLOY_ADDRESS,
      Lock.abi,
      signer
    );
    let transaction = await lock
      .connect(signer)
      .setMessage("world hello!");
    let result = await transaction.wait();
    alert(result.logs[0].args);
  };
  

YOUR_DEPLOY_ADDRESS 为 npm run deploy:hardhat 发布成功后显示的 Lock.sol address

点击 readMessage按钮将alert “hello world”

点击 setMessage ,由于该方法为写入操作需要支付 “燃料”,所以Metamask 将提示确认

image.png

点击“确认”后将alert “hello world”