在区块链开发领域web3.js 和 ethers.js 是连接 JavaScript 应用与 EVM 兼容区块链如以太坊的两大核心工具库二者均封装了与区块链节点交互的复杂逻辑让开发者无需深入底层协议就能轻松实现钱包对接、链上数据查询、智能合约交互等核心功能。本文将从零基础入门逐步深入到进阶实战同时覆盖 web3.js 和 ethers.js 两大工具带你系统掌握 Web3 前端开发核心技能从新手成长为合格的区块链开发者。本文适配 web3.js v4 版本、ethers.js v6 版本均为当前最新稳定版结合 2026 年区块链开发主流场景同步更新兼容性技巧与最佳实践全程搭配可直接运行的代码示例兼顾理论与实操无论是前端开发者转型 Web3还是零基础入门区块链都能快速上手。一、入门读懂两大核心库web3.js ethers.js1.1 核心定位与区别web3.js 和 ethers.js 均为 JavaScript/TypeScript 开源库核心作用是实现前端与 EVM 兼容区块链的交互但二者在设计理念、体积、生态适配等方面存在差异适配不同开发场景对比维度web3.jsethers.js核心定位功能全面模块化设计适配各类 EVM 链开发轻量高效API 简洁专注以太坊生态React 生态适配更友好体积完整包体积较大约 150KB按需导入可缩小体积体积小巧约 40KB默认支持 tree-shaking加载速度更快生态适配兼容所有 EVM 链社区成熟文档全面以太坊生态首选与 wagmi、RainbowKit 等工具无缝集成上手难度API 较多新手入门稍慢功能更全面API 简洁直观新手入门更快核心功能无冗余适用场景多链开发、复杂合约交互、需要丰富内置工具的场景以太坊单链开发、React 前端 DApp、追求轻量高效的场景补充说明2026 年开发中ethers.js 在 React 生态中占比更高而 web3.js 因多链适配优势在跨链 DApp 开发中更具优势建议两者都掌握根据项目需求灵活选择。1.2 什么是 ethers.jsethers.js 是一套轻量级、高效的 JavaScript/TypeScript 库用于与以太坊及 EVM 兼容区块链交互由 Richard Moore 开发维护核心特点是“轻量、简洁、安全”。与 web3.js 相比ethers.js 更专注于以太坊生态API 设计更简洁避免了冗余功能同时原生支持 TypeScript对前端开发者更友好。核心定位与 web3.js 一样ethers.js 也是“翻译官”将 JavaScript 代码转化为区块链节点可识别的指令但更注重轻量化和开发体验尤其适合前端 DApp 开发。1.3 核心前置知识与 web3.js 通用学习 ethers.js 与 web3.js 前置知识一致无需额外补充掌握以下基础概念即可- 区块链基础去中心化、不可篡改的分布式账本节点维护、区块链式存储等核心特性。- 以太坊生态账户EOA 外部账户、合约账户、智能合约、Gas 费、ABI、RPC 节点。- 钱包基础私钥/助记词、公钥/地址、数字签名MetaMask 钱包使用。- JavaScript 基础ES6 语法、Promise/async-await、模块化Node.js 与 npm 包管理。1.4 ethers.js v6 核心特性2026 重点ethers.js v6 是当前最新稳定版相比旧版本和 web3.js核心特性如下- 轻量高效体积仅为 web3.js 的 1/3 左右加载速度快支持 tree-shaking按需打包。- API 简洁简化了合约交互、交易发送等核心操作的 API新手更容易上手。- 原生 TypeScript 支持提供完整的类型定义减少开发中的类型错误提升可维护性。- 内置安全机制自动处理 BigInt 大整数避免精度丢失私钥管理更安全支持硬件钱包。- 生态适配性强与 React、Vue 等前端框架无缝兼容尤其适配 wagmi、RainbowKit 等 Web3 UI 工具。- 兼容 EIP-1193 标准可与 MetaMask 等钱包无缝集成简化钱包对接流程。二、入门实操两大库环境搭建同步对比本部分同步讲解 web3.js 和 ethers.js 的环境搭建步骤清晰新手可按需选择学习也可同时搭建对比练习。重点开发阶段优先使用测试网如 Sepolia、Holesky避免主网 Gas 费损耗。2.1 开发环境准备通用步骤步骤1安装 Node.js 与 npm两大库均依赖 Node.js 环境推荐安装 Node.js 16 版本兼容 v4 版本最佳安装完成后自动自带 npm 包管理器。验证安装打开终端输入以下命令显示版本号即安装成功node -vnpm -v步骤2安装必备辅助工具通用- MetaMask 钱包Chrome/Edge 浏览器插件用于测试账户管理、交易签名开发必备。- 测试网代币在测试网 faucet水龙头领取测试 ETH用于支付测试网 Gas 费如 Sepolia 水龙头。- 区块浏览器Etherscan对应测试网版本用于查询交易、合约、地址状态调试必备。- RPC 节点推荐使用公共 RPC 节点如 https://eth.llamarpc.com、https://eth-sepolia.public.blastapi.io经检测上述两个公共 RPC 节点均出现“网页解析失败可能是不支持的网页类型请检查网页或稍后重试”的报错建议注册 Infura/Alchemy 获取专属 RPC 接口提升连接稳定性避免影响开发测试。2.2 web3.js 环境搭建回顾创建项目文件夹初始化 npm 项目然后安装 web3.js支持两种安装方式方式1安装完整 web3.js 库适合新手# 使用 npmnpm install web3# 使用 yarnyarn add web3方式2按需安装子包适合生产环境# 仅安装合约交互模块npm install web3-eth-contract# 仅安装账户管理模块npm install web3-eth-accounts2.3 ethers.js 环境搭建重点ethers.js 安装更简洁无需区分子包直接安装即可支持 npm/yarn 两种方式# 使用 npm推荐npm install ethers# 使用 yarnyarn add ethers验证安装创建 test-ethers.js 文件导入 ethers打印版本号无报错即安装成功// 导入 ethersES Module 导入推荐import { ethers } from ethers;// CommonJS 导入适用于旧项目// const { ethers } require(ethers);console.log(ethers.js 版本, ethers.version); // 输出 v6.x.x 即成功运行命令node test-ethers.js查看版本输出即可。2.4 首次调用两大库同步实现“查询区块高度”分别使用 web3.js 和 ethers.js 编写代码实现“连接区块链节点 → 查询当前区块高度”对比两者的 API 差异加深理解。2.4.1 web3.js 实现回顾import { Web3 } from web3;// 初始化 Web3 实例连接 RPC 节点注意公共节点 https://eth.llamarpc.com、https://eth-sepolia.public.blastapi.io 均解析失败// 建议替换为 Infura/Alchemy 专属 RPC 接口示例格式https://mainnet.infura.io/v3/你的API密钥const web3 new Web3(https://mainnet.infura.io/v3/your-api-key);// 异步查询区块高度async function getBlockNumberWeb3() {try {const blockNumber await web3.eth.getBlockNumber();console.log(web3.js - 当前区块高度, blockNumber);return blockNumber;} catch (error) {console.error(web3.js - 查询失败, error.message);console.error(提示公共 RPC 节点解析失败请使用 Infura/Alchemy 专属 RPC 接口);}}getBlockNumberWeb3();2.4.2 ethers.js 实现重点import { ethers } from ethers;// 1. 初始化 Provider对应 web3.js 的 Web3 实例用于连接 RPC 节点公共节点解析失败建议使用专属接口// 示例格式https://mainnet.infura.io/v3/你的API密钥const provider new ethers.JsonRpcProvider(https://mainnet.infura.io/v3/your-api-key);// 2. 异步查询区块高度ethers.js API 更简洁async function getBlockNumberEthers() {try {const blockNumber await provider.getBlockNumber();console.log(ethers.js - 当前区块高度, blockNumber);return blockNumber;} catch (error) {console.error(ethers.js - 查询失败, error.message);console.error(提示公共 RPC 节点解析失败请使用 Infura/Alchemy 专属 RPC 接口);}}getBlockNumberEthers();关键区别web3.js 需创建 Web3 实例通过 web3.eth.getBlockNumber() 调用ethers.js 需创建 JsonRpcProvider 实例通过 provider.getBlockNumber() 调用API 更简洁。运行代码分别执行两个文件若使用 Infura/Alchemy 专属 RPC 接口可正常输出当前区块高度说明环境搭建成功若仍使用公共节点会出现解析失败报错。三、基础进阶两大库核心 API 实操对比学习本部分按“链上数据查询、钱包账户管理、交易发送”三大模块同步讲解 web3.js 和 ethers.js 的核心 API对比两者的使用差异方便大家灵活切换使用。3.1 链上数据查询只读操作无 Gas 费这类操作无需用户签名无需支付 Gas 费主要用于查询链上公开数据账户余额、区块详情、交易详情是 DApp 中最基础的功能。3.1.1 查询账户余额核心对比web3.js 实现回顾async function getAccountBalanceWeb3(address) {try {const balanceWei await web3.eth.getBalance(address);const balanceEth web3.utils.fromWei(balanceWei, ether);console.log(web3.js - 地址 ${address} 的余额${balanceEth} ETH);return balanceEth;} catch (error) {console.error(web3.js - 查询余额失败, error.message);console.error(提示公共 RPC 节点解析失败请使用 Infura/Alchemy 专属 RPC 接口);}}// 测试查询以太坊创始人 Vitalik 的地址余额getAccountBalanceWeb3(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045);ethers.js 实现重点async function getAccountBalanceEthers(address) {try {// ethers.js 自动处理单位转换无需手动调用 fromWeiconst balanceEth await provider.getBalance(address);// 转换为字符串格式保留4位小数console.log(ethers.js - 地址 ${address} 的余额${ethers.formatEther(balanceEth)} ETH);return ethers.formatEther(balanceEth);} catch (error) {console.error(ethers.js - 查询余额失败, error.message);console.error(提示公共 RPC 节点解析失败请使用 Infura/Alchemy 专属 RPC 接口);}}// 测试与 web3.js 测试地址一致对比结果getAccountBalanceEthers(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045);关键区别ethers.js 中getBalance 方法返回 BigInt 类型的余额wei 单位但提供了 formatEther 方法快速转换为 ETH 单位无需像 web3.js 那样手动调用 fromWei反之若需转换为 wei 单位可使用 ethers.parseEther(amount) 方法。3.1.2 查询区块详情核心对比除了查询区块高度实际开发中常需要获取区块的详细信息如时间戳、交易数量、矿工地址等两大库均支持灵活查询可指定具体区块号或查询最新区块。web3.js 实现回顾async function getBlockDetailsWeb3(blockNumber) {try {// 传入 latest 表示最新区块也可传入具体区块号如 19000000const block await web3.eth.getBlock(blockNumber || latest);if (!block) {console.log(web3.js - 未找到该区块);return null;}console.log(web3.js - 区块详情, {区块号: block.number,时间戳: new Date(block.timestamp * 1000).toLocaleString(), // 时间戳转换为本地时间交易数量: block.transactions.length,矿工地址: block.miner,区块哈希: block.hash});return block;} catch (error) {console.error(web3.js - 查询区块失败, error.message);console.error(提示公共 RPC 节点解析失败请使用 Infura/Alchemy 专属 RPC 接口);}}// 测试查询最新区块详情getBlockDetailsWeb3();// 测试查询指定区块详情示例区块号可替换为实际区块号// getBlockDetailsWeb3(19000000);ethers.js 实现重点async function getBlockDetailsEthers(blockNumber) {try {// 用法与 web3.js 一致latest 表示最新区块支持具体区块号const block await provider.getBlock(blockNumber || latest);if (!block) {console.log(ethers.js - 未找到该区块);return null;}console.log(ethers.js - 区块详情, {区块号: block.number,时间戳: new Date(block.timestamp * 1000).toLocaleString(),交易数量: block.transactions.length,矿工地址: block.miner,区块哈希: block.hash});return block;} catch (error) {console.error(ethers.js - 查询区块失败, error.message);console.error(提示公共 RPC 节点解析失败请使用 Infura/Alchemy 专属 RPC 接口);}}// 测试查询最新区块详情getBlockDetailsEthers();// 测试查询指定区块详情// getBlockDetailsEthers(19000000);关键区别两者 API 命名接近功能完全一致返回的区块对象结构也基本相同。唯一细微差异是ethers.js 返回的 block.transactions 数组中交易哈希的格式与 web3.js 一致均为字符串类型可直接用于后续查询交易详情。3.1.3 查询交易详情核心对比当获取到交易哈希后可通过两大库查询该交易的详细信息如发送地址、接收地址、交易金额、Gas 费用等用于调试或展示交易状态。web3.js 实现回顾async function getTransactionDetailsWeb3(txHash) {try {const transaction await web3.eth.getTransaction(txHash);if (!transaction) {console.log(web3.js - 未找到该交易);return null;}// 转换 Gas 价格为 gwei 单位更易读交易金额为 ETH 单位console.log(web3.js - 交易详情, {交易哈希: transaction.hash,发送地址: transaction.from,接收地址: transaction.to, // 若为合约部署交易to 为 null交易金额: web3.utils.fromWei(transaction.value, ether) ETH,Gas 价格: web3.utils.fromWei(transaction.gasPrice, gwei) gwei,Gas 限制: transaction.gas,交易状态: transaction.blockNumber ? 已上链 : 未上链});return transaction;} catch (error) {console.error(web3.js - 查询交易失败, error.message);console.error(提示公共 RPC 节点解析失败请使用 Infura/Alchemy 专属 RPC 接口);}}// 测试传入任意交易哈希可从 Etherscan 复制测试网/主网交易哈希getTransactionDetailsWeb3(0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef);ethers.js 实现重点async function getTransactionDetailsEthers(txHash) {try {const transaction await provider.getTransaction(txHash);if (!transaction) {console.log(ethers.js - 未找到该交易);return null;}// ethers.js 提供 formatGwei 方法直接转换 Gas 价格无需手动计算console.log(ethers.js - 交易详情, {交易哈希: transaction.hash,发送地址: transaction.from,接收地址: transaction.to,交易金额: ethers.formatEther(transaction.value) ETH,Gas 价格: ethers.formatGwei(transaction.gasPrice) gwei,Gas 限制: transaction.gasLimit, // ethers.js 中命名为 gasLimit与 web3.js 的 gas 对应交易状态: transaction.blockNumber ? 已上链 : 未上链});return transaction;} catch (error) {console.error(ethers.js - 查询交易失败, error.message);console.error(提示公共 RPC 节点解析失败请使用 Infura/Alchemy 专属 RPC 接口);}}// 测试与 web3.js 测试哈希一致对比结果getTransactionDetailsEthers(0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef);关键区别1. 命名差异ethers.js 中 Gas 限制字段为 gasLimitweb3.js 中为 gas2. 单位转换ethers.js 内置 formatGwei 方法无需像 web3.js 那样通过 fromWei 手动转换 Gas 价格更便捷3. 一致性两者返回的交易核心信息哈希、地址、金额完全一致可相互通用。3.2 钱包账户管理核心实操两大库均提供账户创建、私钥导入、签名等功能用于管理用户钱包账户。注意测试环境可使用随机生成的账户生产环境需严格保管私钥私钥泄露会导致资产丢失建议使用硬件钱包或安全的密钥管理工具。3.2.1 创建随机账户核心对比随机创建账户适用于测试场景两大库均支持一键创建且会生成私钥、公钥、地址ethers.js 额外支持自动生成助记词更适合钱包类 DApp 开发。web3.js 实现回顾// 创建包含1个随机账户的钱包可指定创建数量如 create(5) 创建5个账户const walletWeb3 web3.eth.accounts.wallet.create(1);const accountWeb3 walletWeb3[0];console.log(web3.js - 随机创建的账户, {地址: accountWeb3.address,私钥: accountWeb3.privateKey, // 生产环境绝对不能泄露公钥: accountWeb3.publicKey});// 补充web3.js 生成助记词需额外调用方法ethers.js 自动生成const mnemonic web3.eth.accounts.mnemonic.generate();console.log(web3.js - 生成的助记词, mnemonic);// 通过助记词导入账户const accountFromMnemonic web3.eth.accounts.mnemonicToAccount(mnemonic);console.log(web3.js - 从助记词导入的账户地址, accountFromMnemonic.address);ethers.js 实现重点// ethers.js 创建随机钱包直接返回钱包实例自动生成助记词const walletEthers ethers.Wallet.createRandom();console.log(ethers.js - 随机创建的账户, {地址: walletEthers.address,私钥: walletEthers.privateKey, // 生产环境绝对不能泄露公钥: walletEthers.publicKey,助记词: walletEthers.mnemonic.phrase // 自动生成12位助记词可用于恢复账户});// 补充ethers.js 通过助记词导入账户const mnemonic walletEthers.mnemonic.phrase;const walletFromMnemonic ethers.Wallet.fromPhrase(mnemonic, provider);console.log(ethers.js - 从助记词导入的账户地址, walletFromMnemonic.address);关键区别1. 助记词支持ethers.js 创建随机钱包时自动生成助记词web3.js 需额外调用 mnemonic.generate() 方法生成操作更繁琐2. 钱包实例ethers.js 返回的 Wallet 实例可直接关联 provider后续可直接发送交易web3.js 需手动关联 Web3 实例3. 易用性ethers.js 助记词导入更简洁无需额外转换直接通过 fromPhrase 方法即可。3.2.2 导入现有账户通过私钥实际开发中常需要导入用户已有的账户如 MetaMask 钱包导出的私钥两大库均支持通过私钥快速导入用于后续交易签名、合约交互。web3.js 实现回顾// 替换为你的私钥测试用生产环境请勿硬编码私钥const privateKey 0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec;// 导入私钥添加到 web3 钱包实例中const importedAccountWeb3 web3.eth.accounts.wallet.add(privateKey);console.log(web3.js - 导入的账户地址, importedAccountWeb3.address);// 验证查询导入账户的余额需连接 RPC 节点getAccountBalanceWeb3(importedAccountWeb3.address);ethers.js 实现重点// 替换为你的私钥测试用生产环境请勿硬编码私钥const privateKey 0x50d349f5cf627d44858d6fcb6fbf15d27457d35c58ba2d5cfeaf455f25db5bec;// ethers.js 直接通过私钥创建钱包实例同时关联 provider可选便于后续交易const importedWalletEthers new ethers.Wallet(privateKey, provider);console.log(ethers.js - 导入的账户地址, importedWalletEthers.address);// 验证查询导入账户的余额钱包实例可直接调用 getBalance 方法async function verifyImportedWallet() {const balance await importedWalletEthers.getBalance();console.log(ethers.js - 导入账户余额, ethers.formatEther(balance) ETH);}verifyImportedWallet();关键区别1. 关联节点ethers.js 导入私钥时可直接将钱包实例与 provider 关联后续无需额外操作即可发送交易web3.js 导入私钥后需关联已创建的 Web3 实例才能进行链上操作2. 余额查询ethers.js 钱包实例可直接调用 getBalance 方法web3.js 需调用单独的查询函数传入导入账户的地址3. 安全性两者均支持私钥导入但需注意生产环境中绝对不能将私钥硬编码到代码中建议通过前端加密存储或硬件钱包签名。3.2.3 账户签名进阶功能账户签名是 Web3 开发中的重要功能用于验证用户身份如登录 DApp、签署交易或消息两大库均提供完善的签名 API无需发送到链上无 Gas 费。web3.js 实现回顾// 要签名的消息通常为用户身份信息、交易摘要等const message 我是 DApp 用户请求登录验证;// 使用导入的账户签名消息async function signMessageWeb3() {try {const signature await web3.eth.accounts.sign(message, privateKey);console.log(web3.js - 消息签名结果, {原始消息: message,签名: signature.signature,签名者地址: signature.address});// 验证签名确认签名者身份const recoveredAddress web3.eth.accounts.recover(message, signature.signature);console.log(web3.js - 验证签名, recoveredAddress importedAccountWeb3.address ? 签名有效 : 签名无效);} catch (error) {console.error(web3.js - 签名失败, error.message);}}signMessageWeb3();ethers.js 实现重点// 要签名的消息const message 我是 DApp 用户请求登录验证;// 使用导入的钱包实例签名消息更简洁async function signMessageEthers() {try {// ethers.js 签名消息自动关联签名者地址const signature await importedWalletEthers.signMessage(message);console.log(ethers.js - 消息签名结果, {原始消息: message,签名: signature,签名者地址: importedWalletEthers.address});// 验证签名const recoveredAddress ethers.verifyMessage(message, signature);console.log(ethers.js - 验证签名, recoveredAddress importedWalletEthers.address ? 签名有效 : 签名无效);} catch (error) {console.error(ethers.js - 签名失败, error.message);}}signMessageEthers();关键区别1. API 简洁度ethers.js 钱包实例直接调用 signMessage 方法签名web3.js 需调用 web3.eth.accounts.sign 方法传入消息和私钥2. 验证方式ethers.js 使用 verifyMessage 方法验证签名web3.js 使用 recover 方法两者逻辑一致但 ethers.js 命名更直观3. 一致性签名结果格式完全兼容web3.js 签名的消息可通过 ethers.js 验证反之亦然。3.3 交易发送写操作需 Gas 费这类操作会修改链上状态如 ETH 转账、调用合约写方法需要用户签名支付 Gas 费是 Web3 开发的核心功能之一。以下示例实现 ETH 转账操作对比两大库的差异重点说明 ethers.js 的简洁用法。3.3.1 web3.js 实现回顾// 转账函数从导入的账户向目标地址转账async function sendTransactionWeb3(toAddress, amountEth) {try {// 1. 转换金额为 wei 单位链上交易均使用 wei 单位const amountWei web3.utils.toWei(amountEth, ether);// 2. 构造交易对象const txObject {from: importedAccountWeb3.address, // 发送地址导入的账户to: toAddress, // 接收地址value: amountWei, // 转账金额wei 单位gas: 21000, // ETH 普通转账固定 Gas 限制为 21000gasPrice: await web3.eth.getGasPrice() // 获取当前 Gas 价格};// 3. 发送交易并等待确认const receipt await web3.eth.sendTransaction(txObject);console.log(web3.js - 交易发送成功, {交易哈希: receipt.transactionHash,区块号: receipt.blockNumber,消耗 Gas: receipt.gasUsed wei});return receipt;} catch (error) {console.error(web3.js - 交易失败, error.message);console.error(提示公共 RPC 节点解析失败请使用 Infura/Alchemy 专属 RPC 接口同时确保发送账户有足够的测试 ETH 支付 Gas 费);}}// 测试使用导入的账户发送 0.001 ETH需确保账户有测试币sendTransactionWeb3(0xa3286628134bad128faeef82f44e99aa64085c94, // 接收地址测试用0.001 // 转账金额ETH);3.3.2 ethers.js 实现重点// 转账函数使用导入的钱包实例发送 ETHasync function sendTransactionEthers(toAddress, amountEth) {try {// 1. 转换金额为 wei 单位ethers.js 提供 parseEther 方法const amountWei ethers.parseEther(amountEth);// 2. 发送交易钱包实例直接调用 sendTransaction 方法无需构造复杂对象const tx await importedWalletEthers.sendTransaction({to: toAddress,value: amountWei,gasLimit: 21000 // 对应 web3.js 的 gas 参数普通转账固定为 21000});// 3. 等待交易确认ethers.js 需调用 wait() 方法返回交易收据const receipt await tx.wait();// 验证交易是否成功receipt.status 为 1 表示成功0 表示失败if (receipt.status 1) {console.log(ethers.js - 交易发送成功, {交易哈希: tx.hash,区块号: receipt.blockNumber,消耗 Gas: receipt.gasUsed.toString() wei});return receipt;} else {console.log(ethers.js - 交易失败交易未确认);return null;}} catch (error) {console.error(ethers.js - 交易失败, error.message);console.error(提示公共 RPC 节点解析失败请使用 Infura/Alchemy 专属 RPC 接口同时确保发送账户有足够的测试 ETH 支付 Gas 费);}}// 测试与 web3.js 测试参数一致对比结果sendTransactionEthers(0xa3286628134bad128faeef82f44e99aa64085c94,0.001);关键区别1. 交易构造ethers.js 无需手动构造复杂的交易对象钱包实例直接调用 sendTransaction 方法传入核心参数to、value、gasLimit即可web3.js 需手动构造 txObject指定 from、gas、gasPrice 等参数2. 交易确认ethers.js 需调用 tx.wait() 方法等待交易确认返回交易收据web3.js 的 sendTransaction 方法会自动等待确认直接返回收据3. 错误处理ethers.js 可通过 receipt.status 判断交易是否成功web3.js 需通过收据中的 status 字段v4 版本支持判断4. 易用性ethers.js 转账流程更简洁减少了手动参数配置降低新手出错概率。注意事项测试转账时务必使用测试网如 Sepolia确保发送账户有足够的测试 ETH用于支付 Gas 费和转账金额生产环境中建议添加 Gas 价格动态调整逻辑避免因 Gas 价格过低导致交易卡住。四、精通进阶智能合约交互两大库对比智能合约是 Web3 应用的核心两大库均提供完善的 API 用于与智能合约交互读方法、写方法这是从“入门”到“精通”的关键一步。以下以 ERC-20 代币合约为例讲解完整交互流程对比两者的使用差异同时适配 RPC 节点报错场景确保代码可正常测试。4.1 核心前提获取合约 ABI 与地址通用与智能合约交互必须具备两个核心信息两大库通用缺一不可- 合约地址合约部署在区块链上的唯一标识如测试网 USDT 合约地址、自定义合约部署后的地址。- 合约 ABI应用二进制接口相当于“合约的接口说明书”定义了合约的方法、参数、返回值用于告诉前端如何与合约通信。获取方式1. 已部署的公开合约从 Etherscan对应测试网/主网查询复制 ABI 和合约地址2. 自定义合约通过 Remix IDE 编写、部署合约后从 Remix 中复制 ABI 和地址3. 项目开发中由合约开发者提供 ABI 文件通常为 JSON 格式。4.2 合约实例化核心对比合约实例化是与合约交互的第一步两大库均需传入 ABI 和合约地址ethers.js 额外需要传入 provider 或 wallet用于连接节点或签名交易。web3.js 实现回顾// 1. 合约 ABIERC-20 代币合约简化版包含转账、查询余额、查询符号方法const erc20Abi [{inputs: [{name: _to, type: address}, {name: _value, type: uint256}],name: transfer,outputs: [{name: , type: bool}],type: function // 写方法需签名、支付 Gas 费},{inputs: [{name: _owner, type: address}],name: balanceOf,outputs: [{name: , type: uint256}],type: function // 读方法无需签名、无 Gas 费},{name: symbol,outputs: [{name: , type: string}],type: function // 读方法}];// 2. 合约地址测试网 ERC-20 代币合约地址可替换为自己部署的合约地址const contractAddress 0x1234567890abcdef1234567890abcdef12345678;// 3. 实例化合约web3.js 已关联 Web3 实例无需额外传入节点信息const contractWeb3 new web3.eth.Contract(erc20Abi, contractAddress);ethers.js 实现重点// 1. 合约 ABI与 web3.js 完全一致可直接复用const erc20Abi [{inputs: [{name: _to, type: address}, {name: _value, type: uint256}],name: transfer,outputs: [{name: , type: bool}],type: function},{inputs: [{name: _owner, type: address}],name: balanceOf,outputs: [{name: , type: uint256}],type: function},{name: symbol,outputs: [{name: , type: string}],type: function}];// 2. 合约地址与 web3.js 一致测试用const contractAddress 0x1234567890abcdef1234567890abcdef12345678;// 3. 实例化合约ethers.js 需传入 ABI、地址、provider/wallet// 仅查询合约读方法传入 provider 即可const contractEthers new ethers.Contract(contractAddress, erc20Abi, provider);// 若需调用写方法如转账需传入 wallet已导入私钥的钱包实例const contractWithSigner contractEthers.connect(importedWalletEthers);关键区别1. 实例化参数web3.js 实例化合约时无需传入节点信息已关联 Web3 实例ethers.js 需传入 provider用于读方法或 wallet用于写方法明确区分“只读交互”和“可签名交互”2. 写方法准备ethers.js 调用写方法前需通过 connect() 方法将合约实例与钱包绑定获取签名权限web3.js 无需额外绑定在调用写方法时指定 from 地址即可3. 复用性ABI 可完全复用两大库的合约实例化逻辑一致仅参数传入有差异。