前言本文主要用Ethers.jsv5在一篇文章里讲透「钱包全链路」:连接→授权→转账→检测→交易记录→账号列表。所有代码片段可直接拷进项目跑通。补充:使用ganache作为测试账号,通过创建自定义网络的导入账号;以web端为主准备工作注册个Ganache账号用来
本文主要用 Ethers.js v5 在一篇文章里讲透「钱包全链路」:连接 → 授权 → 转账 → 检测 → 交易记录 → 账号列表。所有代码片段可直接拷进项目跑通。补充:使用ganache作为测试账号,通过创建自定义网络的导入账号;以web端为主
<!---->
启动终端指令 cmd
ganache//返回链id rpc链接 和10个账号的公钥和私钥 助记词等
ganache返回值汇总
字段 | 值 |
---|---|
网络名称 | Ganache Local |
RPC URL | <http://127.0.0.1:8545> |
链 ID | 1337 |
货币符号 | ETH |
区块浏览器 URL | (可不填) |
安装个metamask浏览器插件,用来导入测试账号和dapp交互使用
<!---->
# 插件安装完毕,已经注册了metamask账号
# 点击设置选择网络
# 点击 添加自定义网络
# 弹出面板,分别填写 网络名称、RPCURL、链ID、货币符号、区块浏览器url(可填、可部填),这些信息获取可以通过ganache返回值中获取 .
<!---->
# 包安装
npx expo install ethers
npx expo install @ethersproject/shims
npx expo install react-native-get-random-values
_layout.tsx
)顶部 第一行 引入 shims<!---->
import '@ethersproject/shims';
import 'react-native-get-random-values';
ethers
<!---->
import { ethers } from 'ethers';
# 链接钱包
const onConnectWalletFunction=async ()=>{
// 1. 判断 MetaMask
if (!window.ethereum) {
alert('请先安装 MetaMask');
return null;
}
// 2. 创建 Provider
const provider = new ethers.providers.Web3Provider(window.ethereum);
// 3. 唤起授权
await provider.send('eth_requestAccounts', []);
let addressList=await provider.listAccounts()
console.log(addressList);
// 4. 获取签名器 & 地址
const signer = await provider.getSigner();
const address = await signer.getAddress();
// 5. 查余额(wei → ETH)
const balanceWei = await provider.getBalance(address);
const balanceEth = ethers.utils.formatEther(balanceWei);
//使用zustand 存储钱包的信息:例如 地址 余额交易信息等等
setAddress(address);//zustand 定义的方法
setBalance(balanceEth);//zustand 定义的方法
setAddressBookList([...addressList]);//联系人 钱包列表
}
# 断开钱包
# 断开钱包需要手动断开,组件知识清除存储的信息
const disconnectFn=()=>{
setBalance("")
setWellatAddress("")
useWallet.persist.clearStorage();//zustand清空数据
}
说明:主要自定义网络
只能通过扫描log日志来实现交易记录整理,(不是最优解
),如果是测试链(mainnet)可以通过(new ethers.providers.EtherscanProvider
)来实现更加优雅
<!---->
const provider = new ethers.providers.EtherscanProvider('mainnet', YOUR_KEY);
const history = await provider.getHistory(address, 0, 'latest');
console.log(history.slice(-100));
<!---->
# 说明通过扫描日志log来获取信息,整理交易信息
const hostlistFn= async ()=>{
const TARGET_ADDR = address.toLowerCase();
const provider = new ethers.providers.JsonRpcProvider('http://localhost:8545');//ganache rpcurl
const latest = await provider.getBlockNumber();//获取区块
const list: any[] = [];
console.log(`开始扫描 0 → ${latest} 区块...`);
for (let i = 0; i <= latest; i++) {
const block = await provider.getBlockWithTransactions(i);
console.log(block)
for (const tx of block.transactions) {
if (
tx.from.toLowerCase() === TARGET_ADDR ||
(tx.to && tx.to.toLowerCase() === TARGET_ADDR)
) {
list.push({
hash: tx.hash,
from: tx.from,
to: tx.to,
value: ethers.utils.formatEther(tx.value),
block: tx.blockNumber,
timestamp: new Date(block.timestamp * 1000).toLocaleString(),
});
}
}
}
return list;
}
hostlistFn()
.then(txs => {
console.log(`共 ${txs.length} 笔转账`);
console.table(txs);
})
.catch(console.error);
# 核心代码
window.ethereum.on('accountsChanged',async (accounts: string[]) => {
if (accounts.length === 0) {
// 用户断开所有账户
setAddress(null);
} else {
//可以进行后续的操作
}
})
const onSend=async()=>{
// 1. 拿到浏览器注入的 provider
const provider = new ethers.providers.Web3Provider(window.ethereum);
// 2. 让用户授权并拿到 signer
await provider.send("eth_requestAccounts", []);
const signer = await provider.getSigner();
// 3. 构造交易
const tx = await signer.sendTransaction({
to: Recipient, // 接收地址
value: ethers.utils.parseEther(Amount), // 0.01 ETH → wei
// gasLimit、maxFeePerGas 可省略,MetaMask 会自动估算
});
// 4. 等待确认
const receipt = await tx.wait();
console.log("交易已确认,哈希:", receipt); // 成功
if(receipt.status==1){
//成功后进行后续操作
}else{
alert("交易失败");
}
}
# 创建 Provider
const provider = new ethers.providers.Web3Provider(window.ethereum);
# 授权
await provider.send('eth_requestAccounts', []);
# 获取账号列表
let addressList=await provider.listAccounts()
<div style="display:flex; gap:8px;flex-wrap:wrap;">
<img src="https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/cf834dbf6d0b476386d94b71be6a0fb2~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5pyo6KW_:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjQzNjE3MzQ5Njg0NTU0OSJ9&rk3s=e9ecf3d6&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1756125869&x-orig-sign=dvROBVnziTu6UUa%2FFD8Pf4mDYIk%3D" alt="图1" width="200">
<img src="https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/9232714519244a7fad0ebcd8f65815e0~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5pyo6KW_:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjQzNjE3MzQ5Njg0NTU0OSJ9&rk3s=e9ecf3d6&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1756125913&x-orig-sign=EE7TLQn4RN9s3hVeMYA0cPLLJUI%3D" alt="图1转存失败,建议直接上传图片文件" width="200">
<img src="https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/6eee1733f3af4adda8e200c0d3647021~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5pyo6KW_:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjQzNjE3MzQ5Njg0NTU0OSJ9&rk3s=e9ecf3d6&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1756126192&x-orig-sign=%2FP6R6vFEbKH2gQXT74Z%2FI2BwRZY%3D" alt="图1转存失败,建议直接上传图片文件" width="200">
<img src="https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/c195ab0a6a2d44ad9c3c128f9ca884d8~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5pyo6KW_:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjQzNjE3MzQ5Njg0NTU0OSJ9&rk3s=e9ecf3d6&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1756126234&x-orig-sign=xVwBudV9x6xXzJtFDG0LZ3s7NxU%3D" alt="图1转存失败,建议直接上传图片文件" width="200">
<img src="https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/389c4f830a5d4769a48046ff6e58aa9a~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5pyo6KW_:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjQzNjE3MzQ5Njg0NTU0OSJ9&rk3s=e9ecf3d6&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1756126273&x-orig-sign=VqUqCvxyDXLvJdIGC0%2F2S9rj9LQ%3D" alt="图1转存失败,建议直接上传图片文件" width="200">
<img src="https://p0-xtjj-private.juejin.cn/tos-cn-i-73owjymdk6/7110b79ce73748bea7635680ba0faf40~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5pyo6KW_:q75.awebp?policy=eyJ2bSI6MywidWlkIjoiMjQzNjE3MzQ5Njg0NTU0OSJ9&rk3s=e9ecf3d6&x-orig-authkey=f32326d3454f2ac7e96d3d06cdbb035152127018&x-orig-expires=1756126082&x-orig-sign=hI79yzHKqn6apmkPkHvFNbze10Y%3D" alt="图1转存失败,建议直接上传图片文件" width="200">
</div>
至此,「钱包全链路」完整闭环:
连接 → 授权 → 转账 → 余额 → 交易记录 → 账号列表 → 监听 → 断开。
所有代码可直接落地项目;如需支持移动端 React-Native,把 window.ethereum
换成 WalletConnect 即可
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!