> 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/developer-guides/websocket-subscriptions.md).

# WebSocket Subscriptions

Subscribe to Rome EVM events over WebSocket — eth\_subscribe with newHeads and logs, working out of the box with ethers; with viem, use polling.

Rome EVM endpoints support Ethereum WebSocket subscriptions (`eth_subscribe` / `eth_unsubscribe`) over `wss://`. Connect to the same host as the HTTPS RPC, with the `wss://` scheme:

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

This is what the `ethers` `WebSocketProvider` uses under the hood, so `.on('block')` and `contract.on(event)` work out of the box. `viem` needs one setting, described in the [viem](#viem) section.

## Subscription types

| Type                     | Fires on                                  | Use for                                                             |
| ------------------------ | ----------------------------------------- | ------------------------------------------------------------------- |
| `newHeads`               | each new block                            | block tickers, refreshing balances/nonces, per-block bots, indexers |
| `logs`                   | matching events (by `address` / `topics`) | reacting to your contract's events, relayers/bridges, trading bots  |
| `newPendingTransactions` | —                                         | accepted but never emits (Rome has no public mempool)               |

## 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 — react to a contract event
const contract = new ethers.Contract(address, abi, provider);
contract.on("Transfer", (from, to, value) => {
  console.log("Transfer", from, to, value.toString());
});
```

## viem

`viem`'s `webSocket` transport registers a subscription only when the id is a string. Rome returns a number, so `watchBlocks` over a plain `webSocket` transport receives nothing. Pass `poll: true` and `viem` polls over the connection instead (checked with `watchBlocks`), or use `ethers` for push updates.

```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),
});
```

## Raw 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…}}}
```

The subscription id is a JSON number, not a hex string, and the notifications carry the same number. `ethers` handles this for you. `viem`'s `webSocket` transport only accepts a string id, so it drops the notifications (see [viem](#viem)). If you write a raw client, compare ids as numbers and pass the number back to `eth_unsubscribe`.

For `logs`, pass a filter object as the second param:

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

## Notes

* Subscriptions push updates as new blocks are produced (latency is on the order of a block time).
* For long-lived connections, handle reconnects in your client — standard for any 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/developer-guides/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.
