RPC examples
Working code for the Supanode Robinhood Chain node: curl, ethers v6, viem, web3.py and wscat over HTTPS and WebSocket with x-token auth. Every example was run against the live endpoint.
// updated 2026-09-24
Every snippet here was run against the node on 24 September 2026 with ethers 6.17, viem 2.56, web3.py 8.0, ws 8.21 and wscat 6.1. Replace YOUR_TOKEN with your token.
Two headers on every HTTPS call: x-token: YOUR_TOKEN and Content-Type: application/json. Most libraries send the second one for you. web3.py does not when you pass your own headers - see below.
curl
curl -s https://ny01.rh.supanode.xyz:8545 \
-H "x-token: YOUR_TOKEN" -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
{"jsonrpc":"2.0","id":1,"result":"0x43eda90"}
ethers v6 (Node)
ethers takes the header through a FetchRequest for HTTPS, and through a ws socket factory for WebSocket.
import { ethers } from "ethers";
import WebSocket from "ws";
// HTTPS
const req = new ethers.FetchRequest("https://ny01.rh.supanode.xyz:8545");
req.setHeader("x-token", "YOUR_TOKEN");
const provider = new ethers.JsonRpcProvider(req);
console.log(await provider.getBlockNumber()); // 71228555
console.log((await provider.getNetwork()).chainId); // 4663n
// WebSocket
const ws = new ethers.WebSocketProvider(() =>
new WebSocket("wss://ny01.rh.supanode.xyz:8546", { headers: { "x-token": "YOUR_TOKEN" } }));
ws.on("block", (n) => console.log("new block", n));
viem (Node)
import { createPublicClient, http, formatEther } from "viem";
const client = createPublicClient({
transport: http("https://ny01.rh.supanode.xyz:8545", {
fetchOptions: { headers: { "x-token": "YOUR_TOKEN" } },
}),
});
console.log(await client.getChainId()); // 4663
console.log(await client.getBlockNumber()); // 71261467n
console.log(formatEther(await client.getBalance({
address: "0x0000000000000000000000000000000000000000",
})));
viem's webSocket() transport has no option for headers. Without the header the handshake is rejected and viem reports "An unknown RPC error occurred". For WebSocket use ethers or web3.py. If you must stay on viem, the workaround below replaces the global WebSocket in Node with a ws subclass that adds the header. Import viem after the override.
import WS from "ws";
globalThis.WebSocket = class extends WS {
constructor(url, protocols) {
super(url, protocols, { headers: { "x-token": "YOUR_TOKEN" } });
}
};
const { createPublicClient, webSocket } = await import("viem");
const client = createPublicClient({ transport: webSocket("wss://ny01.rh.supanode.xyz:8546") });
client.watchBlocks({ onBlock: (b) => console.log("new block", b.number) });
web3.py 8
import asyncio
from web3 import Web3, AsyncWeb3, WebSocketProvider
# HTTPS: your headers replace web3.py's defaults, so Content-Type goes in too
w3 = Web3(Web3.HTTPProvider(
"https://ny01.rh.supanode.xyz:8545",
request_kwargs={"headers": {"Content-Type": "application/json", "x-token": "YOUR_TOKEN"}},
))
print(w3.eth.chain_id, w3.eth.block_number) # 4663 71261842
# WebSocket: newHeads
async def main():
async with AsyncWeb3(WebSocketProvider(
"wss://ny01.rh.supanode.xyz:8546",
websocket_kwargs={"additional_headers": {"x-token": "YOUR_TOKEN"}},
)) as w3:
await w3.eth.subscribe("newHeads")
async for msg in w3.socket.process_subscriptions():
print("new block", msg["result"]["number"])
asyncio.run(main())
Without Content-Type in request_kwargs the node answers 415 Unsupported Media Type.
wscat
npx wscat -c wss://ny01.rh.supanode.xyz:8546 -H "x-token: YOUR_TOKEN"
Then subscribe:
> {"jsonrpc":"2.0","id":1,"method":"eth_subscribe","params":["newHeads"]}
< {"jsonrpc":"2.0","id":1,"result":"0x8b9e63df4cf5b0919e691cbf5e3e1ddf"}
< {"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x8b9e...","result":{"number":"0x...", ...}}}
A filtered logs subscription on the same connection:
> {"jsonrpc":"2.0","id":2,"method":"eth_subscribe","params":["logs",{"address":"0x0bd7d308f8e1639fab988df18a8011f41eacad73"}]}
L2 block number from a contract call
Solidity block.number returns a parent-chain number on Arbitrum. The ArbSys precompile at 0x64 gives the L2 block:
curl -s https://ny01.rh.supanode.xyz:8545 \
-H "x-token: YOUR_TOKEN" -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"0x0000000000000000000000000000000000000064","data":"0xa3b1b31d"},"latest"]}'
0xa3b1b31d is the selector of arbBlockNumber().