Skip to content

Flashblocks RPC

Flashblocks are sub-block preconfirmations produced every 200ms on Base. Read preconfirmed balances, nonces, receipts, and block data through standard JSON-RPC, or stream every flashblock as it lands.

A single Base block (produced every 2 seconds) is divided into ten flashblocks streamed at 200ms intervals. Each flashblock is a delta containing new transactions and the resulting state changes. The Flashblocks RPC exposes this preconfirmed state through the standard Ethereum JSON-RPC interface by supporting the "pending" block tag.

Block N (2s)
├── Flashblock 0 (0ms)
├── Flashblock 1 (200ms)
├── Flashblock 2 (400ms)
├── Flashblock 3 (600ms)
├── Flashblock 4 (800ms)
├── Flashblock 5 (1000ms)
├── Flashblock 6 (1200ms)
├── Flashblock 7 (1400ms)
├── Flashblock 8 (1600ms)
└── Flashblock 9 (1800ms)
Block N+1 (2s)
└── ...

Pass "pending" to any supported JSON-RPC method to read the latest preconfirmed state. The same call against "latest" returns the last sealed block.

eth_getBalance with the "pending" tag returns the balance reflecting every transaction included in the most recent flashblock — usually within 200ms of the user’s submission.

The hex result is the balance in wei.

Terminal window
curl -X POST https://your-base-rpc-endpoint \
-H "Content-Type: application/json" \
-d '{
"method": "eth_getBalance",
"params": ["0xYourAddress", "pending"],
"id": 1,
"jsonrpc": "2.0"
}'
# {
# "id": 1,
# "jsonrpc": "2.0",
# "result": "0x1bc16d674ec80000"
# }

After submitting a transaction, poll eth_getTransactionReceipt immediately — no need to wait for the next sealed block.

A preconfirmed receipt is identifiable by its zero blockHash. Once the parent block seals, the same receipt comes back with a real block hash.

Terminal window
curl -X POST https://your-base-rpc-endpoint \
-H "Content-Type: application/json" \
-d '{
"method": "eth_getTransactionReceipt",
"params": ["0xYourTxHash"],
"id": 1,
"jsonrpc": "2.0"
}'
# {
# "result": {
# "transactionHash": "0x...",
# "blockHash": "0x000...000",
# "blockNumber": "0x123",
# "status": "0x1",
# "gasUsed": "0x5208",
# "logs": []
# }
# }

eth_getBlockByNumber with "pending" returns the in-progress block including every transaction landed in flashblocks so far.

Pass true as the second parameter for full transaction objects, false for hashes only.

Terminal window
curl -X POST https://your-base-rpc-endpoint \
-H "Content-Type: application/json" \
-d '{
"method": "eth_getBlockByNumber",
"params": ["pending", true],
"id": 1,
"jsonrpc": "2.0"
}'

eth_getTransactionCount against "pending" returns a nonce that already accounts for transactions sitting in flashblocks.

This avoids nonce collisions when an account submits many transactions in rapid succession.

Terminal window
curl -X POST https://your-base-rpc-endpoint \
-H "Content-Type: application/json" \
-d '{
"method": "eth_getTransactionCount",
"params": ["0xYourAddress", "pending"],
"id": 1,
"jsonrpc": "2.0"
}'
# {
# "result": "0x5"
# }

Pass "pending" as the block tag to any read method to get preconfirmed values.

For receipts, poll getTransactionReceipt on a 200ms interval — that matches the flashblock cadence.

import { JsonRpcProvider } from "ethers";
const provider = new JsonRpcProvider("https://your-base-rpc-endpoint");
const balance = await provider.getBalance("0xYourAddress", "pending");
const nonce = await provider.getTransactionCount("0xYourAddress", "pending");
async function waitForFlashblockReceipt(txHash, intervalMs = 200) {
while (true) {
const receipt = await provider.getTransactionReceipt(txHash);
if (receipt) return receipt;
await new Promise((r) => setTimeout(r, intervalMs));
}
}

viem accepts blockTag: "pending" on every read method. Receipts return as soon as the transaction is included in a flashblock.

import { createPublicClient, http } from "viem";
import { base } from "viem/chains";
const client = createPublicClient({
chain: base,
transport: http("https://your-base-rpc-endpoint"),
});
const balance = await client.getBalance({
address: "0xYourAddress",
blockTag: "pending",
});
const nonce = await client.getTransactionCount({
address: "0xYourAddress",
blockTag: "pending",
});
const receipt = await client.getTransactionReceipt({
hash: "0xYourTxHash",
});

For real-time updates, connect to the WebSocket endpoint and subscribe to flashblocks_v1. Each flashblock arrives as it is produced — five times per second.

Open a WebSocket, send an eth_subscribe request with the flashblocks_v1 topic, and handle each eth_subscription message as it arrives.

flashblock.diff carries the new transactions and state changes since the previous flashblock; flashblock.index runs from 0 to 9 within each parent block.

import WebSocket from "ws";
const ws = new WebSocket("wss://your-base-ws-endpoint");
ws.on("open", () => {
ws.send(
JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "eth_subscribe",
params: ["flashblocks_v1"],
})
);
});
ws.on("message", (data) => {
const msg = JSON.parse(data);
if (msg.method === "eth_subscription") {
const flashblock = msg.params.result;
console.log("Index:", flashblock.index);
console.log("Txs:", flashblock.diff.transactions?.length ?? 0);
}
});

Each streamed flashblock contains:

FieldDescription
payload_idIdentifier for the parent payload (block being built).
indexFlashblock index within the current block (0, 1, 2, …).
basePresent only on index 0. Contains the base execution payload.
diffDelta of transactions, receipts, and state changes since the previous flashblock.
metadataAdditional metadata, including the flashblock access list if enabled.

When the "pending" tag is used but no preconfirmed data is available — for example, during sequencer downtime or between blocks — the RPC falls back to the "latest" confirmed state. That means:

  • Applications do not need special error handling for missing flashblock state.
  • Results are always consistent: either preconfirmed or latest confirmed.
  • The caller cannot distinguish a “pending equals latest” response from a fallback, so applications should not assume the data is fresher than the latest block.

Standard JSON-RPC error codes apply:

ScenarioBehavior
Invalid method parametersStandard JSON-RPC error response with error code and message.
Transaction not foundnull result (not an error).
Block not foundnull result (not an error).
Flashblocks disabledFalls back to standard RPC behavior. No error is returned.

A preconfirmed receipt can be identified by its blockHash:

  • PreconfirmedblockHash is the zero hash.
  • FinalizedblockHash is a real block hash.
function isPreconfirmed(receipt) {
return (
receipt.blockHash ===
"0x0000000000000000000000000000000000000000000000000000000000000000"
);
}