guide10 min read

Rootstock Mainnet RPC for Wallet Builders

Rootstock mainnet RPC checks for wallets: chain ID 30 / 0x1e, RBTC gas, EIP-1191 checksums, confirmation counts, and public endpoints that passed 8 probes.

By RPC Directory•
#Rootstock#RSK#RBTC#RPC#Wallet#Chain ID#Bitcoin#EVM
$rootstock-mainnet-rpc.md

Rootstock is an EVM chain merge-mined with Bitcoin. Gas is paid in RBTC, a Bitcoin-pegged token, not ETH. The node software is RSKj, not Geth, so the JSON-RPC surface is close to Ethereum but not identical. Wallet builders who copy an Ethereum config, reuse Ethereum checksums, or wait for a finalized tag will hit errors that Ethereum mainnet never shows.

This is not a ranking of providers. Use the Rootstock mainnet hub to compare public endpoints and paid rows, then run the checks below on the URL you configure. The Rootstock mainnet providers page lists the keyed options side by side.

Chain ID 30 is mainnet, 31 is testnet

  • Rootstock mainnet: chain ID 30, hex 0x1e. This is what eth_chainId returns and what EIP-155 signatures use. net_version on the official public node returned "30" during the test.
  • Rootstock testnet: chain ID 31, hex 0x1f, with tRBTC as the gas token.
  • Ethereum mainnet: chain ID 1. A wallet that already has Ethereum added still needs a separate Rootstock network entry.

Wallet-add fields for mainnet, matching the Rootstock MetaMask guide:

  • Network name: Rootstock Mainnet
  • Chain ID: 30 (or 0x1e if the form wants hex)
  • Currency symbol: RBTC
  • RPC URL: a JSON-RPC HTTPS endpoint you have already probed, such as the official https://public-node.rsk.co
  • Block explorer: https://explorer.rootstock.io

RBTC balances use 18 decimals in JSON-RPC, like ETH. The bridge contract's eth_getBalance returned about 20.99 million RBTC during the test, against the 21,000,000 total supply in the rBTC docs. Call eth_chainId on the exact URL you will ship and expect 0x1e. A gateway that returns 0x1f is testnet. A timeout, an HTML page, a paid-plan error, or a rate-limit body is not a working Rootstock mainnet transport.

Public endpoints that answered eth_chainId

We probed every public Rootstock mainnet URL on the hub 8 times, about 55 seconds apart, on 2026-10-08 between 02:11 and 02:18 UTC. Each round called eth_chainId, eth_getBlockByNumber("latest"), eth_getBalance on the PowPeg bridge contract, and an eth_call for the RIF token's totalSupply(), with a curl User-Agent on every request. The hub lists 7 HTTPS and 1 WSS transports. These passed eth_chainId, the latest block, and a balance read in 8 of 8 rounds:

EndpointTransportNotes
https://public-node.rsk.coHTTPSOfficial RootstockLabs public node. Head 30 to 79 seconds old, never behind the median
https://mycrypto.rsk.coHTTPSSame head as the official node in every round
https://rootstock.drpc.org / wss://rootstock.drpc.orgHTTPS, WSSThe only WSS row that passed. Returns HTTP 403 (Cloudflare error 1010) to Python urllib's default User-Agent, so set a User-Agent on server-side clients. Node's built-in fetch, Go net/http, requests with no User-Agent, curl, axios, requests, httpx, and a browser User-Agent string worked
https://30.rpc.thirdweb.comHTTPSSame Python urllib HTTP 403 as DRPC. The other clients above worked
https://rsk-mainnet.gateway.tatum.ioHTTPSeth_call returned JSON-RPC -16401 "available for paid plans only" in 8 of 8 rounds, and a separate burst hit a 5 requests per minute limit. Fine for a chain ID check, not for token balances

Two rows failed all 8 rounds, and the directory now hides them. Blast API's Rootstock URL returned -32000 "Blast API is no longer available" on every call. lb.routeme.sh/rpc/evm/30 answered eth_chainId in 3 rounds but returned the -32029 public rate-limit error on the block read in all 8. A row on a directory page is a starting point, not proof it serves Rootstock today.

What the RSKj JSON-RPC does differently

Rootstock nodes run RSKj. The supported methods table covers the usual eth_ reads and writes, plus rsk_, debug_, trace_, and txpool_ modules. web3_clientVersion on the official node returned RskJ/9.0.3/Linux/Java17/VETIVER-c19cf12 during the test. DRPC answered the same method with Geth/v10.0.0/drpc, so do not use that string to detect the backend.

Calls that behaved differently from Ethereum on both public-node.rsk.co and rootstock.drpc.org:

  • eth_getBlockByNumber("finalized") and ("safe") returned JSON-RPC -32602 "invalid blocknumber". Libraries or indexers that default to those tags will error.
  • eth_feeHistory and eth_maxPriorityFeePerGas returned -32601 "method not found".
  • eth_getBlockByNumber("pending") returned a block object with a null number. The docs mark pending as not supported on several methods, including eth_getCode and eth_getBlockByNumber.

The official public nodes are HTTP only. Rootstock's public nodes page says they do not expose WebSockets and points to your own node, the keyed Rootstock RPC API, or a third-party provider instead. In the probe, wss://rootstock.drpc.org was the only public WSS transport on the hub.

Finality: count confirmations, not tags

Rootstock blocks are merge-mined with Bitcoin under DECOR+, a variant of Nakamoto consensus, per the Rootstock FAQ. Finality is probabilistic. There is no finality gadget behind a finalized tag, which matches the -32602 error above. The FAQ recommends a minimum of 12 confirmations for payments, about 6 minutes, and more for larger amounts.

Measured on the official node during the test, the last 200 blocks spanned 6,292 seconds, about 31.6 seconds per block. 124 of those 200 blocks referenced at least one uncle, 217 uncles in total. Competing blocks at the tip are routine, so treat a latest receipt as pending until it has the confirmation depth your product needs.

PowPeg timing is separate from send finality. Rootstock's conversion guide lists 100 Bitcoin confirmations for a mainnet peg-in and 4,000 Rootstock blocks for a peg-out release. Do not reuse those numbers as the confirmation count for ordinary RBTC or token transfers.

Fees: minimumGasPrice plus a buffer

Rootstock does not use an EIP-1559 base fee. Block headers carry a minimumGasPrice field that miners can move by up to 1% per block, as described in the gas docs. Blocks returned by the official node had no baseFeePerGas field.

During the test on the official node:

  • The latest block's minimumGasPrice was 0x1699280 (23,696,000 wei, about 0.0237 gwei).
  • eth_gasPrice returned 0x18dbac0 (26,065,600 wei), about 10% above that minimum.
  • eth_estimateGas for a plain RBTC transfer returned 0x5208 (21,000).
  • The latest block's gasLimit was 10,000,000. The FAQ still cites 6.8M, so read the live header if a limit matters.

What that means for a wallet:

  • Price from eth_gasPrice or minimumGasPrice plus about 10%. The gas docs call raw minimumGasPrice the optimistic choice and suggest adding 10%. A transaction priced below the next block's minimum can be rejected.
  • Do not expect EIP-1559 fields. With no baseFeePerGas and no eth_feeHistory, fall back to a single gasPrice instead of maxFeePerGas and maxPriorityFeePerGas math.
  • Peg-out sends are special. The conversion guide asks for a manual 100,000 gas limit on RBTC sent to the bridge contract 0x0000000000000000000000000000000001000006.

Addresses, checksums, and derivation paths

Rootstock implements EIP-1191, a checksum that mixes the chain ID into the uppercase and lowercase pattern. A mixed-case address checksummed for Ethereum can fail validation in a Rootstock-aware wallet, and the reverse. The FAQ notes that the node does not enforce it, so the check lives in your client.

The docs list the mainnet derivation path as m/44'/137'/0'/0/N (coin type 137) and testnet as m/44'/37310'/0'/0/N. Wallets that use Ethereum's m/44'/60' path, such as MetaMask, derive different addresses from the same seed phrase. Whichever path you ship, document it and keep it fixed so users can restore funds in another wallet.

MetaMask, Rabby, and Rainbow

The Rootstock wallet compatibility matrix shows which wallets support the Rootstock checksum and derivation path.

  • MetaMask: does not support EIP-1191 checksums and uses the Ethereum derivation path. The docs suggest lowercasing addresses copied from MetaMask and warn that some screens may show ETH instead of RBTC. When a dapp calls wallet_switchEthereumChain for an unknown chain, MetaMask returns error 4902, so follow up with wallet_addEthereumChain.
  • Rabby: the matrix shows no Rootstock checksum and no Rootstock derivation path. Check whether Rootstock is already in Rabby's network list before adding a custom entry.
  • Rainbow: the matrix shows both the Rootstock checksum and the Rootstock derivation path.

For wallet_addEthereumChain, send a full EIP-3085 payload: chainId: "0x1e", chainName: "Rootstock Mainnet", nativeCurrency: { name: "RBTC", symbol: "RBTC", decimals: 18 }, rpcUrls with your probed HTTPS endpoint, and blockExplorerUrls: ["https://explorer.rootstock.io"]. For wallet_switchEthereumChain, send only { chainId: "0x1e" }.

Wallet-add gotchas that show up in QA

  1. Chain ID 31 in the mainnet row: the label says Rootstock but signatures target testnet.
  2. Ethereum checksums on display: EIP-1191 validators reject them, or users paste a lowercase address into a strict field.
  3. Mixed derivation paths: one build uses coin type 137 and another uses 60, so restored wallets show empty balances.
  4. Waiting on finalized: the call errors instead of returning a block. Count confirmations instead.
  5. EIP-1559 fee code paths: eth_feeHistory is missing, so fee estimation must fall back to gasPrice.
  6. Token balances through Tatum's public URL: eth_call is paid-only there, so ERC-20 balances come back as errors.
  7. WebSocket on the official node: it is HTTP only. Use a provider WSS or poll.

Public vs dedicated for wallet traffic

RootstockLabs describes its public nodes as being for testing and recommends running your own node or using another provider for production. Its keyed Rootstock RPC API has a daily limit of 25,000 requests per user, with up to 4 API keys.

Public endpoints are fine for:

  • Local development and wallet QA
  • Low-volume eth_chainId and eth_blockNumber probes
  • One-off scripts and docs examples

They are a poor primary path when you:

  • Run production wallet RPC for many users (balance, nonce, fee estimate, send, receipt polls)
  • Need WebSocket subscriptions, since the official nodes are HTTP only
  • Depend on eth_call for token balances on a gateway that gates it behind a paid plan
  • Cannot absorb shared-node rate limits during a launch or market spike

Probe the candidate URL before you call it ready:

  1. eth_chainId returns 0x1e.
  2. The latest block advances over a minute or two, and its timestamp is within about a minute of wall-clock time.
  3. A plain transfer eth_estimateGas returns 0x5208 (21,000).
  4. An eth_call on a token contract you care about returns data, not a paid-plan error.
  5. A burst of 20 to 50 quick requests does not return HTTP 429 or a JSON-RPC rate-limit error at the volume you expect.
  6. If you call from Python's urllib or another client without a library User-Agent, confirm the URL still answers, or set one.

For production wallet traffic, compare the paid rows on the same hub for method coverage, WebSocket support, and quota. At the time of writing those include Alchemy and DRPC. A cheaper URL that fails the probe above is not a savings.

The public vs paid guide covers when a shared endpoint stops being enough, and the pricing calculator estimates monthly cost for a request mix. Log-heavy indexers should read the eth_getLogs caps guide, and the dead public endpoints guide explains why listed URLs stop answering.

Practical split for a wallet stack

  • User-facing Rootstock network row: chain ID 30 / 0x1e, RBTC symbol, explorer.rootstock.io, an RPC you probed today.
  • Address handling: EIP-1191 checksums with chain ID 30, one documented derivation path, lowercase fallback for MetaMask copies.
  • Confirmations: block-number counting, at least 12 for payments per the FAQ, more for large amounts. No safe or finalized tags.
  • Fee estimation: eth_gasPrice or minimumGasPrice plus about 10%, refreshed per send.
  • Backend / indexer: dedicated or paid endpoint with WebSocket and full eth_call support. Do not share the browser wallet's public URL.

Ship the hub comparison and the probe first. A network called "Rootstock" in a dropdown does not replace eth_chainId returning 0x1e.