RPC节点与数据获取:公共节点与私有节点、JSON-RPC协议详解、使用Web3.py/ethers.js获取区块数据
这一章,我们来聊聊链上数据的入口——RPC节点。
说实话,很多新手一上来就急着写合约、跑策略,结果第一步就被节点卡住了。我见过太多人因为用了免费的公共节点,跑着跑着突然断连,套利机会眼睁睁溜走。嗯,咱们今天就把这事彻底讲透。
公共节点 vs 私有节点:你该怎么选?
先问个问题:你平时用哪个节点?
大部分人会回答:Infura、Alchemy、QuickNode。这些都是公共节点服务商。说白了,就是他们把节点搭好,你付钱(或者免费)去调用。
公共节点的好处很明显:
- 上手快,注册个账号就能用
- 不用自己维护服务器
- 免费额度够你学习用
但坑也不少:
- 有速率限制(Rate Limit),高频调用会被封
- 节点不稳定,高峰期延迟高
- 数据可能滞后,对套利来说这是致命的
我曾经在跑一个Uniswap V3的套利策略时,用了公共节点。结果因为节点数据延迟了2个区块,我的交易总是比MEV机器人慢一步。后来换成自建节点,延迟从800ms降到了50ms,收益直接翻倍。
私有节点,就是你自己搭的节点。比如用Geth或者Nethermind跑一个全节点。
我个人习惯在套利场景下用私有节点。为什么呢?
- 没有速率限制,想调多少次调多少次
- 延迟可控,数据实时性高
- 可以自定义一些优化,比如只同步你需要的合约状态
当然,私有节点也有成本:你得有一台服务器,硬盘至少2TB(以太坊全节点现在快12TB了),还要维护它别断线。
| 对比项 | 公共节点 | 私有节点 |
|---|---|---|
| 上手难度 | 低 | 高 |
| 成本 | 免费或按量付费 | 服务器+带宽+维护 |
| 延迟 | 200-800ms | 20-100ms |
| 速率限制 | 有 | 无 |
| 适合场景 | 学习、低频查询 | 高频交易、套利 |
JSON-RPC协议详解:链上数据的“通用语言”
不管你是用公共节点还是私有节点,它们都通过同一个协议跟你对话——JSON-RPC。
JSON-RPC说白了就是一个轻量级的远程调用协议。你发一个JSON格式的请求过去,节点返回一个JSON格式的响应。就这么简单。
一个典型的请求长这样:
{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": 1
}
节点返回:
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x10d4f3a"
}
你看,result字段返回的是最新区块号,十六进制的。0x10d4f3a换算成十进制就是17623866。
常用的JSON-RPC方法有哪些?我列几个你一定会用到的:
eth_blockNumber— 获取最新区块号eth_getBlockByNumber— 获取区块详情eth_getTransactionReceipt— 获取交易回执eth_call— 调用合约的只读方法eth_getLogs— 获取事件日志,套利必备
我个人习惯用
eth_getLogs来监听DEX的Swap事件。比如Uniswap V3的Swap事件里包含了价格、流动性等信息,你可以实时捕捉套利机会。
使用Web3.py获取区块数据
好了,理论讲完了,咱们来点实际的。我用Python的Web3.py库来演示怎么获取区块数据。
先安装:
pip install web3
然后连接节点:
from web3 import Web3
# 连接公共节点
w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/YOUR_PROJECT_ID'))
# 检查是否连接成功
print(w3.is_connected()) # 返回True就对了
获取最新区块号:
latest_block = w3.eth.block_number
print(f"最新区块: {latest_block}")
获取区块详情:
block = w3.eth.get_block(latest_block)
print(f"区块哈希: {block['hash'].hex()}")
print(f"时间戳: {block['timestamp']}")
print(f"交易数量: {len(block['transactions'])}")
获取区块里的所有交易:
for tx_hash in block['transactions']:
tx = w3.eth.get_transaction(tx_hash)
print(f"交易哈希: {tx_hash.hex()}")
print(f"发送方: {tx['from']}")
print(f"接收方: {tx['to']}")
print(f"金额: {w3.from_wei(tx['value'], 'ether')} ETH")
注意
get_block默认不返回完整的交易详情,只返回交易哈希。如果你需要交易详情,可以设置full_transactions=True,但这样会慢很多。我建议先获取哈希,再按需获取具体交易。
使用ethers.js获取区块数据
如果你用JavaScript/TypeScript,ethers.js是首选。我个人在Node.js环境里用得最多。
安装:
npm install ethers
连接节点:
const { ethers } = require('ethers');
const provider = new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/v3/YOUR_PROJECT_ID');
获取最新区块:
async function getLatestBlock() {
const blockNumber = await provider.getBlockNumber();
console.log(`最新区块: ${blockNumber}`);
const block = await provider.getBlock(blockNumber);
console.log(`区块哈希: ${block.hash}`);
console.log(`时间戳: ${block.timestamp}`);
console.log(`交易数量: ${block.transactions.length}`);
}
getLatestBlock();
监听新区块(套利必备):
provider.on('block', (blockNumber) => {
console.log(`新区块: ${blockNumber}`);
// 在这里触发你的套利逻辑
});
用
provider.on('block')监听时,如果你的回调函数执行时间太长,会错过后续区块。我曾经因为这个原因丢了好几个套利机会。建议把逻辑写成异步的,或者用消息队列缓冲。
知识体系结构图
下面这张图帮你理清本章的知识脉络:
这张图把整个流程串起来了:从节点选择(公共/私有),到通信协议(JSON-RPC),再到具体的方法调用,最后用Web3.py或ethers.js实现。你想想看,是不是一下子就清晰了?
刚开始学的时候,先用公共节点+Web3.py跑通流程。等你真正开始做套利了,再考虑搭私有节点。别一上来就搞全节点,那玩意儿同步数据就要好几天。
好了,这一章的内容就到这。记住:节点是你的眼睛,数据是你的弹药。没有好的节点,再牛的策略也是白搭。