guide11 min read

Unichain Mainnet RPC for Wallet Builders

What to check before a wallet points at Unichain mainnet: chain ID 130 / 0x82, ETH gas, 1-second blocks, Flashblocks and the pending tag, OP Stack safe and finalized tags, public endpoints that passed an 8-round probe, and public vs dedicated RPC.

By RPC Directory•
#Unichain#ETH#RPC#Wallet#Chain ID#OP Stack#Flashblocks
$unichain-mainnet-rpc.md

Unichain is an OP Stack Layer 2 on Ethereum built by Uniswap Labs, with 1-second blocks and Flashblocks preconfirmations. Gas is paid in ETH, so the fee symbol looks familiar, but the chain is not Ethereum mainnet and not Unichain Sepolia. Wallet builders who paste chain ID 1, reuse the Sepolia key, or read nonces from the wrong block tag will ship the wrong network or stuck transactions. Prove chain ID 130 and probe the URL first.

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

Chain ID 130 is not Ethereum and not Unichain Sepolia

  • Unichain mainnet: chain ID 130, hex 0x82. This is what wallets, eth_chainId, and EIP-155 signatures use. net_version returns 130.
  • Unichain Sepolia testnet: chain ID 1301, hex 0x515, RPC https://sepolia.unichain.org, explorer https://sepolia.uniscan.xyz.
  • Ethereum mainnet: chain ID 1. A wallet that already has Ethereum added still needs a separate Unichain network entry.

Wallet-add fields for mainnet, matching Unichain's published network information:

  • Network name: Unichain
  • Chain ID: 130 (or 0x82 if the form wants hex)
  • Currency symbol: ETH
  • RPC URL: a JSON-RPC HTTPS endpoint you have already probed, such as the official https://mainnet.unichain.org
  • Block explorer: https://uniscan.xyz

Native gas is ETH with 18 decimals, the same unit as on Ethereum, and the native balance is read with eth_getBalance. Because the symbol matches Ethereum, the network name is the only thing that tells a user which chain they are on. Show it next to every balance and fee, or users will assume the ETH they see is on L1. Wrapped ETH sits at the standard OP Stack predeploy 0x4200000000000000000000000000000000000006.

Call eth_chainId on the exact RPC URL you will ship. Expect 0x82. A gateway that returns 0x515 is Sepolia. A gateway that returns 0x1 is Ethereum. A timeout, an HTML page, a 404, or a rate-limit body is not Unichain mainnet for that transport. Run the check after any load balancer or fallback so you test the backend production actually hits.

Public endpoints that answered eth_chainId

We probed every public Unichain mainnet URL on the hub and in Unichain's docs 8 times, about 55 seconds apart, on 2026-10-06 between 02:12 and 02:19 UTC. Each round called eth_chainId, eth_getBlockByNumber("latest"), and eth_getBalance on the WETH predeploy. The URLs below passed all three calls in 8 of 8 rounds. Nodeflare passed 8 of 8 in a second run with a curl User-Agent, explained in its row:

EndpointTransportNotes
https://mainnet.unichain.orgHTTPSOfficial, rate limited. Head block was 3 to 4 seconds old, 2 to 3 blocks behind most other URLs
https://unichain-rpc.publicnode.com / wss://unichain-rpc.publicnode.comHTTPS, WSSHead 0 to 1 seconds old
https://unichain.drpc.org / wss://unichain.drpc.orgHTTPS, WSSHead 0 to 1 seconds old
https://130.rpc.thirdweb.comHTTPSHead 3 to 4 seconds old, same height as the official RPC in every round
https://rpc.sentio.xyz/unichain-mainnet / https://unichain-mainnet.rpc.sentio.xyzHTTPSHead 0 to 1 seconds old
https://rpc.swiftnodes.io/rpc/unichainHTTPSHead 0 to 1 seconds old
https://unichain-mainnet.gateway.tatum.ioHTTPSHead 0 to 1 seconds old
https://unichain.api.onfinality.io/publicHTTPSHead 0 to 1 seconds old. Returned HTTP 429 to a short burst of extra calls outside the probe
https://rpc.nodeflare.app/unichain/publicHTTPS8 of 8 with a curl User-Agent (02:53 to 03:00 UTC), head under 1 second old. Returns HTTP 403 to some default User-Agents (Node's built-in fetch, Python urllib, Go net/http) and to requests with none, so set a User-Agent on server-side clients. Browsers, curl, ethers, axios, and python-requests worked

Five other rows did not pass every round. Four failed all 8 with an HTTP 404 or a reset connection, also with a curl User-Agent, and the directory now hides them. lb.routeme.sh/rpc/evm/130 passed 3 of 8 rounds and returned a public rate-limit error on the rest, so it stays listed with that caveat. A row on a directory page is a starting point, not proof it serves Unichain mainnet today.

Unichain's docs state that https://mainnet.unichain.org and https://sepolia.unichain.org are rate limited and not intended for production. Treat the table as a probe list for development and QA, not as a production recommendation.

Flashblocks and the pending tag

Unichain produces a block every second. During the test, 100 consecutive blocks spanned exactly 100 seconds. Flashblocks add partial block updates about every 200 ms. Unichain's docs say apps read them with the pending tag on standard methods such as eth_getBlockByNumber, eth_getBalance, eth_call, and eth_getTransactionCount, and that the public RPC URLs are Flashblocks-aware.

The pending tag is where the endpoints disagreed most. In 10 samples per URL, 3 seconds apart, at 02:19 UTC:

  • mainnet.unichain.org: pending returned a block 3 to 5 ahead of eth_blockNumber in 3 samples. In the other 7 it returned a block between 12,503 and 1,063,220 blocks old, roughly 3.5 hours to 12 days.
  • 130.rpc.thirdweb.com: pending returned an old block in 10 of 10 samples.
  • unichain-rpc.publicnode.com: pending was 0 or 1 block ahead in 10 of 10 samples.

The same split showed up in nonces. For a busy sender address, eth_getTransactionCount(address, "pending") came back between about 88,000 and 7.4 million below the latest nonce in 8 of 12 reads on the official RPC and 12 of 12 on thirdweb. PublicNode never returned a pending nonce below latest.

For a wallet this matters more than head freshness. A nonce read from a stale pending block produces "nonce too low" errors, or a send queue that replays old nonces. Probe pending on your URL before relying on it. If results jump, read nonces from latest, track your own in-flight count, and use pending only where the endpoint has proved it serves Flashblocks state.

Fees on an OP Stack chain with 1-second blocks

During the test, eth_gasPrice returned 1,500,000 wei (0.0015 gwei), the base fee was 500,000 wei, and eth_maxPriorityFeePerGas returned 1,000,000 wei. eth_estimateGas for a plain ETH transfer returned 0x5208 (21,000) on both the official RPC and PublicNode.

Like other OP Stack chains, Unichain charges an L1 data fee on top of gasUsed * gasPrice. It does not consume gas limit and is deducted from the sender's balance. The GasPriceOracle predeploy at 0x420000000000000000000000000000000000000F returned an upper bound of 1,527,843,746 wei for a 110-byte transaction, about 5% of the 31,500,000,000 wei execution fee for a transfer at that gas price.

What that means for a wallet:

  • "Send max" needs the L1 fee. Subtract the execution fee and the getL1Fee or getL1FeeUpperBound result, or leave a small buffer, so the transaction does not fail on the last few wei.
  • Do not cap fees with Ethereum L1 defaults. A gas price of a few thousandths of a gwei is normal here. An L1-style minimum priority fee overpays by orders of magnitude.
  • Fee data moves fast. With 1-second blocks, refresh fee estimates per send, not once per session.

OP Stack quirks that matter for wallets

  • Three block tags, three heights. In a single read across eight URLs at 02:19 UTC, safe trailed latest by 166 to 178 blocks (about 3 minutes) and finalized by 1,356 to 1,368 blocks (about 23 minutes). One earlier read from the official RPC put safe 558 blocks back, so tag heights also vary by backend. Show a latest receipt as included, and reserve "final" for UI that needs L1-backed finality.
  • Canonical withdrawals are a multi-step L1 flow. Unichain is a Stage 1 rollup with permissionless fault proofs. Withdrawals through the standard bridge need a prove step, a challenge window, and a finalize transaction on Ethereum. Third-party bridges listed in Unichain's docs, such as Across and Relay, have their own timing.
  • Address aliasing on L1 to L2 messages. For deposits and other L1-initiated transactions, msg.sender on L2 is the aliased L1 address, as on upstream OP Stack. This matters to contract wallets and allowlists, not to ordinary EOAs.
  • Standard JSON-RPC otherwise. Unichain documents the usual Ethereum methods, including eth_feeHistory, eth_getBlockReceipts, and eth_getProof. The official RPC returned HTTP 403 to web3_clientVersion, so do not use that call as a health check.

MetaMask, Rabby, and Rainbow

All three accept Unichain as an EVM network with the fields above. What to expect:

  • MetaMask: the add-network form takes the five fields directly. When a dapp calls wallet_switchEthereumChain for a chain MetaMask does not know, it returns error 4902. Handle that by calling wallet_addEthereumChain.
  • Rabby: check whether Unichain already appears in Rabby's network list before adding a custom entry, so you do not end up with two Unichain rows pointing at different RPCs.
  • Rainbow: accepts the same EIP-3085 add request from a dapp. If your dapp connects wallets with RainbowKit or wagmi, define Unichain with the fields above and confirm the explorer URL is uniscan.xyz.

For wallet_addEthereumChain, send a full EIP-3085 payload: chainId: "0x82", chainName: "Unichain", nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, rpcUrls with your probed HTTPS endpoint, and blockExplorerUrls: ["https://uniscan.xyz"]. For wallet_switchEthereumChain, send only { chainId: "0x82" }. Prefer one primary RPC in the wallet payload and keep failover in your own client.

A browser wallet computes its own fees and nonces from the RPC in its network entry. If that entry points at a URL with a stale pending tag, the wallet inherits the problem. That is one more reason to probe the URL you put in the add-network payload.

Wallet-add gotchas that show up in QA

  1. Chain ID 1 in the Unichain row: the network name says Unichain but signatures target Ethereum.
  2. Sepolia mix-up: 1301 / 0x515 pasted into a mainnet config, or a Sepolia RPC behind a mainnet label.
  3. ETH balances without a network label: users read the balance as L1 ETH.
  4. Nonce from a stale pending tag: "nonce too low" on send, or a queue that never clears.
  5. Fee shown from estimateGas only: understates the total by the L1 data fee.
  6. One shared "unichain" RPC key for mainnet and testnet: separate config keys so a fallback cannot silently swap networks.

Public vs dedicated for wallet traffic

Public endpoints are fine for:

  • Local development and wallet QA
  • Low-volume eth_chainId / 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 predictable latency and a support channel when the gateway rate limits you
  • Depend on Flashblocks pending state, historical state, wide eth_getLogs, or sustained WebSocket traffic
  • Cannot absorb shared-node brownouts during a launch, airdrop, or market spike

Probe the candidate URL before you call it ready:

  1. eth_chainId returns 0x82.
  2. The latest block advances when you poll twice a few seconds apart, and its timestamp is within a few seconds of wall-clock time.
  3. eth_getBlockByNumber("pending") stays within a few blocks of eth_blockNumber across ten polls, if you use Flashblocks.
  4. eth_getTransactionCount with pending is never below latest for an address you control.
  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 per client.
  6. If you need push updates, a WebSocket eth_subscribe that survives a disconnect.

Public rows on the hub are shared and rate-limited. Use them for the probe. For production wallet traffic, compare the paid rows on the same hub for method coverage, Flashblocks support, archive access, and quota. At the time of writing those are Alchemy, Chainstack, DRPC, Infura, and Dwellir. Dwellir's row is a keyed Unichain mainnet endpoint over HTTPS and WSS, billed as one response credit per call on every method. It is not the only option.

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 given request mix. Log-heavy indexers should also 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 Unichain network row: chain ID 130 / 0x82, ETH symbol with the network name shown, Uniscan, RPC you probed today.
  • Unichain Sepolia row: chain ID 1301 / 0x515, separate config key, never reused as the mainnet RPC.
  • Nonce and Flashblocks reads: pending only on an endpoint that passed the pending checks above, with latest plus a local in-flight counter as the fallback.
  • Fee estimation: execution fee plus the GasPriceOracle L1 fee, refreshed per send.
  • Backend / indexer: dedicated or paid endpoint with explicit method and archive needs. Do not share the browser wallet's public URL.

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