Skip to content

WebSocket subscriptions

Subscribe to new heads and logs over the GraphOps RPC WebSocket endpoint.

Update balances, send notifications, or start jobs as new blocks and matching events arrive. This guide subscribes to USDC Transfer logs over WebSocket, then shows how to fill the gap with eth_getLogs when the connection drops, because a new subscription only delivers new events.

Prerequisites

  • A GraphOps RPC API key.
  • WebSocket access for the target chain.
  • A WebSocket client. Use route-token authentication when the client cannot send custom headers.
  • Durable progress tracking for the last processed block and log identity.

Subscribe to logs

This request subscribes to USDC Transfer logs over the Ethereum mainnet WebSocket endpoint. The endpoint uses route-token authentication, so the URL contains your API key; redact it from logs, metrics labels, and support output.

import WebSocket from "ws";

const socket = new WebSocket(
  "wss://rpc.graphops.xyz/v1/evm/1/<GRAPHOPS_API_KEY>",
);

socket.on("open", () => {
  socket.send(
    JSON.stringify({
      jsonrpc: "2.0",
      id: 1,
      method: "eth_subscribe",
      params: [
        "logs",
        {
          address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
          topics: [
            "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
          ],
        },
      ],
    }),
  );
});

socket.on("message", (message) => {
  const payload = JSON.parse(message.toString());
  console.log(payload);
});

Response

The first message confirms the subscription and returns its id:

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

Each matching log then arrives as a notification:

{  "jsonrpc": "2.0",  "method": "eth_subscription",A notification, not a reply  "params": {    "subscription": "0x9cef478923ff08bf67fde6c64013158d",The id eth_subscribe returned    "result": {One log, shaped like an eth_getLogs entry      "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",      "topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],      "data": "0x00000000000000000000000000000000000000000000000000000001dcd65000",      "blockNumber": "0x112a880",Store as your last processed block      "transactionHash": "0xde0ca4c3db355459e8573d7d6f6373256ef1e883e331f3aaf9e4cb8bd668138d",      "logIndex": "0x3d",      "removed": falsetrue when a reorg reverses this log    }  }}
A notification for the USDC Transfer subscription. Notifications have no id; match them to your subscription by the subscription field.

Use a client library

Client libraries manage the subscription for you. Each example uses the route-token WebSocket endpoint; the curl tab shows the HTTPS backfill request you send after a disconnect.

curl cannot hold a subscription. Use it for the HTTPS backfill request that fills a gap:

curl "https://rpc.graphops.xyz/v1/evm/1" \
  -H "Authorization: Bearer <GRAPHOPS_API_KEY>" \
  -H "Content-Type: application/json" \
  --data '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getLogs",
    "params": [
      {
        "fromBlock": "0x112a880",
        "toBlock": "0x112a880",
        "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        "topics": [
          "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
        ]
      }
    ]
  }'

Supported subscriptions

SubscriptionUse it for
newHeadsNew block headers.
logsLogs matching an address and topic filter.
newPendingTransactionsPending transaction hashes when available for the network.
syncingNode sync status updates.

Recover after a disconnect

Blocks N+2 and N+3 were produced while the socket was down, and a new subscription only delivers events from N+4 onward. One bounded eth_getLogs request fills the gap; deduplicate by log identity where the ranges meet.
  1. Store the last processed block and log identity as you handle each notification.
  2. Reconnect with exponential backoff after a disconnect.
  3. Resubscribe with the same filter.
  4. Backfill with eth_getLogs from the block after the last one you processed up to the first block the new subscription delivers.
  5. Deduplicate by (blockHash, transactionHash, logIndex) where the backfill and the live stream overlap.
  6. Treat logs with removed: true as reversals. See Retries and reorgs.

Next steps