Skip to content

加法器

Sepolia 网络上部署加法器合约,在前端 Dapp 页面上点击 Add 即向合约里的 counter + 1

操作步骤:

  1. 部署合约
  2. 创建 vue 工程
  3. 引入 Web3.js 依赖
  4. 前端连接区块链网络
    1. 连接钱包
    2. 与合约交互

技术准备

Nodejs v18.16.0Web3.js 1.8.0Vue 3

合约部分

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Counter {
    uint256 public count = 0;

    function add() public {
        count += 1;
    }
}

作者已部署到 Sepolia 网络

bash
https://sepolia.etherscan.io/address/0x2383507348bfcce28ea9293a4ae3cd6cdfafd11f

合约地址 0x2383507348BfCce28ea9293A4AE3cD6cDfaFd11F

创建 vue 工程

bash
npm init vue@latest

src/App.vue 替换为

vue
<template></template>

<script></script>

引入 Web3.js 依赖

vue 项目根目录下输入

bash
npm i web3@1.8.0

前端连接区块链网络

与合约交互分为 两类。如果只是简单读取合约信息,则可以直接读取;如果是要修改合约上的数据(本例中的 counter + 1),则需要支付 gas,本质上这是 发送交易,因此需要先连接钱包

1. 连接钱包

首先检查游览器是否安装 metamask,如果未安装则弹出警告,如果已安装则连接钱包

vue
<script>
import Web3 from "web3";

export default {
  data() {
    return {
      account: null,  // 用于存储连接的钱包地址
      web3: null,     // 用于存储Web3实例
    };
  },
  methods: {
    async connectWallet() {
      if (typeof window.ethereum !== 'undefined' || (typeof window.web3 !== 'undefined')) {
        // 使用MetaMask的Ethereum提供商
        this.web3 = new Web3(window.ethereum || window.web3.currentProvider);

        try {
          // 请求连接钱包
          const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
          this.account = accounts[0];  // 保存连接的账户
        } catch (error) {
          console.error("用户拒绝了连接请求");
        }
      } else {
        alert("请安装MetaMask钱包!");
      }
    }
  }
};
</script>

2. 与合约交互

通过合约 abi 已经合约 address 构造合约对象,进而与合约进行交互

  1. 获取 counter 的值

    js
    async getCounter() {
        this.counter = await this.contract.methods.count().call()
    },
  2. Add 逻辑

    js
    async add() {
        try {
        let res = await this.contract.methods.add().send({
            from: this.account,
        });
        await this.getCounter();  // 交易完成后更新计数
        this.hash = res.transactionHash
        } catch (error) {
        console.error('Transaction failed:', error);
        }
    }

完整代码 src/App.vue

vue
<template>
  <h1>当前值: {{ counter }}</h1>
  <br>
  <h2>钱包地址: {{ account ? account : '请先连接钱包' }}</h2>
  <br><br>
  <button @click="connectWallet">连接钱包</button>

  <button @click="add">Add {{ hash ? hash : '' }}</button>
</template>

<script>
import Web3 from "web3";

export default {
  data() {
    return {
      account: null,  // 用于存储连接的钱包地址
      web3: null,     // 用于存储Web3实例
      contract: null,
      counter: '请先连接钱包',     // 计数器值
      hash: null    // 交易哈希
    };
  },
  methods: {
    // 获取 counter 值
    async getCounter() {
      this.counter = await this.contract.methods.count().call()
    },
    // 连接钱包
    async connectWallet() {
      if (typeof window.ethereum !== 'undefined' || (typeof window.web3 !== 'undefined')) {
        // 使用MetaMask的Ethereum提供商
        this.web3 = new Web3(window.ethereum || window.web3.currentProvider);

        try {
          // 请求连接钱包
          const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
          this.account = accounts[0];  // 保存连接的账户
        } catch (error) {
          console.error("用户拒绝了连接请求")
          return;
        }
      } else {
        alert("请安装MetaMask钱包!");
        return
      }

      // 钱包连接成功后,构造合约对象
      // 合约 abi
      let abi = [
        {
          "inputs": [],
          "name": "add",
          "outputs": [],
          "stateMutability": "nonpayable",
          "type": "function"
        },
        {
          "inputs": [],
          "name": "count",
          "outputs": [
            {
              "internalType": "uint256",
              "name": "",
              "type": "uint256"
            }
          ],
          "stateMutability": "view",
          "type": "function"
        }
      ]
      // 合约地址
      let address = '0x2383507348BfCce28ea9293A4AE3cD6cDfaFd11F'

      this.contract = new this.web3.eth.Contract(abi, address);
      this.getCounter()
    },
    // Add 按钮
    async add() {
      try {
        let res = await this.contract.methods.add().send({
          from: this.account,
        });
        await this.getCounter();  // 交易完成后更新计数
        this.hash = res.transactionHash
      } catch (error) {
        console.error('Transaction failed:', error);
      }
    }
  }
};
</script>