Web3钱包:钱包集成与签名验证
大家好,我是欧阳瑞(Rich Own)。今天想和大家聊聊Web3钱包这个重要话题。作为一个全栈/Web3开发者,钱包集成是DApp开发的核心功能。今天就来分享一下钱包集成和签名验证的实战经验。
Web3钱包概述
常见钱包
| 钱包 | 说明 | 类型 |
|---|---|---|
| MetaMask | 浏览器插件钱包 | 热钱包 |
| WalletConnect | 跨平台钱包协议 | 协议 |
| Coinbase Wallet | Coinbase官方钱包 | 热钱包 |
| Ledger | 硬件钱包 | 冷钱包 |
核心功能
连接钱包 → 获取用户地址
签名交易 → 授权转账
签名消息 → 身份验证
监听事件 → 账户/网络变化
MetaMask集成
基础连接
javascript
async function connectWallet() {
if (window.ethereum) {
try {
const accounts = await window.ethereum.request({
method: 'eth_requestAccounts'
});
return accounts[0];
} catch (error) {
console.error('连接失败:', error);
throw error;
}
} else {
throw new Error('请安装MetaMask');
}
}
获取账户信息
javascript
async function getAccountInfo() {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const address = await signer.getAddress();
const balance = await provider.getBalance(address);
const chainId = await provider.getNetwork().then(net => net.chainId);
return {
address,
balance: ethers.utils.formatEther(balance),
chainId
};
}
监听变化
javascript
// 监听账户变化
window.ethereum.on('accountsChanged', (accounts) => {
if (accounts.length === 0) {
console.log('账户已断开');
} else {
console.log('账户已切换:', accounts[0]);
}
});
// 监听网络变化
window.ethereum.on('chainChanged', (chainId) => {
console.log('网络已切换:', chainId);
window.location.reload();
});
WalletConnect集成
初始化连接
javascript
import WalletConnect from '@walletconnect/client';
import QRCodeModal from '@walletconnect/qrcode-modal';
const connector = new WalletConnect({
bridge: 'https://bridge.walletconnect.org',
qrcodeModal: QRCodeModal
});
async function connectWithWalletConnect() {
if (!connector.connected) {
await connector.createSession();
}
connector.on('connect', (error, payload) => {
if (error) {
throw error;
}
const { accounts, chainId } = payload.params[0];
console.log('已连接:', accounts[0]);
});
connector.on('disconnect', (error, payload) => {
console.log('已断开连接');
});
}
签名验证
签名消息
javascript
async function signMessage(message) {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const signature = await signer.signMessage(message);
return signature;
}
验证签名
javascript
function verifySignature(message, signature, address) {
const signer = ethers.utils.verifyMessage(message, signature);
return signer === address;
}
登录示例
javascript
async function login() {
const nonce = generateNonce();
localStorage.setItem('nonce', nonce);
const message = `欢迎登录!\n\nNonce: ${nonce}`;
const signature = await signMessage(message);
// 发送到后端验证
const response = await fetch('/api/login', {
method: 'POST',
body: JSON.stringify({
address: await getAddress(),
signature,
nonce
})
});
return response.json();
}
实战案例:DApp钱包集成
javascript
class WalletService {
constructor() {
this.provider = null;
this.signer = null;
this.address = null;
this.chainId = null;
}
async connect() {
if (!window.ethereum) {
throw new Error('请安装Web3钱包');
}
this.provider = new ethers.providers.Web3Provider(window.ethereum);
const accounts = await this.provider.send('eth_requestAccounts', []);
this.address = accounts[0];
this.signer = this.provider.getSigner();
this.chainId = await this.provider.getNetwork().then(net => net.chainId);
this.setupListeners();
return this.address;
}
setupListeners() {
window.ethereum.on('accountsChanged', (accounts) => {
if (accounts.length > 0) {
this.address = accounts[0];
this.signer = this.provider.getSigner();
}
});
window.ethereum.on('chainChanged', () => {
window.location.reload();
});
}
async getBalance() {
if (!this.provider || !this.address) {
throw new Error('请先连接钱包');
}
const balance = await this.provider.getBalance(this.address);
return ethers.utils.formatEther(balance);
}
async sendTransaction(to, amount) {
if (!this.signer) {
throw new Error('请先连接钱包');
}
const tx = await this.signer.sendTransaction({
to,
value: ethers.utils.parseEther(amount)
});
return tx.hash;
}
}
// 使用
const wallet = new WalletService();
await wallet.connect();
console.log('地址:', wallet.address);
console.log('余额:', await wallet.getBalance());
最佳实践
1. 多钱包支持
javascript
// 支持多种钱包
const wallets = {
metamask: connectMetaMask,
walletconnect: connectWalletConnect,
coinbase: connectCoinbase
};
2. 错误处理
javascript
try {
await connectWallet();
} catch (error) {
if (error.code === 4001) {
// 用户拒绝连接
console.log('用户拒绝连接');
} else {
console.error('连接失败:', error);
}
}
总结
Web3钱包集成是DApp开发的基础。通过正确的钱包连接、签名验证和事件监听,可以提供良好的用户体验。
我的鬃狮蜥Hash对钱包也有自己的理解------它总是安全地保护自己的领地,这也许就是自然界的"钱包"吧!
如果你对Web3钱包集成有任何问题,欢迎留言交流!我是欧阳瑞,极客之路,永无止境!
技术栈:Web3钱包 · MetaMask · WalletConnect