DEV Community

OnFinality
OnFinality

Posted on Originally published at onfinality.io

Base Node RPC: Endpoint, Chain ID & Debugging

Base is an Ethereum Layer 2 built on the OP Stack, which means its node RPC interface is deliberately familiar: standard JSON-RPC over HTTP, the same eth_* method names you already use on Ethereum, and a small set of OP-Stack-specific methods on top. If you are wiring up a wallet, a backend indexer, or a test suite, you mostly need the right chain settings, a working endpoint, and a clear debugging path when a request fails.

This page is a working reference for Base node RPC. It covers the settings you paste into a wallet, how to send a request with curl and with viem, what to check when a call fails, and how to decide between a public endpoint and a dedicated Base node.

Chain settings at a glance

Before you write any code, confirm the network parameters. Base mainnet and Base Sepolia are separate networks with different chain IDs, so a wallet or SDK pointed at the wrong one will look like it is working while returning the wrong data.

Setting Base mainnet Base Sepolia
Chain ID 8453 84532
Native currency ETH (18 decimals) ETH (18 decimals)
Block explorer https://basescan.org https://sepolia.basescan.org
RPC transport HTTP (JSON-RPC) HTTP (JSON-RPC)
Typical use Production apps, real value Development, testing, faucets

A quick sanity check: call eth_chainId and confirm it returns 0x2105 for mainnet (8453 in decimal) or 0x14a34 for Sepolia (84532). If the value does not match the network you intended, stop and fix the configuration before debugging anything else.

Adding Base to a wallet

Most wallets accept a custom network. The fields map directly to the table above:

  • Network name: Base
  • RPC URL: your Base endpoint
  • Chain ID: 8453
  • Currency symbol: ETH
  • Block explorer: https://basescan.org

For Base Sepolia, use chain ID 84532 and the Sepolia explorer. If you are building a wallet connection flow, you can request the network programmatically instead of asking users to type it in:

await window.ethereum.request({
  method: "wallet_addEthereumChain",
  params: [{
    chainId: "0x2105",
    chainName: "Base",
    nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
    rpcUrls: ["https://base.api.onfinality.io/public"],
    blockExplorerUrls: ["https://basescan.org"]
  }]
});
Enter fullscreen mode Exit fullscreen mode

If you are using OnFinality for Base, the public endpoint is https://base.api.onfinality.io/public and the Base Sepolia equivalent is https://base-sepolia.api.onfinality.io/public. For production traffic, a dedicated Base node gives you a private endpoint you can rotate without touching user configuration. See the Base network page and Base Sepolia network page for current details.

Sending your first Base RPC request

The fastest way to confirm an endpoint works is a single curl call. This checks connectivity, chain ID, and the latest block in one shot:

curl -s https://base.api.onfinality.io/public \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'

curl -s https://base.api.onfinality.io/public \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
Enter fullscreen mode Exit fullscreen mode

A healthy response returns a JSON object with a result field. If you get an error object instead, the error.code and error.message tell you whether the problem is the request, the endpoint, or the network.

In application code, the same call looks like this with viem:

import { createPublicClient, http } from "viem";
import { base } from "viem/chains";

const client = createPublicClient({
  chain: base,
  transport: http("https://base.api.onfinality.io/public")
});

const blockNumber = await client.getBlockNumber();
const chainId = await client.getChainId();
console.log({ chainId, blockNumber });
Enter fullscreen mode Exit fullscreen mode

Because Base follows Ethereum conventions, most Ethereum tooling works without a Base-specific adapter. The main differences are chain ID, explorer URLs, and a handful of OP-Stack methods.

Which Base RPC methods matter in practice

You do not need every method. Most applications lean on a small set, and knowing which ones are heavier helps you plan capacity.

Method What it does Notes for Base
eth_chainId Returns the chain ID Use to verify you are on 8453 or 84532
eth_blockNumber Latest block height Cheap, good for health checks
eth_getBalance Account balance Common in wallet flows
eth_call Read-only contract call Core of most dapp reads
eth_getLogs Query event logs Heaviest common method; scope by block range
eth_getTransactionReceipt Transaction status Poll after sending a tx
eth_estimateGas Gas estimate Run before sending
eth_sendRawTransaction Broadcast a signed tx Returns a tx hash, not a receipt

eth_getLogs deserves special attention. Wide block ranges and broad topic filters can return large payloads and are a frequent cause of timeouts. Narrow the range, filter by address, and paginate where possible.

Debug path for common Base RPC failures

When something breaks, the error message usually points at the layer. Work through this table before assuming the endpoint is down.

Symptom Likely cause First check
chainId mismatch Wrong network configured Call eth_chainId, compare to 8453/84532
method not found Typo or unsupported method Confirm method name and endpoint transport
Timeout on eth_getLogs Block range too wide Reduce range, add address filter
nonce too low Stale nonce after a stuck tx Re-read eth_getTransactionCount with pending
insufficient funds Gas or value exceeds balance Check balance and gas estimate
Empty result on a read Contract not deployed on this network Verify address on the correct explorer
Intermittent 429 Shared endpoint rate limits Move heavy reads to a dedicated node

Two patterns cause most confusion. First, mixing mainnet and testnet data: a contract address that exists on Base mainnet will not exist on Base Sepolia, and vice versa. Second, treating eth_sendRawTransaction as final: it returns a hash immediately, but you must poll eth_getTransactionReceipt to know whether the transaction succeeded.

Public endpoint or dedicated Base node?

This is the decision most teams face once an app moves past prototyping. The right answer depends on your workload shape, not on a single benchmark.

Workload Public endpoint Dedicated Base node
Prototypes and demos Usually fine Not needed yet
Low-volume reads Usually fine Optional
Heavy eth_getLogs indexing Risky under load Recommended
High-frequency trading or bots Shared limits apply Recommended
Compliance or data isolation needs Not suitable Recommended
Predictable production traffic Shared capacity Recommended

A useful rule: if your application's reliability depends on a specific request pattern that a shared endpoint cannot guarantee, isolate that pattern onto a dedicated node and leave everything else on the public endpoint. This keeps cost proportional to actual need. OnFinality offers both shared RPC API access and dedicated Base nodes; see RPC pricing for the current options and supported RPC networks for the full list.

WebSocket and subscription considerations

Base supports JSON-RPC over HTTP, which is what most applications use. If you need push-style updates, check whether your provider exposes WebSocket transport for Base before designing around subscriptions. HTTP polling of eth_blockNumber or eth_getTransactionReceipt is a reliable fallback and is easier to reason about under failure.

If you do use subscriptions, plan for reconnection logic. Long-lived connections drop, and a subscription that silently stops delivering events is worse than one that fails loudly. Treat the connection as something that will need to be re-established.

Operational checklist before launch

Before you point production traffic at any Base endpoint, confirm the following:

  • Chain ID is verified at runtime, not just in config.
  • The endpoint is reachable from your deployment environment, not only from your laptop.
  • Heavy methods such as eth_getLogs are scoped and paginated.
  • You have a fallback endpoint or a plan for one.
  • Errors are logged with the JSON-RPC error code, not just a generic message.
  • You know which network each contract address belongs to.

A simple monitoring probe keeps you ahead of problems:

async function probe(endpoint) {
  const res = await fetch(endpoint, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_blockNumber", params: [] })
  });
  const json = await res.json();
  return { ok: res.ok && !!json.result, block: json.result };
}
Enter fullscreen mode Exit fullscreen mode

Run this on a schedule and alert on repeated failures. It is a small amount of code that catches a large class of incidents early.

Key Takeaways

  • Base uses standard Ethereum JSON-RPC; chain ID 8453 for mainnet and 84532 for Sepolia.
  • Verify eth_chainId at runtime to avoid silently querying the wrong network.
  • eth_getLogs is the most common source of timeouts; scope block ranges and filters.
  • eth_sendRawTransaction returns a hash, not a receipt; poll for the receipt to confirm success.
  • Public endpoints suit prototypes and light reads; dedicated Base nodes suit heavy, predictable, or isolated workloads.
  • OnFinality provides Base RPC API access and dedicated nodes; check RPC pricing and supported networks.

Frequently Asked Questions

What is the Base chain ID?
Base mainnet uses chain ID 8453. Base Sepolia uses 84532. Always confirm with eth_chainId at runtime.

What is the Base RPC endpoint?
Any JSON-RPC endpoint that serves the Base network. OnFinality exposes a public Base endpoint and dedicated options; see the Base network page for current details.

Can I use Ethereum tooling with Base?
Yes. Base follows Ethereum conventions, so most Ethereum libraries and wallets work once you set the correct chain ID and endpoint.

Why does my Base transaction show as pending?
eth_sendRawTransaction returns a hash before the transaction is included. Poll eth_getTransactionReceipt until it returns a receipt, and check gas settings if it stalls.

Do I need a dedicated Base node?
Only if your workload needs private capacity, isolation, or predictable behavior under heavy reads. Prototypes and light apps usually do not.

How do I debug a Base RPC timeout?
Start with the method. eth_getLogs with a wide range is the usual culprit; narrow the range and add filters before investigating the endpoint itself.

Related resources

Originally published at OnFinality.

Top comments (0)