Docs

Base - Ethereum L2 Documentation

Complete guide to Base L2 integration with Dwellir RPC. Learn how to build on Base, access JSON-RPC methods, and optimize your dApp performance.

Base RPC

With Dwellir, you get access to our global Base network which always routes your API requests to the nearest available location, ensuring low latency and the fastest speeds.

Get your API key

Why Build on Base?

Base is Coinbase's Ethereum Layer 2 solution, designed to bring the next billion users onchain. Built on Optimism's OP Stack, Base offers:

Lightning Fast Performance

  • 200ms Flashblocks - Sub-block preconfirmations every ~200ms via Flashblocks
  • 10-100x lower costs than Ethereum mainnet
  • EIP-4844 enabled - Leveraging blob data for even lower fees

Enterprise Security

  • Backed by Coinbase - Institutional-grade infrastructure
  • Ethereum security - Inherits L1 security guarantees
  • Battle-tested - Built on proven Optimism technology

Massive Ecosystem

  • 1M+ weekly active users - Rapidly growing user base
  • $2B+ TVL - Strong DeFi ecosystem
  • Major integrations - Circle USDC, Chainlink, The Graph

Quick Start with Base

Connect to Base in seconds with Dwellir's optimized endpoints:

Base RPC Endpoints
HTTPS
curl -sS -X POST https://api-base-mainnet-archive.n.dwellir.com/<API_Keys_Are_Not_Made_for_Bots> \  -H 'Content-Type: application/json' \  -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
import { JsonRpcProvider } from 'ethers';const provider = new JsonRpcProvider(  'https://api-base-mainnet-archive.n.dwellir.com/<API_Keys_Are_Not_Made_for_Bots>');const latest = await provider.getBlockNumber();console.log('block', latest);
import requestsurl = 'https://api-base-mainnet-archive.n.dwellir.com/<API_Keys_Are_Not_Made_for_Bots>'payload = {  'jsonrpc': '2.0', 'id': 1,  'method': 'eth_blockNumber', 'params': []}resp = requests.post(url, json=payload)print(resp.json())
package mainimport (  "bytes"  "fmt"  "io"  "net/http")func main() {  url := "https://api-base-mainnet-archive.n.dwellir.com/<API_Keys_Are_Not_Made_for_Bots>"  payload := []byte(`{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}`)  resp, err := http.Post(url, "application/json",    bytes.NewBuffer(payload))  if err != nil { panic(err) }  defer resp.Body.Close()  body, _ := io.ReadAll(resp.Body)  fmt.Println(string(body))}

Installation & Setup

Network Information

ParameterValueDetails
Chain ID8453Mainnet
Block Time~200msFlashblocks
Gas TokenETHNative token
RPC StandardEthereumJSON-RPC 2.0

API Reference

Base supports the full Ethereum JSON-RPC API specification plus Base-specific Flashblocks methods and subscriptions.

Flashblocks - 200ms Preconfirmations

Dwellir's Base endpoints support Flashblocks, delivering sub-block updates every ~200ms. Instead of waiting for a full 2-second block, your application can read preconfirmed state, stream pending transactions, and get receipts within milliseconds of submission.

What You Get

CapabilityDescription
"pending" block tagAll state-reading methods (eth_getBlockByNumber, eth_call, eth_getBalance, eth_getLogs, etc.) accept "pending" to query the latest Flashblock state
Preconfirmed receiptseth_getTransactionReceipt returns receipts for transactions in the current Flashblock before the block is sealed
eth_sendRawTransactionSyncSubmit a transaction and get a full receipt synchronously in about 200ms
eth_simulateV1Simulate transaction bundles against the latest state with transfer tracing
base_transactionStatusCheck whether a transaction is still pending in the Base mempool
WebSocket subscriptionsnewFlashblocks, newFlashblockTransactions, and pendingLogs for real-time streaming

Stream Flashblocks via WebSocket

Query Preconfirmed State

Use the "pending" block tag to read state from the latest Flashblock:

JavaScript
// Get balance reflecting the latest Flashblock
const balance = await provider.send('eth_getBalance', [address, 'pending']);

// Execute a call against Flashblock state
const result = await provider.send('eth_call', [{ to: contract, data: calldata }, 'pending']);

// Get logs from the current Flashblock
const logs = await provider.send('eth_getLogs', [{ fromBlock: 'pending', toBlock: 'pending' }]);

Common Integration Patterns

Transaction Monitoring

Monitor pending and confirmed transactions efficiently:

JavaScript
// Watch for transaction confirmation
async function waitForTransaction(txHash) {
  const receipt = await provider.waitForTransaction(txHash, 1);

  // L2 specific: Check L1 data availability
  if (receipt.l1Fee) {
    console.log('L1 data cost:', receipt.l1Fee);
  }

  return receipt;
}

Gas Optimization

Optimize gas costs on Base L2:

JavaScript
// Estimate L2 execution gas
const l2Gas = await provider.estimateGas(tx);

// Get current L1 data fee (Base specific)
const l1DataFee = await provider.send('eth_estimateL1Fee', [tx]);

// Total cost = L2 execution + L1 data posting
const totalCost = l2Gas + BigInt(l1DataFee);

Event Filtering

Efficiently query contract events:

JavaScript
// Query events with automatic retry and pagination
async function getEvents(contract, eventName, fromBlock = 0) {
  const filter = contract.filters[eventName]();
  const events = [];
  const batchSize = 2000; // Base recommended batch size

  for (let i = fromBlock; i <= currentBlock; i += batchSize) {
    const batch = await contract.queryFilter(
      filter,
      i,
      Math.min(i + batchSize - 1, currentBlock)
    );
    events.push(...batch);
  }

  return events;
}