Blast is an OP Stack Layer 2 on Ethereum, not "Ethereum with a different RPC URL." It also changes one thing no other mainstream L2 changes: native ETH on Blast is rebasing, so an ordinary wallet balance can grow without a transaction. Wallet builders who paste chain ID 1, reuse a Blast Sepolia config key, trust any hostname with "blast" in it, or rebuild balances from transfer history will ship the wrong network or a balance that drifts. Before you wire MetaMask, Rabby, Rainbow, or your own wallet_addEthereumChain flow, prove chain ID 81457, separate L1 from L2, and probe the URL you intend to ship.
This is not a ranking of providers. Use the Blast Mainnet hub to compare endpoints and paid rows, then run the checks below on the URL you configure. If you only need the network in a browser wallet, the add Blast to MetaMask and add Blast to Rainbow pages have the fields prefilled.
Chain ID 81457 is not Ethereum and not Blast Sepolia
Mainnet chain ID is 81457, hex 0x13e31. Blast Sepolia is 168587773 / 0xa0c71fd. Ethereum mainnet is 1. Those are different networks. A wallet that already has Ethereum added still needs a separate Blast network entry.
Wallet-add fields for mainnet:
- Network name:
Blast(orBlast Mainnetif the product already scopes the list) - Chain ID:
81457(or0x13e31if the form wants hex) - Currency symbol:
ETH - RPC URL: a JSON-RPC HTTPS endpoint you have already probed
- Block explorer:
https://blastscan.io
Native gas is ETH with 18 decimals, same symbol as Ethereum L1 and most Ethereum L2s. Show the network name and chain ID in the UI, not the symbol alone, or users will not know which "ETH" balance they are looking at.
Call eth_chainId on the exact RPC URL you will ship. Expect 0x13e31. A gateway that returns 0x1 is Ethereum. A gateway that returns 0xa0c71fd is Blast Sepolia. A timeout or an HTML error page is not Blast mainnet for that transport. Run the check after any load balancer or fallback so you are testing the backend production actually hits. The official public RPC is https://rpc.blast.io (already on the hub); treat it as a probe target, not as proof that every branded gateway behind a "Blast" label serves this chain.
"Blast" in a hostname is not a chain ID check
The name is crowded, which makes the eth_chainId probe more important here than on most chains:
- Other chains share the name. When this guide was written, at least one URL with "blast" in the hostname returned chain ID
0xee(238), not0x13e31. It answers valid JSON-RPC, so a liveness check alone will pass it. - Blast API is a provider brand, not the Blast network. Endpoints on
blastapi.ioserved many chains, including Blast. Its public Blast mainnet URL now returns a deprecation error instead of a result. Configs copied from older tutorials still point at it. - Keyed gateways fail quietly. Some provider URLs for Blast now require an API key and return a 403-style JSON error without one. That is not an outage; it is a URL you cannot ship unauthenticated.
Treat every candidate URL the same way: eth_chainId first, then a head that moves, then a real read.
OP Stack and Blast quirks that matter for wallets
Blast runs on the Optimism OP Stack with Ethereum as the parent chain, plus Blast-specific changes to native ETH. Both reach the wallet layer:
- Rebasing ETH for EOAs. Externally owned accounts default to automatic yield, so their ETH balance increases on yield distribution without a
Transferevent or a transaction. Read balances witheth_getBalanceat the block you display. Do not reconstruct them from transaction history, or the number will drift below what the chain reports. - Smart contract accounts behave differently. Contracts default to a void yield mode (balance does not rebase) unless they opt in through the Blast yield predeploy at
0x4300000000000000000000000000000000000002. A smart wallet and an EOA holding the same deposit can show different balance behavior over time. That is expected, not an RPC bug. - USDB also rebases for EOAs. If the wallet shows token balances, call
balanceOfrather than summing transfer logs. - Confirmation tags follow OP Stack semantics.
latestis the unsafe sequencer head,safeis derived from L1 data, andfinalizedfollows L1 finality. On a healthy public endpoint the three heights differ by hundreds of blocks. Do not copy "wait N Ethereum blocks" heuristics into a Blast receipt poller without checking what your RPC returns for those tags. - Deposits and withdrawals go through the Blast bridge against Ethereum L1, and withdrawals to L1 wait out a multi-day challenge window before they can be finalized on Ethereum. Bridge UX needs an L1 RPC policy even when the dapp only calls Blast for day-to-day sends.
- Contract addresses are not portable from Ethereum. The same dapp on Ethereum and Blast uses different deployments. Hard-coding an Ethereum token or router address into a Blast wallet path is a funds bug.
- Not Base. Blast shares the OP Stack with Base and Optimism, but it does not run Base Flashblocks preconfirmations. Do not import a Base
pendingFlashblocks policy into a Blast wallet path. Confirmation on Blast is the ordinarylatest/safe/finalizedset covered in the Optimism mainnet RPC guide. - Not a zkEVM. Unlike Scroll, Linea, or zkSync Era, Blast is an optimistic rollup. Withdrawal timing comes from the optimistic challenge window, not from validity proofs.
Wallet-add gotchas that show up in QA
The failures that show up in support and QA are usually config, not cryptography:
- Wrong chain ID - Ethereum
1or Blast Sepolia168587773pasted into a mainnet form. - Ethereum RPC on a Blast network row -
eth_chainIdwill not return0x13e31. - Name-collision URL - a "blast" hostname that serves a different chain, or a deprecated Blast API endpoint.
- Explorer mismatch - pointing users at
etherscan.iofor Blast tx hashes, or atsepolia.blastscan.iofor mainnet hashes. - One shared "blast" RPC bucket in app config - separate keys for
blastandblast-sepoliaso a fallback cannot silently swap networks. - Balance from history - summing transfers instead of calling
eth_getBalance, which misses rebasing yield. - Missing parent Ethereum - bridge and withdraw flows need L1 configured even when the product UI lives on Blast.
wallet_addEthereumChain vs wallet_switchEthereumChain
When you implement wallet_addEthereumChain, send a full EIP-3085 payload: chainId: "0x13e31", chainName: "Blast", a complete nativeCurrency object ({ name: "Ether", symbol: "ETH", decimals: 18 }), rpcUrls pointing at your probed HTTPS endpoint, and blockExplorerUrls: ["https://blastscan.io"]. Wallets that receive only symbol on add can reject the request.
For wallet_switchEthereumChain, send only { chainId: "0x13e31" }. Metadata fields belong on add, not switch. Try switch first and fall back to add when the wallet reports the chain is unknown (error code 4902 in MetaMask-compatible wallets). Prefer one primary RPC in the wallet payload; put failover in your own client, not as five public URLs the wallet may pick at random.
Public vs dedicated for wallet traffic
Public endpoints are fine for:
- Local development and wallet QA
- Low-volume
eth_chainId/eth_blockNumberprobes - One-off scripts and docs examples
They are a poor primary path when you:
- Run production wallet RPC for many users (balance, nonce, send, receipt polls)
- Need predictable latency and a support channel when the gateway 429s
- Depend on historical state, wide
eth_getLogs, or sustained WebSocket traffic - Cannot absorb shared-node brownouts during a mint, airdrop, or market spike
Probe the candidate URL before you call it ready:
eth_chainIdreturns0x13e31.- The latest block or head advances when you poll twice a few seconds apart. Do not use an unchanged account balance as proof the node is live, and do not use a changed one either: rebasing moves EOA balances on its own.
eth_getBlockByNumberforlatest,safe, andfinalizedreturns three heights wherefinalizedis at or belowsafe, andsafeis at or belowlatest.safeandfinalizedmust not error if your confirmation policy depends on them.- One balance or receipt read against a known Blast mainnet address (not an Ethereum or Blast Sepolia address).
- If you need push updates, a WebSocket path that survives a disconnect (many public sockets do not).
- One historical
eth_getBalanceat an old block if you need archive, and oneeth_getLogsfilter in the range your indexer uses.
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, archive or historical access if you need it, and quota. Dwellir is one of those rows, with a Blast mainnet archive endpoint and a flat response-credit model that is easier to budget when the mix of reads and writes is not stable. 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. The pricing calculator is there for the rest. Log-heavy indexers should also read the eth_getLogs caps guide before assuming a wide filter will pass on every URL.
Practical split for a wallet stack
- User-facing Blast network row - chain ID 81457 /
0x13e31, ETH symbol, Blastscan, RPC you probed today. - Blast Sepolia row - chain ID 168587773 /
0xa0c71fd, separate config key, never reused as the mainnet RPC. - Parent Ethereum row - chain ID 1, kept for bridge and withdraw flows, never reused as the Blast RPC.
- Balance reads -
eth_getBalanceandbalanceOfat a known block, not reconstruction from transfer history. - Backend / indexer - dedicated or paid endpoint with explicit method and archive needs; do not share the browser wallet's public URL.
- Receipt policy - decide whether "confirmed" means
latest,safe, orfinalizedon this OP Stack chain, and store that next to the RPC URL.
Ship the hub comparison and the probe first. A URL with "blast" in the hostname does not replace eth_chainId returning 0x13e31.