Q7 · 前端与链交互
Ethers.js 几大核心模块分别做什么?
⚡ 速记答案(30 秒)
- Provider:连接区块链节点(RPC),读链上数据
- Signer / Wallet:持有私钥,可发交易、签名消息
- Contract:前端与合约交互的封装(读写函数、监听事件)
- Utils:格式转换、单位转换(
parseEther/formatUnits等) - ABI / Interface:解析合约 ABI,编码/解码数据
- Errors:统一错误类型和错误消息
📖 详细讲解
Ethers.js v6 架构
1. Provider - 只读连接
Provider 用于连接区块链节点,只能读取数据,不能发送交易。
2. Signer - 签名者
Signer 是 Provider 的扩展,持有私钥可以签名交易。常见类型:
• Wallet:使用私钥/助记词
• JsonRpcSigner:通过 MetaMask 等注入
3. Contract - 合约交互
Contract 是与智能合约交互的抽象层,自动编码/解码调用数据。
面试要点
• Provider 和 Signer 的区别
• v5 到 v6 的 API 变化
• 如何处理大数(BigInt)
💻 代码示例
Provider 使用示例
import { ethers } from 'ethers';
// 1. 创建 Provider(连接到 RPC)
const provider = new ethers.JsonRpcProvider('https://eth.llamarpc.com');
// 2. 读取链上数据
const blockNumber = await provider.getBlockNumber();
const balance = await provider.getBalance('vitalik.eth');
const gasPrice = await provider.getFeeData();
console.log('当前区块:', blockNumber);
console.log('余额:', ethers.formatEther(balance), 'ETH');Contract 交互示例
import { ethers } from 'ethers';
// ERC20 合约 ABI(仅需用到的方法)
const ERC20_ABI = [
'function balanceOf(address) view returns (uint256)',
'function transfer(address to, uint256 amount) returns (bool)',
'event Transfer(address indexed from, address indexed to, uint256 value)',
];
// 创建合约实例
const usdtAddress = '0xdAC17F958D2ee523a2206206994597C13D831ec7';
const contract = new ethers.Contract(usdtAddress, ERC20_ABI, provider);
// 读取余额(只读操作)
const balance = await contract.balanceOf('0x...');
// 发送交易(需要 Signer)
const contractWithSigner = contract.connect(signer);
const tx = await contractWithSigner.transfer('0x...', 1000000n);
await tx.wait();面试技巧:回答时先给出核心结论,再展开细节。如果有实际项目经验,一定要结合具体案例说明。