Bitlayer RPC: A Developer's Guide (Chain ID 200901)

By John Sullivan · October 18, 2026 · 7 min read · #bitlayer #bitlayer rpc #bitcoin layer 2 #btc #developer guide

Bitlayer is a Bitcoin layer 2 that runs the EVM and pays gas in BTC. Contracts, wallets and libraries from Ethereum work unchanged, and the chain answers the usual eth_ methods. A few things still trip up code written for Ethereum: a minimum tip that rejects anything below 0.025 gwei, no safe or finalized block, and a public RPC that forgets state a few minutes after it happens.

Everything below was measured against the live chain on October 18, 2026, through the SwiftNodes endpoint and Bitlayer's public RPC.

The endpoint

https://rpc.swiftnodes.io/rpc/bitlayer?key=YOUR_API_KEY
wss://rpc.swiftnodes.io/ws/bitlayer?key=YOUR_API_KEY
import { createPublicClient, http, defineChain } from "viem";

const bitlayer = defineChain({
  id: 200901,
  name: "Bitlayer",
  nativeCurrency: { name: "Bitcoin", symbol: "BTC", decimals: 18 },
  rpcUrls: { default: { http: ["https://rpc.swiftnodes.io/rpc/bitlayer?key=YOUR_API_KEY"] } },
});

const client = createPublicClient({ chain: bitlayer, transport: http() });

Native balances are BTC with 18 decimals, so formatEther gives you BTC. One BTC is 10^18 wei here, and one satoshi is 10^10 wei.

What we measured

Property Value
Chain ID 200901 (0x310c5)
Client (Bitlayer public RPC) Geth/v1.1.10-stable-842b00a4/linux-amd64/go1.21.13
Block 1 April 5, 2024
Block interval exactly 3 s (199 of 199 intervals)
Block producers 21 addresses, taking turns
Transactions per block 1.05 on average; 55 of 200 blocks empty
Block gas limit 40,000,000
Gas used 0.11% of the limit on average
Base fee 7 wei
eth_maxPriorityFeePerGas 25,000,000 wei (0.025 gwei)
eth_gasPrice 25,000,007 wei
Minimum tip accepted 0.025 gwei
Plain BTC transfer 21,000 gas, 52.5 satoshis
safe / finalized tags not supported
eth_getLogs range no block-range cap on the public RPC
Historical state (public RPC) about the last 128 blocks

The chain is a proof-of-authority network. Over 200 consecutive blocks, 21 different addresses appeared in the miner field, each producing 9 or 10 blocks in rotation. Every block has difficulty 2 and a 97-byte extraData (32 bytes of vanity data plus a 65-byte signature), which is the Clique-style way of sealing blocks with a validator signature instead of proof of work. So the miner field tells you which validator signed the block, and it changes every block.

The tip must be at least 0.025 gwei

We signed transactions from an empty wallet with different tips and sent them to the public RPC:

Tip Response
0 transaction underpriced: tip needed 25000000, tip permitted 0
0.01 gwei transaction underpriced: tip needed 25000000, tip permitted 10000000
0.05 gwei insufficient funds for gas * price + value

The last error is the one you want: the node accepted the tip and only then found the wallet had no BTC. Legacy (type 0) transactions follow the same rule, since their tip is gasPrice minus the base fee: a legacy gasPrice of 0.01 gwei got the same "tip needed 25000000" rejection.

The base fee sits at 7 wei because blocks are almost empty, so the price you pay is the tip. Of the 210 transactions in the 200 blocks we sampled, 208 paid exactly 0.025 gwei and 2 paid 0.05 gwei. 207 were EIP-1559 (type 2) and 3 were legacy.

Ask the node instead of hardcoding:

const tip = await client.estimateMaxPriorityFeePerGas(); // 25,000,000 wei today
const { maxFeePerGas } = await client.estimateFeesPerGas();

eth_maxPriorityFeePerGas returns exactly the floor, so viem's defaults produce a valid transaction. A plain BTC transfer used 21,000 gas at an effective price of 25,000,007 wei, which comes to 525,000,147,000 wei: 0.000000525 BTC, or 52.5 satoshis. eth_estimateGas returned 21,000 for the same transfer, as on Ethereum. For contract calls, see estimating gas with EIP-1559 for how much padding to add.

One difference between endpoints: eth_feeHistory is not available on Bitlayer's public RPC, which answers "method FeeHistory not support". Through SwiftNodes it works. Every reward percentile came back as 25,000,000 and every base fee as 7, which matches the floor described above. Some libraries call eth_feeHistory to estimate fees, so if your fee estimation fails against the public RPC, this is the likely cause.

No safe or finalized block

eth_getBlockByNumber("safe")      -> safe block not found
eth_getBlockByNumber("finalized") -> finalized block not found

Bitlayer is one of the chains in our survey of the finalized block tag across 62 chains that return an error instead of a block. Code that waits for finalized throws or hangs, and an indexer that reads up to finalized never moves. Use a confirmation count on latest: at 3 seconds per block, 20 confirmations is one minute. Keep the parent-hash check from handling chain reorgs in an indexer so a replaced block is caught whatever depth you pick.

Recent state only on the public RPC

This is the difference most likely to break a backend. Bitlayer's public RPC is a full node, not an archive node: it keeps state only for recent blocks, roughly the last 128 (about six minutes of chain). We asked it for a balance at a range of heights:

Block Public RPC
10 blocks behind the head ok
about 130 blocks behind missing trie node
100,000 behind missing trie node
1,000,000 to 20,000,000 missing trie node
1 ok

Block 1 also answers, which makes the node look like an archive node to a quick test at block 1. Every other height older than a few minutes that we tried was gone. That affects eth_getBalance, eth_call, eth_getCode and eth_getStorageAt at a past block, so balance snapshots, airdrop checks and historical price reads all fail.

An archive node answers at every height we tried, from block 1 to the head. On SwiftNodes, add archive=1 to the URL to route a request only to archive upstreams (paid plans):

https://rpc.swiftnodes.io/rpc/bitlayer?key=YOUR_API_KEY&archive=1

More on the difference in full node vs archive node.

Logs

The public RPC has no block-range cap on eth_getLogs. Unfiltered, the chain emits about 0.8 logs per block:

Range Logs
1,000 blocks 813
10,000 blocks 7,876
50,000 blocks 39,862
100,000 blocks 79,506
500,000 blocks timed out after 30 s

No cap does not mean no limit: big unfiltered ranges eventually time out. Through SwiftNodes, unfiltered queries of 10,000 to 20,000 blocks came back in 1.5 to 2.5 seconds, and 50,000 blocks in about 7 seconds, though one of three 50,000-block attempts hit our upstream timeout. A filter makes a big difference: the Wrapped BTC contract's logs over 200,000 blocks (about a week) came back in one request, 50,158 entries in under 10 seconds. Filter by address and topics, and keep unfiltered pages around 20,000 blocks. See eth_getLogs range caps for chunking code.

The busiest contracts in our sample were tokens. Of 210 transactions, 57 went to Wrapped BTC (0xff20…fc5f), 47 to Tether USD (0xfe9f…9dd2) and 45 to a token named "Ethereum Token" (0xef63…f4c2). So most activity is ERC-20 transfers, and Transfer logs are the main thing to index.

For live data, WebSocket newHeads subscriptions work through SwiftNodes and delivered a header every 3 seconds in our test. Polling over HTTP every 3 seconds also matches the block interval.

Receipts and tracing

Method Public RPC SwiftNodes
eth_getBlockReceipts works works
eth_feeHistory not supported works
debug_traceTransaction (callTracer) not available works
debug_traceBlockByNumber not available works
trace_block not available not available
txpool_* not available not available
safe / finalized tags not available not available

If you need internal calls, for example to follow BTC moved by a contract, use debug_traceTransaction with callTracer through an endpoint that has it. The Parity-style trace_* methods are not available anywhere we tested. Internal calls with trace_filter and trace_transaction explains how the two tracing families differ.

Summary

  • EVM chain, chain ID 200901, gas in BTC with 18 decimals, 3-second blocks from 21 rotating validators.
  • The minimum tip is 0.025 gwei; lower tips fail with transaction underpriced. Read eth_maxPriorityFeePerGas, which returns exactly that.
  • The base fee is 7 wei, so a transfer costs 52.5 satoshis.
  • No safe or finalized block: count confirmations on latest.
  • The public RPC keeps only recent state and has no eth_feeHistory or tracing. Use an archive endpoint for history.
  • No eth_getLogs range cap on the public RPC, but big unfiltered ranges time out: filter, and page at about 20,000 blocks.

Bitlayer endpoints and method support are on our Bitlayer RPC page, with 127 other chains on the same key. For another chain that pays gas in BTC, compare Rootstock. SwiftNodes has a free tier to try it.

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

  • Etherlink RPC: A Developer's Guide (Chain ID 42793)

    Etherlink is the EVM rollup on Tezos. Measured: sub-second to 1.5 s blocks, a fixed 1 gwei base fee, plain transfers that use 621,000 gas because the data fee is charged as gas, a 500-block eth_getLogs cap, and no safe tag.

  • Tempo RPC: A Developer's Guide (Chain ID 4217)

    Tempo is a payments chain with no native token: fees are paid in USD stablecoins. Measured: 550 ms blocks, instant finality, an eth_getBalance that returns the same huge number for every address, the 0x76 transaction type, and a 20,000-result eth_getLogs cap.

  • Immutable zkEVM RPC: A Developer's Guide (Chain ID 13371)

    Immutable zkEVM is the gaming chain that pays gas in IMX. Measured: 2-second blocks, a base fee of 49 wei, a hard 10 gwei minimum tip that rejects anything lower, no safe or finalized tags, and a 5,000-block eth_getLogs cap.

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 →