整块订阅(blockreq_newBlocks)

blockreq_newBlocks 是 BlockReq 为 eth_subscribe 提供的订阅类型。链上每出一个块,你会收到一条标准的 eth_subscription 通知,params.result 是带完整交易对象的整个块,与 eth_getBlockByHash(hash, true) 返回的对象一致,字段原样来自节点。

它替代了常见的两步循环:先订阅 newHeads,再对收到的每个链头调用 eth_getBlockByHash。

这是 BlockReq 的扩展订阅,不是以太坊标准订阅。ethers 和 viem 内置的区块监听不会用它,请像下面的示例那样直接发送原始 eth_subscribe。

支持的链

仅在 BlockReq 自建节点的主网上提供。其他链和所有测试网都会拒绝该订阅。

链Chain IDWSS 端点
Ethereum1wss://ethereum-rpc.blockreq.com/v1/rpc/BRQ1P0000000000000000000000000000000000000000000000000000000
Base8453wss://base-rpc.blockreq.com/v1/rpc/BRQ1P0000000000000000000000000000000000000000000000000000000
Arbitrum One42161wss://arbitrum-one-rpc.blockreq.com/v1/rpc/BRQ1P0000000000000000000000000000000000000000000000000000000
BNB Smart Chain56wss://bsc-rpc.blockreq.com/v1/rpc/BRQ1P0000000000000000000000000000000000000000000000000000000
Robinhood4663wss://robinhood-mainnet-rpc.blockreq.com/v1/rpc/BRQ1P0000000000000000000000000000000000000000000000000000000
Arc5042wss://arc-rpc.blockreq.com/v1/rpc/BRQ1P0000000000000000000000000000000000000000000000000000000

该订阅需要带 API key 的端点,公开端点(/v1/rpc/public)会拒绝。

订阅

只发送一个参数 "blockreq_newBlocks",大小写必须完全一致。其他任何写法都会返回 invalid params 错误。

{ "jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["blockreq_newBlocks"] }

和其他订阅一样,响应里是订阅 ID:

{ "jsonrpc": "2.0", "id": 1, "result": "0x9a1c3f0e5b7d2a48c6e1f3b5d7a9c2e4" }

之后每个新块以通知的形式到达。示例经过截短:数值仅作示意,logsBloom 被截断,交易列表只放了该块的一笔交易。

{ "jsonrpc": "2.0", "method": "eth_subscription", "params": { "subscription": "0x9a1c3f0e5b7d2a48c6e1f3b5d7a9c2e4", "result": { "number": "0x1312d00", "hash": "0x5e1c0b7c2c4f0a9d6b3e8f21a7d4c9b05e6f1a2b3c4d5e6f708192a3b4c5d6e7", "parentHash": "0x3b9f4a1d8c7e6052f1a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f809", "timestamp": "0x6745a9c3", "miner": "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97", "gasLimit": "0x1c9c380", "gasUsed": "0xb71b00", "baseFeePerGas": "0x3b9aca00", "logsBloom": "0x00a1…0004", "transactionsRoot": "0x7a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f9", "stateRoot": "0x1f2e3d4c5b6a79880716253443526170899a8b7c6d5e4f30211203f4e5d6c7b8", "receiptsRoot": "0x9c8b7a69584736251403f2e1d0c9b8a7968574635241302f1e0d1c2b3a495867", "transactions": [ { "hash": "0xa1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90", "blockHash": "0x5e1c0b7c2c4f0a9d6b3e8f21a7d4c9b05e6f1a2b3c4d5e6f708192a3b4c5d6e7", "blockNumber": "0x1312d00", "transactionIndex": "0x0", "from": "0x00000000219ab540356cbb839cbe05303d7705fa", "to": "0xdac17f958d2ee523a2206206994597c13d831ec7", "type": "0x2", "nonce": "0x2a", "gas": "0x186a0", "maxFeePerGas": "0x77359400", "maxPriorityFeePerGas": "0x59682f00", "value": "0x0", "input": "0xa9059cbb…", "chainId": "0x1", "accessList": [] } ], "uncles": [] } } }

实际出现哪些字段取决于链及其最近一次硬分叉:通知携带的是节点对 eth_getBlockByHash(hash, true) 的返回,包含链自己的扩展字段。

用 eth_unsubscribe 退订,传入订阅 ID:

{ "jsonrpc": "2.0", "id": 2, "method": "eth_unsubscribe", "params": ["0x9a1c3f0e5b7d2a48c6e1f3b5d7a9c2e4"] }

示例

把 BRQ1P0000000000000000000000000000000000000000000000000000000 换成你的端点 key,下面从环境变量 BLOCKREQ_API_KEY 读取。

wscat

npx wscat -c "wss://ethereum-rpc.blockreq.com/v1/rpc/$BLOCKREQ_API_KEY" \ -x '{"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["blockreq_newBlocks"]}' -w 60

Node.js

需要 Node.js 22 或更新版本,无需安装任何包:

const ws = new WebSocket(`wss://ethereum-rpc.blockreq.com/v1/rpc/${process.env.BLOCKREQ_API_KEY}`); ws.addEventListener("open", () => { ws.send(JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_subscribe", params: ["blockreq_newBlocks"] })); }); let lastNumber = null; ws.addEventListener("message", (event) => { const message = JSON.parse(event.data); if (message.error) { console.error(message.error.code, message.error.message); ws.close(); return; } if (message.method !== "eth_subscription") { console.log("subscription id:", message.result); return; } const block = message.params.result; const number = Number(block.number); if (lastNumber !== null && number > lastNumber + 1) { console.warn(`blocks ${lastNumber + 1}..${number - 1} were not pushed; fetch them with eth_getBlockByNumber`); } lastNumber = number; console.log(number, block.hash, `${block.transactions.length} transactions`); });

Python

需要 Python 3.9 或更新版本,并执行 pip install websockets:

import asyncio import json import os import websockets URL = f"wss://ethereum-rpc.blockreq.com/v1/rpc/{os.environ['BLOCKREQ_API_KEY']}" async def main() -> None: async with websockets.connect(URL, max_size=None) as ws: await ws.send(json.dumps({"jsonrpc": "2.0", "id": 1, "method": "eth_subscribe", "params": ["blockreq_newBlocks"]})) last_number = None async for raw in ws: message = json.loads(raw) if "error" in message: print(message["error"]["code"], message["error"]["message"]) return if message.get("method") != "eth_subscription": print("subscription id:", message["result"]) continue block = message["params"]["result"] number = int(block["number"], 16) if last_number is not None and number > last_number + 1: print(f"blocks {last_number + 1}..{number - 1} were not pushed; fetch them with eth_getBlockByNumber") last_number = number print(number, block["hash"], f"{len(block['transactions'])} transactions") asyncio.run(main())

max_size=None 解除 websockets 库默认的 1 MiB 单条消息上限,以太坊的一个块可能超过它。

错误

被拒绝的订阅不计 Request。

错误码何时出现怎么办
-32601该链不提供此订阅,或连接没有 API key(公开端点)。消息为 subscription blockreq_newBlocks is not available on this network or endpoint。在支持的链上使用带 key 的端点。
-32000这个网络的订阅容量暂时已满。消息以 blockreq_newBlocks subscriptions are temporarily unavailable on this network 开头,并建议稍后再试。稍后再订阅一次。

Request 计数

  • eth_subscribe 本身计 1 个 Request,与其他请求相同。
  • 推送给你的每条整块通知计 2 个 Request:它替代的那条 newHeads 通知,加上你原本要自己发出的取块调用。没有推送给你的块不计数。
  • 被拒绝的订阅不计数。

通用规则见 Request Counting。

重组与缺口

该订阅跟随 newHeads:

  • 发生重组后,替换它的新块会在到达时照常推送,所以你可能收到两个 number 相同的块。请用 number 和 parentHash 判断哪些块在你的链上。
  • 如果节点没能在时限内给出某个块的内容,这个块就不会推送,你会看到块号跳变。被跳过的块之后不会补发,重新连接后也不会回放。需要每个块都不漏时,请把每条通知的 number 与上一条比较,并用 eth_getBlockByNumber 补取缺失的块。

消息体积

整块比链头大得多。Ethereum 的一个块约 0.5–0.7 MB JSON,BNB Smart Chain 约 0.1 MB,其余链的块从几 KB 到几十 KB。消息不压缩。读得太慢的客户端会被断开,规则与其他订阅相同,所以请在消息到达时就读走,把耗时的处理放到套接字循环之外。

与 newHeads 的区别

newHeadsblockreq_newBlocks
以太坊标准订阅是否,BlockReq 扩展
通知内容区块头带完整交易对象的整个块
获取交易每个链头再调用一次 eth_getBlockByHash已在通知里
每条通知计的 Request12
支持的链所有支持 WSS 的链上面列出的六条链
访问方式公开端点或带 key 端点仅带 key 端点
消息体积区块头整个块,最大约 0.7 MB

只需要知道有新块时用 newHeads;要读取每个新块的交易时用 blockreq_newBlocks。