审核看清楚了 ! 这是以太坊测试网络!用于学习的测试网络!!! 有关web3 和区块链的内容为什么要给我审核不通过? 别人凭什么可以发!
目标成果:
实现功能分析:
- 显示账户信息,地址、chainID、网络ID、余额
- 实现转账功能
需要准备的事情:
- 一个有sepolia ETH余额的web3账户,没有可以找水龙头领取或者某鱼购买
- 浏览器插件安装了 MetaMask钱包插件(小狐狸钱包)
- 准备一个web容器,我这边使用的是nginx
操作环节:
先写出网页大概的内容布局;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>js连接web3钱包</title>
</head>
<body>
<div>
<div><h3>详情信息</h3></div>
<div>
<div>
<label>账户地址:<span></span></label>
</div>
<div>
<label>ChainID:<span></span></label>
</div>
<div>
<label>网络ID:<span></span></label>
</div>
<div>
<label>余额:<span></span></label>
</div>
</div>
<div>
<button>转账</button>
</div>
</div>
<div>
<label>对手地址<input type="text"></label>
<br>
<label>ETH数量<input type="text"></label>
<br>
<button>确定</button>
<button>取消</button>
</div>
</body>
</html>
接下来是写js部分
把大概的框架都写出来:
//判断浏览器是否具备MetaMask环境
const initialize = async ()=>{
if(!isMetaMaskInstalled()){
//如果没安装弹出窗口
alert("请先安装 MetaMask");
}else{
await getNetwork(); //获取网络
await getChainId(); //获取链
await getAccount(); //获取账户地址
await getBalance(); //获取余额
}
}
在上面这个initialize()方法中,里面我们调用了5个方法,每个方法都有其各自的作用.
方法 | 作用 |
---|---|
isMetaMaskInstalled() | 用来判断浏览器是否安装了MetaMask钱包 |
getNetwork() | 获取网络号 |
getChainId() | 获取链ID |
getAccount() | 获取账户地址 |
getBalance() | 获取账户余额 |
现在开始着手写这几个方法
- 判断是否安装
const isMetaMaskInstalled = () => {
const { ethereum } = window;
return Boolean(ethereum && ethereum.isMetaMask);
}
- 获取网络号然然后渲染到html页面上
html部分要要加上 对应的id进行innerHTML
<div>
<label>账户地址:<span id="accountSpan"></span></label>
</div>
<div>
<label>ChainID:<span id="ChainIdSpan"></span></label>
</div>
<div>
<label>网络ID:<span id="NetworkSpan"></span></label>
</div>
<div>
<label>余额:<span id="BalanceSpan"></span></label>
</div>
js部分
const getNetwork = async () => {
try {
const networkId = await ethereum.request({ method: 'net_version' });
NetworkSpan.innerHTML = networkId;
} catch (error) {
console.error(error);
}
}
const getChainId = async () => {
try {
const chainId = await ethereum.request({ method: 'eth_chainId' });
ChainIdSpan.innerHTML = chainId;
} catch (error) {
console.error(error);
}
}
const getAccount = async () => {
try {
const accounts = await ethereum.request({ method: 'eth_requestAccounts' });//调用这个方法会弹出MetaMask的一个授权窗口
accountSpan.innerHTML = accounts[0]; // 显示连接第一个账户
} catch (error) {
console.error(error);
}
}
const getBalance = async () => {
const accounts = await ethereum.request({ method: 'eth_requestAccounts' });
const balance = await ethereum.request({
method: 'eth_getBalance',
params: [accounts[0], 'latest']
});
userBalance = parseInt(balance, 16);
const ethBalance = Web3.utils.fromWei(balance, 'ether');//这里要引入一个web3.js文件
BalanceSpan.innerHTML = `${ethBalance} ETH`;
}
window.addEventListener('DOMContentLoaded', initialize);//进入网页后自动调用initialize方法,不调用就无法查询和渲染页面
还要引入一个web3.js用于单位转换(其实我们也可以自己计算)
<script src="https://cdn.jsdelivr.net/npm/web3@1.6.0/dist/web3.min.js"></script>
现在已经完成显示账户信息的功能了!
接下来我们要实现我们的转账功能.,代码如下(还没有美化的版本)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>js连接web3钱包</title>
<style>
#transferModal {
display: none;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: white;
padding: 20px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
}
</style>
</head>
<body>
<div>
<div><h3>详情信息</h3></div>
<div>
<div>
<label>账户地址:<span id="accountSpan"></span></label>
</div>
<div>
<label>ChainID:<span id="ChainIdSpan"></span></label>
</div>
<div>
<label>网络ID:<span id="NetworkSpan"></span></label>
</div>
<div>
<label>余额:<span id="BalanceSpan"></span></label>
</div>
</div>
<div>
<button id="sendButton">转账</button>
</div>
</div>
<div id="transferModal">
<label>对手地址<input type="text" id="recipientAddress"></label>
<br>
<label>ETH数量<input type="text" id="ethAmount" required min="0" step="0.0001"></label>
<br>
<button id="confirmTransferButton" type="submit">确定</button>
<button id="cancelTransferButton">取消</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/web3@1.6.0/dist/web3.min.js"></script>
<script>
//判断浏览器是否具备MetaMask环境
const initialize = async () => {
if (!isMetaMaskInstalled()) {
//如果没安装弹出窗口
alert("请先安装 MetaMask");
} else {
await getNetwork(); //获取网络
await getChainId(); //获取链
await getAccount(); //获取账户地址
await getBalance(); //获取余额
}
}
//判断是否安装
const isMetaMaskInstalled = () => {
const { ethereum } = window;
return Boolean(ethereum && ethereum.isMetaMask);
}
const getNetwork = async () => {
try {
const networkId = await ethereum.request({ method: 'net_version' });
NetworkSpan.innerHTML = networkId;
} catch (error) {
console.error(error);
}
}
const getChainId = async () => {
try {
const chainId = await ethereum.request({ method: 'eth_chainId' });
ChainIdSpan.innerHTML = chainId;
} catch (error) {
console.error(error);
}
}
const getAccount = async () => {
try {
const accounts = await ethereum.request({ method: 'eth_requestAccounts' });//调用这个方法会弹出MetaMask的一个授权窗口
accountSpan.innerHTML = accounts[0]; // 显示连接第一个账户
} catch (error) {
console.error(error);
}
}
const getBalance = async () => {
const accounts = await ethereum.request({ method: 'eth_requestAccounts' });
const balance = await ethereum.request({
method: 'eth_getBalance',
params: [accounts[0], 'latest']
});
userBalance = parseInt(balance, 16);
const ethBalance = Web3.utils.fromWei(balance, 'ether');//这里要引入一个web3.js文件
BalanceSpan.innerHTML = `${ethBalance} ETH`;
}
//获取最新的gas prices
const getGasPrice = async () => {
const web3 = new Web3(Web3.givenProvider);
const gasPrice = await web3.eth.getGasPrice();
console.log('Current gas prices => ' + gasPrice);
return gasPrice;
}
// 显示和隐藏转账模态窗口
const sendButton = document.getElementById('sendButton');
const transferModal = document.getElementById('transferModal');
const confirmTransferButton = document.getElementById('confirmTransferButton');
const cancelTransferButton = document.getElementById('cancelTransferButton');
sendButton.addEventListener('click', () => {
transferModal.style.display = 'block';
});
cancelTransferButton.addEventListener('click', () => {
transferModal.style.display = 'none';
});
// 处理转账逻辑
confirmTransferButton.addEventListener('click', async () => {
const recipientAddress = document.getElementById('recipientAddress').value;
const ethAmount = document.getElementById('ethAmount').value;
if (!recipientAddress || !ethAmount) {
alert('请填写所有字段');
return;
}
try {
const web3 = new Web3(Web3.givenProvider);
const accounts = await ethereum.request({ method: 'eth_requestAccounts' });
const senderAddress = accounts[0];
const transactionParameters = {
to: recipientAddress,
from: senderAddress,
value: web3.utils.toHex(web3.utils.toWei(ethAmount, 'ether')),
gasPrice: await getGasPrice(),
gas: '21000', // 默认的gas limit
};
await ethereum.request({
method: 'eth_sendTransaction',
params: [transactionParameters],
});
alert('转账成功');
transferModal.style.display = 'none';
await getBalance(); // 更新余额
} catch (error) {
console.error(error);
alert('转账失败');
}
});
// 切换账户的时候触发
ethereum.on('accountsChanged', function (accounts) {
console.log('账户已切换');
window.location.reload();
});
// 切换网络的时候触发
ethereum.on('chainChanged', function (accounts) {
console.log('网络已切换');
window.location.reload();
});
window.addEventListener('DOMContentLoaded', initialize);
</script>
</body>
</html>
结果:
这样就可以完成转账功能了!
美化 二选一 bootstrap or layui.
- 使用bootstrap 美化一下
code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Web3 钱包</title>
<link rel="icon" href="http://u5a.cn/uftiP" type="image/x-icon"></link>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.6.0/css/brands.min.css" rel="stylesheet">
<style>
body {
background-color: #f8f9fa;
}
.wallet-info {
margin-top: 20px;
}
.wallet-info label {
font-weight: bold;
}
.wallet-info span {
font-style: italic;
}
.navbar-brand {
font-weight: bold;
}
.copy-icon {
cursor: pointer;
margin-left: 10px;
color: #007bff;
}
.copy-icon:hover {
color: #0056b3;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-sm navbar-light bg-light">
<div class="container-fluid">
<span class="navbar-brand">币圈老韭菜</span>
</div>
</nav>
<div class="container wallet-info">
<div>
<h3>详情信息</h3>
</div>
<div>
<div class="row">
<div class="col-md-6 mb-3">
<label>账户地址:</label>
<span id="accountSpan"></span>
<i class="fas fa-copy copy-icon" onclick="copyAddress()"></i>
</div>
<div class="col-md-6 mb-3">
<label>Chain:</label>
<span id="NetworkSpan"></span>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label>链ID:</label>
<span id="ChainIdSpan"></span>
</div>
<div class="col-md-6 mb-3">
<label>余额:</label>
<span id="BalanceSpan"></span>
</div>
</div>
</div>
<div>
<button class="btn btn-primary" id="sendButton">转账</button>
</div>
</div>
<!-- 转账表单模态框 -->
<div class="modal fade" id="transferModal" tabindex="-1" aria-labelledby="transferModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="transferModalLabel">转账</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="transferForm">
<div class="mb-3">
<label for="recipientAddress" class="form-label">转账地址</label>
<input type="text" class="form-control" id="recipientAddress" required>
</div>
<div class="mb-3">
<label for="ethAmount" class="form-label">ETH 数量</label>
<input type="number" class="form-control" id="ethAmount" required min="0" step="0.0001">
</div>
<button type="submit" class="btn btn-primary">确定转账</button>
</form>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/web3@1.6.0/dist/web3.min.js"></script>
<script>
let userBalance = 0;
// 初始化
const initialize = () => {
checkMetaMaskClient();
}
// 如果安装了小狐狸才可以获取信息
const checkMetaMaskClient = async () => {
if (!isMetaMaskInstalled()) {
alert("请安装 MetaMask");
} else {
await getNetworkAndChainId(); // 获取网络ID
await getAccount(); // 使用 eth_requestAccounts 获取账户
await getBalance(); // 使用 eth_getBalance 获取余额
}
}
// 验证是不是安装了
const isMetaMaskInstalled = () => {
const { ethereum } = window;
return Boolean(ethereum && ethereum.isMetaMask);
}
const getAccount = async () => {
try {
const accounts = await ethereum.request({ method: 'eth_requestAccounts' });
accountSpan.innerHTML = accounts[0]; // 显示第一个账户
} catch (error) {
console.error(error);
}
}
const getNetworkAndChainId = async () => {
try {
const chainId = await ethereum.request({ method: 'eth_chainId' });
ChainIdSpan.innerHTML = chainId;
const networkId = await ethereum.request({ method: 'net_version' });
NetworkSpan.innerHTML = networkId;
} catch (error) {
console.error(error);
}
}
const getBalance = async () => {
const accounts = await ethereum.request({ method: 'eth_requestAccounts' });
const balance = await ethereum.request({
method: 'eth_getBalance',
params: [accounts[0], 'latest']
});
userBalance = parseInt(balance, 16);
const ethBalance = Web3.utils.fromWei(balance, 'ether');
BalanceSpan.innerHTML = `${ethBalance} ETH`;
}
const getGasPrice = async () => {
const web3 = new Web3(Web3.givenProvider);
const gasPrice = await web3.eth.getGasPrice();
console.log('Current gas prices =>'+gasPrice);
return gasPrice;
}
// 事件触发
// 点击转账按钮的时候触发
document.getElementById('sendButton').onclick = () => {
// 打开模态框
new bootstrap.Modal(document.getElementById('transferModal')).show();
}
// 提交转账表单
document.getElementById('transferForm').onsubmit = async (e) => {
e.preventDefault();
const recipientAddress = document.getElementById('recipientAddress').value;
const ethAmount = parseFloat(document.getElementById('ethAmount').value);
const weiAmount = Web3.utils.toWei(ethAmount.toString(), 'ether');
if (weiAmount <= 0) {
alert('ETH 数量必须大于 0');
return;
}
if (weiAmount > userBalance) {
alert('余额不足');
return;
}
const gasPrice = await getGasPrice();
const accounts = await ethereum.request({ method: 'eth_requestAccounts' });
const params = [{
from: accounts[0],
to: recipientAddress,
value: Web3.utils.toHex(weiAmount),
gas: '0x5208', // 21000 gas 的十六进制
gasPrice: Web3.utils.toHex(gasPrice), // 当前网络 gas price
}];
try {
await ethereum.request({
method: 'eth_sendTransaction',
params: params,
});
alert('转账成功');
} catch (error) {
console.error(error);
alert('转账失败');
}
}
// 一键复制地址功能
const copyAddress = () => {
const address = document.getElementById('accountSpan').textContent;
navigator.clipboard.writeText(address).then(() => {
alert('地址已复制');
}).catch(err => {
console.error('无法复制地址', err);
});
}
// 切换账户的时候触发
ethereum.on('accountsChanged', function (accounts) {
console.log('账户已切换');
window.location.reload();
});
// 切换网络的时候触发
ethereum.on('chainChanged', function (accounts) {
console.log('网络已切换');
window.location.reload();
});
window.addEventListener('DOMContentLoaded', initialize);
</script>
<script src="https://cdn.staticfile.net/popper.js/2.11.8/umd/popper.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.3.3/js/bootstrap.min.js"></script>
<script src="https://cdn.staticfile.net/font-awesome/6.5.1/js/all.min.js"></script>
</body>
</html>
- 使用layui美化的效果 (感觉做的还是太丑了)
code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>js连接web3钱包</title>
<link rel="stylesheet" href="https://cdn.staticfile.net/layui/2.9.4/css/layui.min.css" rel="stylesheet">
<style>
body {
font-size: 16px;
}
.layui-container {
margin-top: 20px;
}
.layui-col-md4 {
padding: 10px 0;
}
#transferModal {
display: none;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: white;
padding: 20px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
font-size: 16px;
}
.layui-form-label {
width: 100px;
}
</style>
</head>
<body>
<div class="layui-container">
<div><h3>详情信息</h3></div>
<div class="layui-row layui-col-space10">
<div class="layui-col-md6">
<label>账户地址:<span id="accountSpan" class="layui-badge"></span></label>
</div>
<div class="layui-col-md6">
<label>ChainID:<span id="ChainIdSpan" class="layui-badge layui-bg-blue"></span></label>
</div>
<div class="layui-col-md6">
<label>网络ID:<span id="NetworkSpan" class="layui-badge layui-bg-green"></span></label>
</div>
<div class="layui-col-md6">
<label>余额:<span id="BalanceSpan" class="layui-badge layui-bg-orange"></span></label>
</div>
</div>
<div>
<button id="sendButton" class="layui-btn layui-btn-normal">转账</button>
</div>
</div>
<div id="transferModal" class="layui-card">
<div class="layui-card-header">转账</div>
<div class="layui-card-body">
<div class="layui-form-item">
<label class="layui-form-label">对手地址</label>
<div class="layui-input-block">
<input type="text" id="recipientAddress" class="layui-input" required>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">ETH数量</label>
<div class="layui-input-block">
<input type="text" id="ethAmount" class="layui-input" required min="0" step="0.0001">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button id="confirmTransferButton" class="layui-btn" type="submit">确定</button>
<button id="cancelTransferButton" class="layui-btn layui-btn-primary">取消</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.staticfile.net/layui/2.9.4/layui.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/web3@1.6.0/dist/web3.min.js"></script>
<script>
layui.use(['layer', 'form'], function(){
const layer = layui.layer;
const form = layui.form;
//判断浏览器是否具备MetaMask环境
const initialize = async () => {
if (!isMetaMaskInstalled()) {
//如果没安装弹出窗口
layer.alert("请先安装 MetaMask");
} else {
await getNetwork(); //获取网络
await getChainId(); //获取链
await getAccount(); //获取账户地址
await getBalance(); //获取余额
}
}
//判断是否安装
const isMetaMaskInstalled = () => {
const { ethereum } = window;
return Boolean(ethereum && ethereum.isMetaMask);
}
const getNetwork = async () => {
try {
const networkId = await ethereum.request({ method: 'net_version' });
NetworkSpan.innerHTML = networkId;
} catch (error) {
console.error(error);
}
}
const getChainId = async () => {
try {
const chainId = await ethereum.request({ method: 'eth_chainId' });
ChainIdSpan.innerHTML = chainId;
} catch (error) {
console.error(error);
}
}
const getAccount = async () => {
try {
const accounts = await ethereum.request({ method: 'eth_requestAccounts' });//调用这个方法会弹出MetaMask的一个授权窗口
accountSpan.innerHTML = accounts[0]; // 显示连接第一个账户
} catch (error) {
console.error(error);
}
}
const getBalance = async () => {
const accounts = await ethereum.request({ method: 'eth_requestAccounts' });
const balance = await ethereum.request({
method: 'eth_getBalance',
params: [accounts[0], 'latest']
});
userBalance = parseInt(balance, 16);
const ethBalance = Web3.utils.fromWei(balance, 'ether');//这里要引入一个web3.js文件
BalanceSpan.innerHTML = `${ethBalance} ETH`;
}
//获取最新的gas prices
const getGasPrice = async () => {
const web3 = new Web3(Web3.givenProvider);
const gasPrice = await web3.eth.getGasPrice();
console.log('Current gas prices => ' + gasPrice);
return gasPrice;
}
// 显示和隐藏转账模态窗口
const sendButton = document.getElementById('sendButton');
const transferModal = document.getElementById('transferModal');
const confirmTransferButton = document.getElementById('confirmTransferButton');
const cancelTransferButton = document.getElementById('cancelTransferButton');
sendButton.addEventListener('click', () => {
transferModal.style.display = 'block';
});
cancelTransferButton.addEventListener('click', () => {
transferModal.style.display = 'none';
});
// 处理转账逻辑
confirmTransferButton.addEventListener('click', async () => {
const recipientAddress = document.getElementById('recipientAddress').value;
const ethAmount = document.getElementById('ethAmount').value;
if (!recipientAddress || !ethAmount) {
layer.alert('请填写所有字段');
return;
}
try {
const web3 = new Web3(Web3.givenProvider);
const accounts = await ethereum.request({ method: 'eth_requestAccounts' });
const senderAddress = accounts[0];
const transactionParameters = {
to: recipientAddress,
from: senderAddress,
value: web3.utils.toHex(web3.utils.toWei(ethAmount, 'ether')),
gasPrice: await getGasPrice(),
gas: '21000', // 默认的gas limit
};
await ethereum.request({
method: 'eth_sendTransaction',
params: [transactionParameters],
});
layer.alert('转账成功');
transferModal.style.display = 'none';
await getBalance(); // 更新余额
} catch (error) {
console.error(error);
layer.alert('转账失败');
}
});
// 切换账户的时候触发
ethereum.on('accountsChanged', function (accounts) {
console.log('账户已切换');
window.location.reload();
});
// 切换网络的时候触发
ethereum.on('chainChanged', function (accounts) {
console.log('网络已切换');
window.location.reload();
});
window.addEventListener('DOMContentLoaded', initialize);
});
</script>
</body>
</html>
展望:
后续还会添加切换账户\网络\加入代币\选择转账的币种\转账的历史记录
小结:
关于gas
- Gas Price(Gas 价格):
- 表示为 gwei(1 gwei = 10^-9 ETH),wei是以太坊的最小单位。
- 用户可以设定他们愿意支付的 gas 价格。Gas 价格越高,交易被矿工处理的速度可能越快,因为矿工更倾向于处理 gas 价格较高的交易以获得更多的报酬。
- Gas Limit(Gas 限额):
- 用户愿意为一个特定交易支付的最大 gas 数量。
- 防止意外消耗过多的 gas 资源。
- Transaction Fee(交易费用):
- 计算方式:
Gas Price * Gas Used
。 - 例如,如果 gas 价格是 20 gwei,并且交易消耗了 21,000 gas,那么交易费用将是
20 gwei * 21,000 = 420,000 gwei
,大约等于0.00042 ETH
。
- 计算方式:
Gas 的作用
- 防止滥用:
- 每个操作都需要支付 gas,防止用户随意发起大量计算资源消耗的操作,确保网络的安全性和稳定性。
- 奖励矿工:
- 矿工通过处理交易获得 gas 费用作为奖励,激励他们维护网络。
- 确保执行:
- 确保用户为执行智能合约或其他操作付费,智能合约的复杂度越高,所需的 gas 就越多。
功能描述
1. MetaMask 环境检测
- 功能:检查浏览器是否安装了 MetaMask 插件。
- 实现:通过
isMetaMaskInstalled
函数检测ethereum
对象及其isMetaMask
属性。
2. 获取网络信息
- 功能:获取并显示当前网络的 Network ID 和 Chain ID。
- 实现:通过调用 MetaMask 提供的
ethereum.request({ method: 'net_version' })
和ethereum.request({ method: 'eth_chainId' })
获取 Network ID 和 Chain ID。
3. 获取账户信息
- 功能:获取并显示连接的以太坊账户地址。
- 实现:通过调用 MetaMask 提供的
ethereum.request({ method: 'eth_requestAccounts' })
获取账户地址,并显示在页面上。
4. 获取账户余额
- 功能:获取并显示当前账户的 ETH 余额。
- 实现:通过调用 MetaMask 提供的
ethereum.request({ method: 'eth_getBalance', params: [accounts[0], 'latest'] })
获取余额,并转换为 ETH 后显示在页面上。
5. 转账功能
- 功能:用户可以通过输入对手地址和 ETH 数量来进行转账操作。
- 实现:
- 提供一个按钮用于显示转账模态窗口。
- 模态窗口中有输入框用于输入对手地址和转账数量。
- 点击确定按钮后,调用 MetaMask 提供的
ethereum.request({ method: 'eth_sendTransaction', params: [transactionParameters] })
完成转账。
6. 实时更新
- 功能:当账户或网络发生变化时,页面会自动刷新。
- 实现:通过
ethereum.on('accountsChanged')
和ethereum.on('chainChanged')
事件监听账户和网络变化,并刷新页面以更新显示的信息。