以太坊批量转账Node.js实现指南,高效处理多笔ETH及代币转账

投稿 2026-02-16 10:51 点击数: 4

在区块链应用开发中,批量转账是一项常

随机配图
见需求,例如空投代币、分发奖励、多商户结算等场景,以太坊作为最大的智能合约平台,其批量转账功能需要结合节点通信、交易签名、Gas优化等技术,本文将详细介绍如何使用Node.js实现以太坊批量转账,涵盖环境准备、核心代码实现、优化技巧及注意事项,帮助开发者高效完成多笔ETH及ERC20代币的转账任务。

开发环境准备

在开始批量转账之前,需完成以下环境配置:

安装Node.js与npm

确保本地已安装Node.js(建议版本≥16.0)及npm(Node.js包管理器),可通过以下命令检查:

node -v
npm -v

初始化项目

创建项目目录并初始化npm工程:

mkdir ethereum-batch-transfer
cd ethereum-batch-transfer
npm init -y

安装依赖库

批量转账需使用以太坊交互库,推荐ethers.js(轻量级、功能完善)或web3.js,本文以ethers.js为例:

npm install ethers dotenv
  • ethers.js:以太坊交互库,支持节点连接、钱包管理、交易签名等功能;
  • dotenv:环境变量管理工具,用于安全存储私钥、节点URL等敏感信息。

核心实现步骤

配置环境变量

在项目根目录创建.env文件,存储敏感信息(注意:私钥切勿泄露,切勿提交到代码仓库):

# 以太坊节点URL(可使用Infura、Alchemy或本地节点)
INFURA_URL=https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID
# 转账方私钥(建议使用新创建的账户,避免风险)
PRIVATE_KEY=0x您的私钥
# 转账金额(单位:ETH,批量转账时可动态调整)
TRANSFER_AMOUNT=0.01

连接以太坊节点

使用ethers.jsJsonRpcProvider连接到以太坊网络:

const { ethers } = require('ethers');
require('dotenv').config();
// 创建Provider实例,连接到以太坊节点
const provider = new ethers.providers.JsonRpcProvider(process.env.INFURA_URL);
// 验证节点连接
provider.getNetwork().then((network) => {
    console.log('当前网络:', network.name, '(Chain ID:', network.chainId, ')');
}).catch((err) => {
    console.error('节点连接失败:', err);
});

创建转账钱包

通过私钥创建钱包实例,用于签名交易:

// 从私钥创建钱包
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
console.log('转账地址:', wallet.address);
console.log('账户ETH余额:', ethers.utils.formatEther(await wallet.getBalance()), 'ETH');

批量转账ETH实现

假设需要向多个接收地址批量转账ETH,核心逻辑是循环构造并发送交易,以下为完整代码:

const addresses = [
    '0x接收地址1',
    '0x接收地址2',
    '0x接收地址3',
    // ...更多接收地址
];
const transferETH = async () => {
    try {
        const amount = ethers.utils.parseEther(process.env.TRANSFER_AMOUNT); // 将ETH转换为wei
        const nonce = await wallet.getTransactionCount(); // 获取当前nonce值,避免交易冲突
        for (let i = 0; i < addresses.length; i++) {
            const toAddress = addresses[i];
            // 构造交易对象
            const transaction = {
                to: toAddress,
                value: amount,
                nonce: nonce + i, // 每笔交易的nonce递增
                gasLimit: 21000, // ETH转账固定Gas Limit
                gasPrice: await provider.getGasPrice(), // 获取当前建议Gas Price
            };
            // 签名并发送交易
            const tx = await wallet.sendTransaction(transaction);
            console.log(`第${i + 1}笔交易已发送,哈希: ${tx.hash}`);
            // 等待交易上链
            await tx.wait();
            console.log(`第${i + 1}笔交易已上链,接收地址: ${toAddress}`);
        }
        console.log('批量ETH转账完成!');
    } catch (error) {
        console.error('批量转账失败:', error);
    }
};
transferETH();

批量转账ERC20代币实现

ERC20代币转账需调用合约的transfer方法,核心步骤包括:

  1. 加载ERC20代币合约;
  2. 构造合约调用交易;
  3. 签名并发送交易。

假设要转账的ERC20代币合约地址为0x代币合约地址,ABI(合约接口)可通过Etherscan或@openzeppelin/contracts获取:

// ERC20代币ABI(简化版,包含transfer方法)
const tokenABI = [
    "function transfer(address to, uint amount) returns (bool)",
    "function decimals() returns (uint8)",
    "function symbol() string"
];
const tokenAddress = '0x您的代币合约地址'; // USDT合约地址
const tokenContract = new ethers.Contract(tokenAddress, tokenABI, wallet);
const transferToken = async () => {
    try {
        const decimals = await tokenContract.decimals();
        const symbol = await tokenContract.symbol();
        const amount = ethers.utils.parseUnits(process.env.TRANSFER_AMOUNT, decimals); // 根据代币精度转换
        const nonce = await wallet.getTransactionCount();
        for (let i = 0; i < addresses.length; i++) {
            const toAddress = addresses[i];
            // 构造合约调用交易
            const tx = await tokenContract.transfer(
                toAddress,
                amount,
                {
                    nonce: nonce + i,
                    gasLimit: 100000, // ERC20转账Gas Limit通常高于ETH转账
                    gasPrice: await provider.getGasPrice(),
                }
            );
            console.log(`第${i + 1}笔${symbol}转账已发送,哈希: ${tx.hash}`);
            await tx.wait();
            console.log(`第${i + 1}笔${symbol}转账已上链,接收地址: ${toAddress}`);
        }
        console.log('批量代币转账完成!');
    } catch (error) {
        console.error('批量代币转账失败:', error);
    }
};
// transferToken(); // 取消注释执行代币转账

批量转账优化技巧

批量转账时,若处理不当可能导致交易效率低下或成本过高,以下是关键优化方向:

Gas优化

  • 动态Gas Price:使用provider.getGasPrice()获取实时Gas Price,或通过ethers.utils.formatUnits手动调整(例如在网络拥堵时适当提高Gas Price)。
  • Gas Limit预估:ETH转账固定为21000,ERC20转账可通过estimateGas方法动态预估:
    const gasLimit = await tokenContract.estimateGas.transfer(toAddress, amount);
    transaction.gasLimit = gasLimit.mul(120).div(100); // 预留20%缓冲

Nonce管理

  • 连续Nonce:确保每笔交易的nonce值连续递增,避免因nonce跳跃导致交易失败,可通过wallet.getTransactionCount()获取初始nonce,循环中递增。
  • 并发控制:若需并行发送交易,需提前规划nonce范围,避免冲突。

错误处理与重试

  • 捕获交易失败:监听交易回溯事件(transaction.receipt.status),若失败(status=0)则记录并重试。
  • 网络波动处理:添加网络超时和重试机制,例如使用try-catch包裹sendTransaction,失败后延迟1秒重试。

批量交易聚合(高级)

对于超大批量转账(如1000笔以上),可考虑以下方案:

  • 多账户签名:使用多个钱包地址分散交易压力,避免单账户nonce拥堵。
  • 第三方服务:使用Flashbots等MEV(最大可提取价值)服务,将批量交易打包提交,降低Gas成本。

注意事项

安全性

  • 私钥管理:切勿将私钥硬编码在代码中,建议使用硬件钱包(如Ledger)或环境变量加密存储。
  • 测试网验证:正式转账前,先在以太坊测试网(如Goerli)测试逻辑,确认无误后再切换到主网。

成本控制

  • Gas费用计算:批量转账总成本 = 单笔Gas Limit × Gas Price × 转账笔数,需提前估算成本,避免账户余额不足。
  • 低峰期操作:选择网络拥堵较轻的时段