> For the complete documentation index, see [llms.txt](https://docs.rome.builders/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rome.builders/zh/kai-fa-zhe-zhi-nan/websocket-subscriptions.md).

# WebSocket 订阅

通过 WebSocket 订阅 Rome EVM 事件——使用带有 newHeads 和 logs 的 eth\_subscribe，配合 ethers 可开箱即用；使用 viem 时，请使用轮询。

Rome EVM 端点支持 Ethereum WebSocket 订阅 (`eth_subscribe` / `eth_unsubscribe`），涵盖 `wss://`. 连接到与 HTTPS RPC 相同的主机，并使用 `wss://` 协议：

```
wss://<chain>.<network>.romeprotocol.xyz/
```

这就是 `ethers` `WebSocketProvider` 在底层使用的实现，因此 `.on('block')` 和 `contract.on(event)` 可直接使用。 `viem` 只需一个设置，详见 [viem](#viem) 部分。

## 订阅类型

| 类型                       | 触发于                 | 适用于                           |
| ------------------------ | ------------------- | ----------------------------- |
| `newHeads`               | 每个新区块               | 区块轮询、刷新余额/nonce、按区块运行的机器人、索引器 |
| `logs`                   | 匹配事件（按 `地址` / `主题`) | 响应合约事件、中继器/跨链桥、交易机器人          |
| `newPendingTransactions` | —                   | 会被接受但从不发出（Rome 没有公共内存池）       |

## ethers（v6）

```javascript
import { ethers } from "ethers";

const provider = new ethers.WebSocketProvider(
  "wss://hadrian.testnet.romeprotocol.xyz/"
);

// newHeads
provider.on("block", (blockNumber) => {
  console.log("new block", blockNumber);
});

// logs — 响应合约事件
const contract = new ethers.Contract(address, abi, provider);
contract.on("Transfer", (from, to, value) => {
  console.log("Transfer", from, to, value.toString());
});
```

## viem

`viem`的 `webSocket` transport 只有在 id 为字符串时才会注册订阅。Rome 返回的是数字，因此 `watchBlocks` 通过普通的 `webSocket` transport 什么也收不到。请传入 `poll: true` 和 `viem` 而是通过连接轮询（已用 `watchBlocks`）进行检查，或者使用 `ethers` 以获取推送更新。

```javascript
import { createPublicClient, webSocket } from "viem";

const client = createPublicClient({
  transport: webSocket("wss://hadrian.testnet.romeprotocol.xyz/"),
});

const unwatch = client.watchBlocks({
  poll: true,
  onBlock: (block) => console.log("new block", block.number),
});

client.watchEvent({
  poll: true,
  address,
  onLogs: (logs) => console.log(logs),
});
```

## 原始 JSON-RPC

```json
→ {"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["newHeads"]}
← {"jsonrpc":"2.0","id":1,"result":8704545703806774}            // subscription id
← {"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":8704545703806774,"result":{…block…}}}
```

订阅 ID 是 JSON 数字，而不是十六进制字符串，通知携带的也是同一个数字。 `ethers` 会为你处理这一点。 `viem`的 `webSocket` transport 只接受字符串 id，因此会丢弃这些通知（参见 [viem](#viem)）。如果你编写原始客户端，请将 id 按数字比较，并将该数字再传回 `eth_unsubscribe`.

对于 `logs`，请将过滤器对象作为第二个参数传入：

```json
{"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["logs",{"address":"0x…","topics":["0x…"]}]}
```

## 说明

* 当新区块生成时，订阅会推送更新（延迟大致相当于一个区块时间）。
* 对于长连接，请在客户端处理重连——这对任何 WebSocket RPC 都是标准做法。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.rome.builders/zh/kai-fa-zhe-zhi-nan/websocket-subscriptions.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
