Appearance
加法器
在 Sepolia
网络上部署加法器合约,在前端 Dapp
页面上点击 Add
即向合约里的 counter + 1
操作步骤:
- 部署合约
- 创建
vue
工程 - 引入
Web3.js
依赖 - 前端连接区块链网络
- 连接钱包
- 与合约交互
技术准备
Nodejs v18.16.0 | Web3.js 1.8.0 | Vue 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
构造合约对象,进而与合约进行交互
获取
counter
的值jsasync getCounter() { this.counter = await this.contract.methods.count().call() },
Add
逻辑jsasync 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>