如何轻松对接以太坊钱包(MetaMask/Trust Wallet等)
在区块链应用(如DeFi、NFT、DApp)开发中,对接以太坊钱包是连接用户与去中心化世界的核心环节,无论是让用户管理数字资产、签名交易,还是与智能合约交互,都需要通过钱包完成,本文将以MetaMask(最主流的浏览器钱包)和Trust Wallet(移动端钱包)
如何轻松对接以太坊钱包(MetaMask/Trust Wallet等)
在区块链应用(如DeFi、NFT、DApp)开发中,对接以太坊钱包是连接用户与去中心化世界的核心环节,无论是让用户管理数字资产、签名交易,还是与智能合约交互,都需要通过钱包完成,本文将以MetaMask(最主流的浏览器钱包)和Trust Wallet(移动端钱包)
在对接前,需先明确几个关键概念:
以太坊钱包(如MetaMask)并非存储“币”,而是存储私钥的助记词/私钥,通过私钥管理链上地址的资产与签名权限,用户通过钱包与以太坊网络交互时,实际是通过钱包软件构造交易、用私钥签名,再广播到节点。
viem(新一代以太坊交互库,兼容钱包连接)、web3-onboard(多钱包连接解决方案),简化与钱包的连接流程。 以React/Vue项目为例,先初始化项目并安装必要的库:
cd dapp-wallet-demo # 安装ethers.js(或web3.js) npm install ethers
MetaMask通过window.ethereum向浏览器注入全局对象,可通过以下方式检测:
// 在React组件中
const checkWalletInstalled = () => {
if (typeof window.ethereum !== 'undefined') {
console.log('MetaMask已安装!');
return true;
} else {
console.log('请先安装MetaMask:https://metamask.io/');
return false;
}
};
连接钱包的核心是调用window.ethereum.request({ method: 'eth_requestAccounts' }),该方法会触发MetaMask的账户选择弹窗,用户授权后返回地址列表。
import { ethers } from 'ethers';
const connectWallet = async () => {
if (!window.ethereum) {
alert('请安装MetaMask!');
return;
}
try {
// 请求用户授权连接账户
const accounts = await window.ethereum.request({
method: 'eth_requestAccounts',
});
const address = accounts[0];
console.log('已连接钱包地址:', address);
// 创建provider(连接以太坊节点)
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner(); // 获取签名者(用于发送交易)
// 获取用户余额(示例)
const balance = await provider.getBalance(address);
console.log('余额:', ethers.formatEther(balance), 'ETH');
return { address, signer, provider };
} catch (error) {
console.error('连接失败:', error);
alert('连接钱包失败,请重试');
}
};
用户可能切换账户或网络(如从主网切到测试网),需监听事件并更新UI:
// 监听账户变化
window.ethereum.on('accountsChanged', (accounts) => {
if (accounts.length === 0) {
console.log('用户已断开钱包连接');
} else {
console.log('切换账户:', accounts[0]);
// 更新UI中的地址信息
}
});
// 监听网络变化
window.ethereum.on('chainChanged', (chainId) => {
console.log('切换网络:', chainId);
// 提示用户刷新页面或重新连接
alert('网络已切换,请刷新页面');
});
连接钱包后,用户可能需要发送ETH或与智能合约交互:
const sendETH = async (toAddress, amount) => {
if (!signer) {
alert('请先连接钱包!');
return;
}
try {
const tx = await signer.sendTransaction({
to: toAddress,
value: ethers.parseEther(amount), // 转换为wei(1 ETH = 1e18 wei)
});
console.log('交易哈希:', tx.hash);
await tx.wait(); // 等待交易上链
alert('交易成功!');
} catch (error) {
console.error('交易失败:', error);
alert('交易失败,请检查余额和网络');
}
};
const contractAddress = '0x...'; // 合约地址
const contractABI = [...]; // 合约ABI
const getContractBalance = async (userAddress) => {
const contract = new ethers.Contract(contractAddress, contractABI, provider);
const balance = await contract.balanceOf(userAddress);
console.log('代币余额:', ethers.formatUnits(balance, 18));
};
若需同时支持MetaMask(浏览器)和Trust Wallet(移动端),可通过web3-onboard库简化实现:
npm install @web3-onboard/core @web3-onboard/injected-wallets
import initOnboard from '@web3-onboard/core';
import injectedModule from '@web3-onboard/injected-wallets';
const injected = injectedModule();
const onboard = initOnboard({
wallets: [injected],
chains: [
{
id: '0xaa36a7', // Sepolia测试网ChainID
token: 'sepETH',
label: 'Sepolia Testnet',
rpcUrl: 'https://sepolia.infura.io/v3/YOUR_INFURA_ID',
},
],
});
// 连接钱包
const connectWallet = async () => {
const wallets = await onboard.connectWallet();
const state = onboard.getState();
const address = state.wallets[0].accounts[0].address;
console.log('连接地址:', address);
};
window.ethereum不存在时,引导用户到官网下载钱包(如MetaMask、Trust Wallet)。 provider.getBalance()确认ETH余额是否足够支付gas费。 provider.getFeeData()获取当前建议的gas价格(如maxPriorityFeePerGas)。 window.ethereum连接,与MetaMask逻辑一致。 trust://协议唤起Trust Wallet(需用户已安装)。 web3-onboard或ethers.js中配置不同链的RPC地址(如BSC的https://bsc-dataseed.binance.org)。