guide7 min read

Polygon Mainnet RPC for Wallet Builders

What to check before a wallet points at Polygon mainnet: chain ID 137 / 0x89, POL vs MATIC, PoS vs zkEVM mix-ups, and public vs dedicated endpoints.

By RPC Directory•
#Polygon#POL#RPC#Wallet#Chain ID#PoS
$polygon-mainnet-rpc.md

Polygon PoS mainnet is an EVM chain with its own chain ID, ticker history, and explorer. Wallet builders who paste Ethereum 1, leave MATIC in the add-network form, or point a zkEVM URL at a PoS network row will ship the wrong network, the wrong gas token label, or a rate-limited public gateway. Before you wire MetaMask, Rabby, Rainbow, Phantom, or your own wallet_addEthereumChain flow, prove chain ID 137, use POL in the currency fields, and probe the URL you intend to ship.

This is not a ranking of providers. Use the Polygon Mainnet hub to compare endpoints and paid rows, then run the checks below on the URL you configure.

Chain ID 137 is not Ethereum and not Amoy

Mainnet chain ID is 137, hex 0x89. Amoy testnet is 80002. The retired Mumbai testnet was 80001. Ethereum mainnet is 1. Those are different networks. A wallet that already has Ethereum added still needs a separate Polygon PoS network entry.

Wallet-add fields for mainnet:

  • Network name: Polygon Mainnet (or Polygon if the product already scopes the list)
  • Chain ID: 137 (or 0x89 if the form wants hex)
  • Currency symbol: POL
  • RPC URL: a JSON-RPC HTTPS endpoint you have already probed
  • Block explorer: https://polygonscan.com

Call eth_chainId on the exact RPC URL you will ship. Expect 0x89. A gateway that returns 0x1 is Ethereum. A gateway that returns Amoy (0x13882) or Mumbai (0x13881), times out, or answers HTML is not Polygon mainnet for that transport. Do this after any load balancer or fallback so you are not checking a different backend than production.

POL is the native gas token, not MATIC

Native gas on Polygon PoS mainnet is POL with 18 decimals. Older docs, SDKs, and wallet presets still say MATIC. Shipping nativeCurrency.symbol: "MATIC" in an EIP-3085 payload, or showing MATIC in the network list while the chain is PoS mainnet, confuses users and support.

Practical rules:

  • Use POL in wallet_addEthereumChain / network config (name, symbol, decimals: 18).
  • Treat legacy MATIC labels as a migration bug in your own UI, not as a second native token on chain ID 137.
  • Token contracts that were branded MATIC are not a substitute for the native gas ticker in the network row. Keep ERC-20 lists separate from the chain's native currency object.

If a third-party wallet already has Polygon with an old MATIC label, your dapp should still send POL in new add/switch requests. Do not rely on the user's stale network row to define your product's chain metadata.

Polygon PoS is not every "Polygon" chain

"Polygon" in product copy often collapses several networks. For wallet RPC this directory's hub is Polygon PoS mainnet (/chains/polygon/mainnet, chain ID 137). Other Polygon-branded networks (zkEVM and similar) use different chain IDs and different endpoints. Mixing them is a funds and explorer bug:

  • Wrong RPC on a PoS network row - eth_chainId will not return 0x89.
  • Wrong explorer - Polygonscan mainnet tx hashes do not resolve on a zkEVM explorer, and the reverse is also true.
  • Hard-coded contract addresses from another Polygon network - USDC, WETH, and app deployments differ by chain ID. Copying an address from a zkEVM or testnet deployment into a PoS wallet path is a funds bug.
  • One shared "polygon" RPC key that sometimes points at Amoy - separate keys for polygon and polygon-amoy (or whatever you name the testnet) so a fallback cannot silently swap networks.

When you implement wallet_addEthereumChain, send chainId: "0x89", a full EIP-3085 nativeCurrency object ({ name: "POL", symbol: "POL", decimals: 18 }), rpcUrls pointing at your probed HTTPS endpoint, and blockExplorerUrls: ["https://polygonscan.com"]. For wallet_switchEthereumChain, send only { chainId: "0x89" } — metadata fields belong on add, not switch. Wallets that receive only symbol on add can reject the request. 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.

Wallet-add gotchas that show up in QA

The failures that show up in support and QA are usually config, not cryptography:

  1. Wrong chain ID - Ethereum 1, Amoy 80002, or Mumbai 80001 pasted into a mainnet form.
  2. MATIC in the currency fields - network adds, but users see the wrong ticker and open tickets.
  3. Ethereum or Amoy RPC on a Polygon mainnet row - eth_chainId will not return 0x89.
  4. Explorer mismatch - pointing users at etherscan.io or a zkEVM explorer for PoS tx hashes.
  5. Public URL baked into the release binary - fine for a docs example, poor as the only production path for balance, nonce, send, and receipt polls.

Directory traffic already hits wallet-add style paths across MetaMask, Rabby, Rainbow, and similar. Prove the payload against the same RPC URL your release will use.

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, 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:

  1. eth_chainId returns 0x89.
  2. 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.
  3. One balance or receipt read against a known Polygon PoS mainnet address (not an Ethereum or Amoy address).
  4. If you need push updates, a WebSocket path that survives a disconnect (many public sockets do not).
  5. Optional: compare safe / finalized block tags if your confirmation policy depends on them, and document which tag "confirmed" means next to the RPC URL.

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: 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 Polygon PoS network row - chain ID 137 / 0x89, POL symbol, Polygonscan, RPC you probed today.
  • Testnet row - Amoy 80002, separate config key, never reused as the mainnet RPC.
  • 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, or finalized on this chain, and store that next to the RPC URL.

Ship the hub comparison and the probe first. Marketing copy about "cheap Polygon gas" does not replace eth_chainId returning 0x89.