4. 执行环境搭建:Node.js与Hardhat环境、Web3.js与Ethers.js库、RPC节点配置
好,咱们直接进入正题。套利策略写得再漂亮,跑不起来等于零。这一章,我就带你搭一套真正能用的执行环境。
说实话,我见过太多人卡在环境搭建这一步。不是版本冲突,就是RPC连不上。我自己早期做套利机器人时,光配环境就折腾了两天。后来总结出一套「稳如老狗」的流程,今天全部分享给你。
4.1 Node.js 环境安装
Node.js 是整个套利脚本的运行基石。你写的所有代码,最终都要靠它来执行。
版本选择:我个人建议用 LTS 版本,别追新。我踩过坑——有次用了 Node 18 的测试版,结果某个依赖包死活装不上,查了半天才发现是兼容性问题。
推荐版本:Node.js 16.x 或 18.x LTS
安装方式:
- Windows/Mac:直接官网下载安装包
- Linux:用 nvm 管理版本,方便切换
# 安装 nvm(Linux/Mac)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
# 安装 Node 16 LTS
nvm install 16
nvm use 16
# 验证版本
node -v # 输出 v16.20.0 或类似
npm -v # 输出 8.x.x
小技巧:装完 Node 后,建议把 npm 源换成淘宝镜像。国内下载依赖包快很多。
npm config set registry https://registry.npmmirror.com
4.2 Hardhat 开发框架
Hardhat 是我最常用的以太坊开发框架。为什么选它?因为它在本地模拟链上跑得飞快,调试起来特别方便。
我记得第一次用 Truffle 时,每次改代码都要重新编译部署,等得人抓狂。Hardhat 的「console.log」调试功能简直是救星——你可以在合约代码里直接打印变量,就像写 JavaScript 一样自然。
4.2.1 初始化 Hardhat 项目
# 创建项目目录
mkdir arbitrage-bot
cd arbitrage-bot
# 初始化 npm 项目
npm init -y
# 安装 Hardhat
npm install --save-dev hardhat
# 初始化 Hardhat 项目
npx hardhat init
初始化时,选择「Create a JavaScript project」。它会自动帮你生成目录结构:
arbitrage-bot/
├── contracts/ # 智能合约存放目录
├── scripts/ # 部署和交互脚本
├── test/ # 测试文件
├── hardhat.config.js # 配置文件
└── package.json # 依赖管理
4.2.2 配置 Hardhat
打开 hardhat.config.js,这是整个项目的核心配置。我一般会这样配:
require("@nomicfoundation/hardhat-toolbox");
module.exports = {
solidity: "0.8.19",
networks: {
hardhat: {
// 本地网络,默认配置
},
sepolia: {
url: "https://sepolia.infura.io/v3/YOUR_PROJECT_ID",
accounts: ["你的私钥"]
},
mainnet: {
url: "https://mainnet.infura.io/v3/YOUR_PROJECT_ID",
accounts: ["你的私钥"]
}
}
};
⚠️ 安全警告:千万别把私钥直接写在配置文件里!我早期犯过这个错,代码传到 GitHub 上,几分钟内钱包就被清空了。建议用环境变量:
// 使用 dotenv 加载 .env 文件
require("dotenv").config();
module.exports = {
networks: {
mainnet: {
url: process.env.MAINNET_RPC_URL,
accounts: [process.env.PRIVATE_KEY]
}
}
};
4.3 Web3.js 与 Ethers.js 库
这两个库都是用来和以太坊交互的。简单说,它们帮你「翻译」JavaScript 和区块链之间的对话。
| 特性 | Web3.js | Ethers.js |
|---|---|---|
| 体积 | 较大(~400KB) | 较小(~200KB) |
| TypeScript 支持 | 一般 | 原生支持 |
| ENS 解析 | 需额外配置 | 内置支持 |
| Gas 估算 | 手动调用 | 自动估算 |
| 社区活跃度 | 高 | 极高 |
我个人更推荐 Ethers.js。为什么?因为它的 API 设计更现代,用起来更顺手。举个例子,查询账户余额:
// Web3.js 方式
const balance = await web3.eth.getBalance(address);
const etherBalance = web3.utils.fromWei(balance, 'ether');
// Ethers.js 方式
const balance = await provider.getBalance(address);
const etherBalance = ethers.utils.formatEther(balance);
你看,Ethers.js 的命名更直观。而且它内置了 gas 估算,省去不少麻烦。
4.3.1 安装与使用
# 安装 Ethers.js
npm install ethers
# 安装 Web3.js(如果你坚持要用)
npm install web3
写套利脚本时,我通常这样初始化:
const { ethers } = require("ethers");
// 连接到以太坊节点
const provider = new ethers.providers.JsonRpcProvider(
"https://mainnet.infura.io/v3/YOUR_PROJECT_ID"
);
// 创建钱包对象(用于发送交易)
const wallet = new ethers.Wallet("你的私钥", provider);
// 连接到合约
const contract = new ethers.Contract(
"合约地址",
["function balanceOf(address) view returns (uint256)"],
wallet
);
经验之谈:做套利时,建议把 provider 和 wallet 分开。provider 只负责读数据,wallet 负责写交易。这样万一私钥泄露,也只是写权限受影响,读数据不受影响。
4.4 RPC 节点配置
RPC 节点就是你和区块链之间的桥梁。节点选得好不好,直接决定你的套利机器人能不能抢到机会。
我早期用公共节点做套利,结果经常遇到限流。有一次眼睁睁看着一个 2 ETH 的套利机会从眼前溜走,就是因为节点返回数据太慢。从那以后,我学乖了——套利用的节点,必须自己搭或者买付费服务。
4.4.1 节点类型对比
| 类型 | 延迟 | 稳定性 | 费用 | 推荐场景 |
|---|---|---|---|---|
| 公共节点(Infura/Alchemy 免费版) | 高(100-500ms) | 一般 | 免费 | 开发测试 |
| 付费节点(Infura/Alchemy 付费版) | 低(20-50ms) | 高 | 月费 $50-$500 | 小规模套利 |
| 自建节点(Geth/Nethermind) | 极低(5-20ms) | 极高 | 服务器成本 | 高频套利 |
| Flashbots 节点 | 极低 | 极高 | 按交易收费 | MEV 套利 |
4.4.2 配置多个节点做冗余
做套利最怕节点挂掉。我一般会配 3 个节点做 failover:
const providers = [
new ethers.providers.JsonRpcProvider("https://eth-mainnet.alchemyapi.io/v2/KEY1"),
new ethers.providers.JsonRpcProvider("https://eth-mainnet.infura.io/v3/KEY2"),
new ethers.providers.JsonRpcProvider("https://rpc.ankr.com/eth")
];
// 轮询使用,哪个快用哪个
async function getFastestProvider() {
const results = await Promise.race(
providers.map(async (provider) => {
const start = Date.now();
await provider.getBlockNumber();
return { provider, latency: Date.now() - start };
})
);
return results.provider;
}
⚠️ 注意:不同节点的数据可能有短暂的不一致。特别是刚出块那几秒,有的节点已经同步了,有的还没。做套利时,建议用同一个节点读取和发送交易,避免数据不一致导致交易失败。
4.5 完整环境搭建流程
好,咱们把上面所有东西串起来。这是我每次搭建新环境的标准流程:
- 安装 Node.js(LTS 版本,用 nvm 管理)
- 创建项目目录,初始化 npm
- 安装 Hardhat 并初始化项目
- 安装 Ethers.js 和 dotenv
- 配置 RPC 节点(至少 2 个,做冗余)
- 编写测试脚本,验证连接是否正常
验证脚本长这样:
// test-connection.js
const { ethers } = require("ethers");
require("dotenv").config();
async function main() {
const provider = new ethers.providers.JsonRpcProvider(
process.env.MAINNET_RPC_URL
);
const blockNumber = await provider.getBlockNumber();
console.log(`当前区块高度: ${blockNumber}`);
const gasPrice = await provider.getGasPrice();
console.log(`当前 Gas 价格: ${ethers.utils.formatUnits(gasPrice, "gwei")} Gwei`);
console.log("✅ 环境搭建成功!");
}
main().catch(console.error);
跑一下:node test-connection.js。如果看到区块高度和 Gas 价格,说明环境搭好了。
核心要点总结:
- Node.js 用 LTS 版本,别追新
- Hardhat 是本地开发和测试的首选
- Ethers.js 比 Web3.js 更适合套利场景
- RPC 节点必须做冗余,别把所有鸡蛋放一个篮子里
- 私钥永远不要硬编码,用环境变量
环境搭好了,下一步就是写真正的套利逻辑了。不过在那之前,我建议你先跑几个测试交易,确保整个链路是通的。别问我为什么知道——我曾经花了一整天调试一个「套利策略」,最后发现是 RPC 节点配错了,压根没连上主网。