Metis Andromeda is an Ethereum layer 2 run by a pool of rotating sequencers. Gas is paid in METIS, not ETH. The node software reports itself as an old Geth fork, so the JSON-RPC surface looks like Ethereum but answers some fee and finality calls differently. Wallet builders who copy an Ethereum mainnet config, build EIP-1559 fee math, or trust the finalized tag without checking it will see errors or stale blocks that Ethereum mainnet never shows.
This is not a ranking of providers. Use the Metis mainnet hub to compare public endpoints and paid rows, then run the checks below on the URL you configure. The Metis mainnet providers page lists the keyed options side by side.
Chain ID 1088 is Andromeda, not Ethereum's 1
- Metis Andromeda mainnet: chain ID 1088, hex
0x440. This is whateth_chainIdreturns and what EIP-155 signatures use.net_versionreturned"1088"on every endpoint that passed the probe. - Metis Sepolia testnet: chain ID 59902, with sMETIS as the gas token, per the Metis RPC docs.
- Ethereum mainnet: chain ID 1. Metis settles to Ethereum, but a transaction signed for chain ID 1 is not valid on Andromeda, and the reverse. A wallet that already has Ethereum added still needs a separate Metis network entry.
Wallet-add fields for mainnet, from the same Metis RPC docs page:
- Network name:
Metis Andromeda(the docs do not fix a label; keep the word Andromeda so users can tell it from testnet) - Chain ID:
1088(or0x440if the form wants hex) - Currency symbol:
METIS - RPC URL: a JSON-RPC HTTPS endpoint you have already probed, such as the official
https://andromeda.metis.io/?owner=1088 - Block explorer:
https://andromeda-explorer.metis.io(Blockscout) orhttps://explorer.metis.io(Routescan)
Call eth_chainId on the exact URL you will ship and expect 0x440. A timeout, an HTML page, a paid-plan error, or a deprecation message is not a working Metis transport.
Public endpoints that answered eth_chainId
We probed every public Metis mainnet URL on the hub 8 times, about 55 seconds apart, on 2026-10-09 between 02:38 and 02:45 UTC. Each round called eth_chainId, eth_getBlockByNumber("latest"), eth_getBalance, and an eth_call for the m.USDC token's totalSupply(), with a curl User-Agent on every request. The hub lists 11 HTTPS and 2 WSS transports. These passed all four calls in 8 of 8 rounds, and every one returned the same head block as the others and as the Blockscout explorer in each round:
| Endpoint | Transport | Notes |
|---|---|---|
https://andromeda.metis.io/?owner=1088 | HTTPS | Official Metis public node. Supports mvm_finalizedBlockNumber |
https://metis-rpc.publicnode.com / wss://metis-rpc.publicnode.com | HTTPS, WSS | Supports mvm_finalizedBlockNumber. The finalized tag returned "element not found" |
https://metis.drpc.org / wss://metis.drpc.org | HTTPS, WSS | The hub lists the HTTPS URL with and without a trailing slash; both behaved the same. mvm_finalizedBlockNumber returned -32601 |
https://metis-andromeda.rpc.thirdweb.com | HTTPS | Supports mvm_finalizedBlockNumber |
https://metis.api.onfinality.io/public | HTTPS | Supports mvm_finalizedBlockNumber. The finalized tag returned a block about 1.4 years old |
https://metis-andromeda.gateway.tenderly.co | HTTPS | mvm_finalizedBlockNumber returned -32601. The finalized tag returned "element not found" |
https://metis-public.nodies.app | HTTPS | mvm_finalizedBlockNumber returned -32601. The finalized tag returned a block about 2.5 years old |
The latest block was 11 to 34 seconds old when we read it. Blocks arrived about every 32 seconds during the test (see the finality section), so a head that is 30 seconds old is normal here, not a lagging node.
Three rows failed all 8 rounds, and the directory now hides them:
https://metis-mainnet.public.blastapi.ioreturned-32000"Blast API is no longer available" on every call.https://api.blockeden.xyz/metis/...returned HTTP 402PAID_PLAN_REQUIREDon every call.https://metis.rpc.hypersync.xyzdoes not resolve in DNS (NXDOMAIN).
A row on a directory page is a starting point, not proof it serves Metis today.
What the Metis JSON-RPC does differently
web3_clientVersion on the official node returned Geth/v1.9.10-stable-4de8ba53/linux-arm64/go1.26.8 during the test. PublicNode returned a Geth/v1.9.10-stable string too, and DRPC answered with Geth/v10.0.0/drpc, so do not use that string to detect the backend. The Metis FAQ states the EVM level: Berlin plus the PUSH0 opcode from Shanghai, no Cancun support yet, and Solidity up to v0.8.23. Contracts compiled for a newer EVM target can fail to deploy or behave differently.
Calls that behaved differently from Ethereum mainnet on all 7 passing HTTPS hosts:
eth_feeHistoryandeth_maxPriorityFeePerGasfailed. Six hosts returned-32601"does not exist/is not available"; DRPC returned code19"Temporary internal error" for both.- Blocks had no
baseFeePerGasfield, adifficultyof0x2, and the zero address asminer. - The
safetag returned the same block on every host. Thefinalizedtag did not (see the next section).
The Metis RPC docs also note that public RPCs are rate limited and tell you to confirm the endpoint supports the methods you need, such as WebSockets for subscriptions. In the probe, PublicNode and DRPC were the two public WSS transports on the hub, and both passed.
Finality: safe, finalized, and mvm_finalizedBlockNumber
The Metis finality docs define mvm_finalizedBlockNumber as the L2 block that "can no longer be reorganized" once 2/3 of sequencers reach consensus, and they show eth_getBlockByNumber("finalized") as the standard way to read the finalized block. The same page notes about 30 minutes for batch submission to Ethereum.
What the endpoints returned during the test, with the head at block 23,257,957:
safe: block 23,256,931 on all 7 hosts, about 9.2 hours old and 1,026 blocks behind the head.mvm_finalizedBlockNumber: also 23,256,931 on the official node, thirdweb, PublicNode, and OnFinality. Tenderly, DRPC, and Nodies returned-32601.finalized: block 23,256,118, about 13.8 hours old, on the official node, DRPC, and thirdweb. Tenderly and PublicNode returned "element not found". Nodies returned block 16,392,433 and OnFinality returned block 20,412,930, both more than a year old.
What that means for a wallet or indexer:
- Do not read
finalizedfrom an arbitrary public URL and trust it. On two of the passing hosts it errors, and on two others it points far into the past. - If you need the sequencer-consensus finality the docs describe, call
mvm_finalizedBlockNumberon a host that supports it and fall back tosafe, which matched it on every host in the test. - For ordinary payment UX, decide on a confirmation policy based on
latestplus your own depth, and treat the finality fields as a separate, slower signal.
Measured on the Blockscout explorer, the last 200 blocks spanned 6,398 seconds, about 32 seconds per block, with 1 to 6 transactions each. Block numbers here move slowly compared with chains that produce a block every second or two, so convert any "N blocks" rule from another chain into wall-clock time before reusing it.
Fees: legacy gasPrice in METIS
During the test, every passing host returned the same eth_gasPrice: 0x37800d808 (14,898,223,112 wei, about 14.9 gwei). eth_estimateGas for a plain METIS transfer returned 0x5208 (21,000), so a simple send cost about 0.00031 METIS at that price. The latest block's gasLimit was 1,100,000,000.
What that means for a wallet:
- Price from
eth_gasPriceand send a legacygasPrice. With nobaseFeePerGas, noeth_feeHistory, and noeth_maxPriorityFeePerGas, EIP-1559 fee code paths have nothing to read. The Metis docs do not describe EIP-1559 support, and the endpoints did not expose it. - Show fees in METIS. Wallet UIs that hardcode an ETH label for gas will mislabel the fee.
- Refresh the price per send rather than caching a value across sessions.
METIS is native gas and an ERC-20
The Metis FAQ says METIS is a native token and also ERC-20 compatible on layer 2, through the built-in MVM_Coinbase contract, so there is no need for a wrapped token. During the test, an ERC-20 balanceOf call on that contract at 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000 returned the same amount as eth_getBalance for the same address (about 47,222.55 METIS on the WMETIS contract). The contract reported name Metis Token, symbol Metis, and 18 decimals.
- Do not double count. A wallet that lists both the native balance and the
0xDeadDeAdd...0000ERC-20 balance shows the same METIS twice. - WMETIS is a separate contract. The FAQ lists a WETH9-style WMETIS at
0x75cb093E4D61d2A2e65D8e0BBb01DE8d89b53481, deployed by the Sushi team. Balances there are wrapped METIS, not the native balance. - ETH on Metis is a token. It is not the gas asset. During the test the contract at
0x420000000000000000000000000000000000000Areported symbolWETHand 18 decimals.
Wallet-add gotchas that show up in QA
- Chain ID 1 in the network row: signatures target Ethereum, and Andromeda rejects them.
- ETH as the fee symbol: users see fees in the wrong asset. Gas is METIS.
- EIP-1559 fee code paths:
eth_feeHistoryandeth_maxPriorityFeePerGasfail, so fee estimation must fall back togasPrice. - Trusting
finalizedeverywhere: some hosts error and some return blocks more than a year old. - Double-counted METIS: the native balance and the
MVM_CoinbaseERC-20 balance are the same funds. - Contracts built for Cancun: the FAQ says Andromeda does not support Cancun yet; pin the compiler and EVM target.
- Dead rows copied from old lists: Blast API, BlockEden's public key, and HyperSync failed every round.
Public vs dedicated for wallet traffic
The Metis RPC docs describe public RPCs as best for development, testing, and light usage, and note that all public RPCs are rate limited.
Public endpoints are fine for:
- Local development and wallet QA
- Low-volume
eth_chainIdandeth_blockNumberprobes - 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 at volume
- Depend on finality fields that differ from host to host
- Cannot absorb shared-node rate limits during a launch or market spike
Probe the candidate URL before you call it ready:
eth_chainIdreturns0x440.- The latest block advances over a few minutes and matches an explorer. Expect it to be tens of seconds old, not a few seconds.
- A plain transfer
eth_estimateGasreturns0x5208(21,000), andeth_gasPricereturns a value. - An
eth_callon a token contract you care about returns data, not a paid-plan error. safe, andmvm_finalizedBlockNumberif you use it, return a recent block on that host.- 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.
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, Chainstack, 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 Metis network row: chain ID 1088 /
0x440, METIS symbol, an Andromeda explorer, an RPC you probed today. - Fee estimation: legacy
gasPricefrometh_gasPrice, refreshed per send, shown in METIS. - Balances: native METIS once, WMETIS and bridged WETH as tokens.
- Finality:
mvm_finalizedBlockNumberorsafefrom a host you checked, notfinalizedfrom any URL. - Backend / indexer: dedicated or paid endpoint with WebSocket support. Do not share the browser wallet's public URL.
Ship the hub comparison and the probe first. A network called "Metis" in a dropdown does not replace eth_chainId returning 0x440.