Somnia RPC: A Developer's Guide (Chain ID 5031)

By John Sullivan · October 24, 2026 · 12 min read · #somnia #somnia rpc #layer 1 #high throughput #developer guide

Somnia is an EVM layer 1 from Improbable and the Somnia Foundation, built for games, social apps and agent economies. The headline is throughput: the chain markets seven-figure TPS for simple transfers, with sub-second finality and a purpose-built state database called IceDB.

The JSON-RPC surface is ordinary EVM. The differences show up in block cadence, fee accounting and history. Somnia produces about ten blocks per second, so timestamps repeat and block numbers climb by roughly 860,000 a day. The block gas limit is 15 billion. The base fee is 6 gwei, yet legacy transactions in the same blocks paid less. Log queries are capped at 1,000 blocks upstream and 100 on the free tier. Each of those can break code written for Ethereum.

Everything below was measured on October 24, 2026, through the SwiftNodes endpoint and Somnia's official RPC.

The endpoint

https://rpc.swiftnodes.io/rpc/somnia?key=YOUR_API_KEY
wss://rpc.swiftnodes.io/ws/somnia?key=YOUR_API_KEY

The proxy slug is somnia. The chain ID and network ID are 5031 (0x13a7), the native gas token is SOMI with 18 decimals, and the explorer is explorer.somnia.network. The official endpoint is https://api.infra.mainnet.somnia.network, with WebSocket at wss://api.infra.mainnet.somnia.network/ws; the network details are in the Somnia docs.

A viem client needs nothing exotic:

import { createPublicClient, http } from "viem";

const somnia = createPublicClient({
  transport: http("https://rpc.swiftnodes.io/rpc/somnia?key=YOUR_API_KEY"),
});

Somnia ships Multicall3 at 0x5e44F178E8cF9B2F5409B6f18ce936aB817C5a11. Use it for batched reads instead of firing ten separate requests at a chain that produces ten blocks a second.

What we measured

Property Value
Chain ID 5031 (0x13a7)
Client somnia-…-release (two builds seen during the sample)
Block height at measurement about 446.67 million
Average block interval 0.1005 s over 200 blocks; 0.1017 s over 60
Transactions per block 1.37 over 200 blocks; 85 blocks were empty
Block gas limit 15,000,000,000
Gas used 1.03 million average (0.007% of the limit); 37.7 million max (0.25%)
Base fee 6 gwei in every block sampled
eth_maxPriorityFeePerGas 0
eth_gasPrice 6 gwei
Legacy gas prices 0.6 to 16 gwei; median 1.8 gwei
Type-2 effective price 6 gwei, with a zero priority fee
Plain SOMI transfer 21,000 gas; 0.0000126 SOMI at 0.6 gwei, 0.000126 at 6 gwei
eth_getLogs 1,000-block upstream cap; 100-block free-tier cap
Finality safe and finalized at or within 3 blocks of the head
Archive official RPC answered 300 million blocks back; shared route is not deterministic
WebSocket newHeads works; first head in about 0.5 s on the shared route
Tracing debug_traceTransaction on the official RPC; paid on SwiftNodes

The block producer field is not useful: miner was the zero address in every block we sampled and difficulty was 0. If you index validators, you will not get them from the standard block header.

Ten blocks a second, one timestamp per second

A 200-block sample spanned 20 seconds, for an average interval of 0.1005 seconds. The head also advanced five or six blocks every half second when polled directly. At that cadence the chain adds about 860,000 blocks a day, which is why the height is already above 446 million.

The timestamps are the trap. Somnia block timestamps have one-second resolution, so consecutive blocks usually share a timestamp. In the 200-block sample, 179 of 199 adjacent pairs had a zero-second difference. A Solidity contract that uses block.timestamp as a unique key, or an indexer that sorts by timestamp and assumes a strict order, will lose blocks.

Use the block number or block hash as the key. If you need ordering inside a block, use the transaction index and log index. If you need wall-clock time, treat the timestamp as a coarse bucket, not a per-block clock.

The same load-balanced route can also return a slightly different head from one request to the next. eth_blockNumber and eth_getBlockByNumber("latest") disagreed by a block or two in our snapshots, and safe or finalized were sometimes a block or two ahead of the eth_blockNumber response. That is backend skew, not a reorg. Pin a single backend if your logic compares block numbers across calls.

The block gas limit is 15 billion

Somnia's block gas limit is 15,000,000,000, which is 500 times Ethereum's 30 million. That is capacity, not current demand.

In the 200-block sample there were 274 transactions, or 1.37 per block. Eighty-five blocks were empty. The average block used about 1.03 million gas, or 0.007% of the limit. The busiest block used 37.7 million gas, or 0.25%. At 0.1005-second blocks, 1.37 transactions per block works out to roughly 14 transactions per second. The chain is provisioned for a much larger workload than it is carrying today.

That changes how you poll. A one-second eth_blockNumber loop skips about ten blocks. Use WebSocket newHeads, or request a block range and process it in order. If you need receipts, eth_getBlockReceipts returns every receipt in a block in one call; it worked on both endpoints we tested. For state reads, batch through Multicall3 rather than making one eth_call per block.

Gas estimation still works normally. eth_estimateGas returned 21,000 for a plain native transfer. The difference is that a 30-million-gas transaction is only 0.2% of a Somnia block, so a gas limit copied from Ethereum is not a congestion signal here.

The 6 gwei base fee is not a floor for legacy transactions

Somnia reports a 6 gwei base fee in every block we sampled. eth_maxPriorityFeePerGas returns 0, eth_gasPrice returns 6 gwei, and eth_feeHistory returns 6 gwei base fees with zero rewards at every percentile. That looks like a fixed-fee chain with no priority auction.

The blocks tell a different story. In the 200-block sample, 272 of 274 transactions were legacy type 0, and their gas prices ranged from 0.6 to 16 gwei, with a median of 1.8 gwei. We found legacy transactions paying 0.6 and 1.8 gwei inside blocks whose baseFeePerGas was 6 gwei. Their receipts reported effectiveGasPrice equal to the transaction's gasPrice, not the base fee.

Type gasPrice maxFeePerGas maxPriorityFeePerGas Effective price Block base fee
0 0.6 gwei — — 0.6 gwei 6 gwei
0 1.8 gwei — — 1.8 gwei 6 gwei
0 6 gwei — — 6 gwei 6 gwei
2 6 gwei 20 gwei 0 6 gwei 6 gwei
0 16 gwei — — 16 gwei 6 gwei

The two type-2 transactions in the sample paid exactly the 6 gwei base fee with a zero priority fee and a 20 gwei max fee. So type-2 transactions behave like EIP-1559: the base fee is the floor. Legacy transactions do not.

That matters if you replay or validate transactions. A check that rejects a legacy transaction when gasPrice < baseFeePerGas will reject transactions that Somnia accepted. Use the receipt's effectiveGasPrice when you need the price that was actually paid, and use eth_gasPrice or a recent receipt when you are choosing a price to send.

A plain 21,000-gas transfer costs:

Gas price Cost
0.6 gwei 0.0000126 SOMI
1.8 gwei 0.0000378 SOMI
6 gwei 0.000126 SOMI
16 gwei 0.000336 SOMI

For a type-2 transaction, set maxFeePerGas to at least the current base fee and maxPriorityFeePerGas to 0 unless you have a reason to tip. For a legacy transaction, eth_gasPrice is the safe default even though lower prices are sometimes included. Do not copy a fixed 1 gwei value from another chain.

Finality is fast; the tags are not a cross-provider guarantee

Somnia uses a BFT consensus design and describes finality as sub-second. The JSON-RPC tags agree in practice: in eight snapshots, safe and finalized were at the head or within three blocks of it. At 0.1-second blocks, three blocks is 0.3 seconds.

The labels are still not a cross-provider guarantee. Because the shared route balances across backends, finalized can be a block or two ahead of the eth_blockNumber response from a different request. We also saw safe and finalized return the same block, then finalized pull one block ahead in the next snapshot. That is not a consensus reorg; it is a backend lag artifact.

For most applications, one confirmation on Somnia is already final enough, and waiting for finalized adds only a fraction of a second. For an indexer that needs a deterministic rule across providers, pin one backend and wait a fixed number of blocks, or use a finality service. The finalized block tag across 62 chains shows how much this varies elsewhere.

pending works and returned the next block in our tests. Do not use it as a finality signal; it is a mempool view.

Logs: 1,000 blocks upstream, 100 on the free tier

Somnia's official RPC caps eth_getLogs at roughly 1,000 blocks per request. A 1,000-block query returned 4,890 logs. A 5,000-block query failed with:

block range exceeds 1000

The SwiftNodes free tier caps the span at 100 blocks, regardless of the upstream limit. A 101-block query returned:

The free plan allows eth_getLogs over at most 100 blocks per request (this one spans 101). Split the range, or upgrade from Starter at $49/month.

A 100-block unfiltered query returned 431 logs in our sample. That is the practical constraint: at 10 blocks a second, 100 blocks is only ten seconds of chain history, and it can already contain hundreds of logs.

Page by blocks and keep the step small enough for both the span cap and the result size:

const STEP = 100n; // free tier; use 1_000n on the official RPC

for (let from = start; from <= end; from += STEP) {
  const to = from + STEP - 1n > end ? end : from + STEP - 1n;
  const logs = await client.getLogs({
    address,
    fromBlock: from,
    toBlock: to,
  });
  // process logs before advancing
}

Pass an address or topic filter whenever you can. It does not raise the block-span cap, but it reduces the result set and makes the query cheaper. If you need every log in a range, page by 100 blocks on the free tier and 1,000 on the official RPC, and handle the error by halving the step.

For per-block indexing, eth_getBlockReceipts is often a better fit than a log query: one call returns all receipts and logs for a block, and it worked on both endpoints.

Deep history is not guaranteed on the shared route

The official RPC kept deep history in our tests. It returned block headers at 1,000, 10,000, 100,000, 1,000,000, 50,000,000, 100,000,000 and 300,000,000 blocks back, and it returned WSOMI contract code at 300,000,000 blocks back in every attempt.

The shared SwiftNodes route is not deterministic for old data. Four identical requests for block 1,000 returned block, null, block, block. Repeated eth_getCode calls for WSOMI at 50 million and 200 million blocks back sometimes returned the contract and sometimes returned:

unable to load historical state

That is what a load-balanced route with mixed backends looks like. Recent blocks and recent state are fine; a backfill that reaches into deep history can land on a node that does not have the data. For deterministic backfills, use the official RPC, a dedicated archive node, or SwiftNodes archive routing on a paid plan (&archive=1). The free tier rejects archive routing with a 403.

The same caveat applies to tracing. The official RPC supports debug_traceTransaction and debug_traceBlockByNumber; trace_transaction returns method not found, and eth_getProof is not implemented on either endpoint. On SwiftNodes, debug and trace methods require a paid plan, so a free-tier trace request returns a plan error rather than a trace.

What to use

For a new Somnia integration:

  • Use https://rpc.swiftnodes.io/rpc/somnia?key=YOUR_API_KEY for HTTP and wss://rpc.swiftnodes.io/ws/somnia?key=YOUR_API_KEY for WebSocket.
  • Follow heads with newHeads or a block-range loop. A one-second poll skips about ten blocks.
  • Key on block number and block hash, not timestamp.
  • Use Multicall3 for batched state reads and eth_getBlockReceipts for per-block receipts.
  • Page eth_getLogs by 100 blocks on the free tier and 1,000 on the official RPC.
  • Read eth_gasPrice before sending. For type 2, use a max fee at least as large as the base fee and a zero priority fee.
  • Do not use baseFeePerGas as a validation floor for legacy transactions.
  • Use the official RPC or a paid archive route for deep history and tracing.

Somnia is fast, cheap and mostly idle in the current sample. The RPC works like Ethereum until the block cadence, the fee accounting or a historical query forces you to look at the chain's own rules. Measure your workload against those rules rather than the headline TPS number.

FAQ

What is the Somnia chain ID?

5031 (0x13a7). The native gas token is SOMI with 18 decimals. The Shannon testnet uses chain ID 50312.

What is the Somnia RPC endpoint?

https://rpc.swiftnodes.io/rpc/somnia?key=YOUR_API_KEY for HTTP and wss://rpc.swiftnodes.io/ws/somnia?key=YOUR_API_KEY for WebSocket. The official endpoint is https://api.infra.mainnet.somnia.network, with WebSocket at wss://api.infra.mainnet.somnia.network/ws.

Why does Somnia produce 10 blocks per second but timestamps only change once a second?

Somnia's measured block interval is about 0.1005 seconds, but block timestamps have one-second resolution. In a 200-block sample, 179 of 199 adjacent blocks shared a timestamp. Use the block number or hash as a key, not the timestamp.

Why is a Somnia transaction allowed below the 6 gwei base fee?

Somnia reports a 6 gwei base fee in every block we sampled, but legacy type-0 transactions in our sample paid 0.6, 1.8, 6 and 16 gwei and were included. The receipt's effectiveGasPrice matched the transaction's gasPrice, not the base fee. Type-2 transactions in the same sample paid the 6 gwei base fee with a zero priority fee. Do not use baseFeePerGas as a validation floor for legacy transactions; read eth_gasPrice or a recent receipt.

What is the eth_getLogs limit on Somnia?

The official node caps a query at roughly 1,000 blocks; a 1,000-block query worked, and 5,000 and 10,000 blocks failed with block range exceeds 1000. The SwiftNodes free tier caps the span at 100 blocks. A 100-block unfiltered query returned 431 logs, so the practical limit is logs per page as much as blocks.

Does Somnia support archive data?

The official RPC answered block headers and contract code at 300,000,000 blocks back in our tests. The shared SwiftNodes route is not a deterministic archive: repeated requests for the same old block or historical code sometimes returned data and sometimes returned null or unable to load historical state. Use archive routing on a paid plan or a dedicated archive endpoint for backfills.

Does Somnia support debug and trace methods?

The official RPC supports debug_traceTransaction and debug_traceBlockByNumber; trace_transaction is not implemented, and eth_getProof returns method not found. On SwiftNodes, debug and trace methods require a paid plan.

What is the Somnia block gas limit?

15,000,000,000 gas. The average block in our 200-block sample used about 1.03 million gas, or 0.007% of the limit; the busiest used 37.7 million, or 0.25%.

J
John Sullivan
Infrastructure Writer, SwiftNodes

John Sullivan covers RPC infrastructure, node operations, and multi-chain development at SwiftNodes — what it actually takes to keep endpoints fast, fresh, and reliable across EVM and non-EVM networks.

Related posts

Try SwiftNodes free — multi-chain RPC across 83 networks, flat-rate pricing, pay by card or crypto, no KYC. Get an API key in 30 seconds →