Skip to main content
Base’s Denim upgrade replaces Flashblocks with canonical 200ms blocks. Denim activated on Base Sepolia on Oct 21, 2026, at 18:00 (UTC), so Flashblocks subscriptions and pending state are no longer available on Base Sepolia. Base Mainnet serves Flashblocks until Denim activates there in November 2026, which is Base’s current target. To move your integration to newHeads, logs, and regular RPC calls, see Base’s migration guide.
Base has no public mempool — pending transactions are held privately by the sequencer, so eth_newPendingTransactionFilter and eth_subscribe("newPendingTransactions") return empty. To watch transactions in real time on Base, subscribe to Flashblocks: the sequencer streams pre-confirmed sub-blocks roughly every 200 ms over WebSocket. This guide streams individual transactions, filtered event logs, and the in-progress block, with tested Python and JavaScript.
Flashblocks is enabled by default on Chainstack Base endpoints. For how it works, see Flashblocks on Base.

Prerequisites

  • A Base mainnet WebSocket endpoint. On Chainstack, copy the WSS endpoint from your Base node’s Access and credentials tab — it looks like wss://base-mainnet.core.chainstack.com/<key>. The examples below use YOUR_CHAINSTACK_WSS_ENDPOINT as a placeholder.
  • Python 3.8+ with the websockets library (pip install websockets), or Node.js 22+ (the WebSocket client is built in, so there are no dependencies to install).

Why pending-transaction filters return empty on Base

Base is an OP Stack chain with a single sequencer. Transactions go to the sequencer’s private mempool and are never gossiped to RPC nodes, so a node has no public pending transactions to report. eth_newPendingTransactionFilter and eth_subscribe("newPendingTransactions") are accepted but always return empty — this is by design, not a node error, and it is the same on every Base RPC provider. See Mempool configurations for the per-protocol breakdown. Flashblocks fills this gap from the other side: instead of unconfirmed mempool transactions, it streams transactions the sequencer has already pre-confirmed into a 200 ms sub-block.

Stream individual transactions

eth_subscribe("newFlashblockTransactions") pushes each transaction as the sequencer pre-confirms it — one WebSocket message per transaction, roughly every 200 ms in batches. By default each message is a transaction hash. Pass true as a second parameter to receive the full transaction object instead.
You get a continuous stream of transaction hashes:

Full transaction objects

Pass true to receive the full transaction with its receipt fields (logs, status, gasUsed) embedded — useful when you want to act on the transaction without a follow-up eth_getTransactionReceipt call:
blockHash is null because the transaction is pre-confirmed, not yet sealed into a final block. blockNumber is the block the sequencer is currently building.

Stream filtered event logs

eth_subscribe("pendingLogs") streams event logs from pre-confirmed transactions, filtered by address and topics the same way as eth_getLogs. This example follows USDC transfers on Base:
Each log carries the standard fields, with blockHash set to zero until the block seals:

Stream the in-progress block

eth_subscribe("newFlashblocks") pushes the block the sequencer is currently building as a standard block object, refreshed roughly every 200 ms. Across updates the block number stays the same while transactions grows, and hash and stateRoot are zero until the block seals — it is the pending block, streamed:
The block number repeats while transactions accumulate, then advances to the next block — each 2-second block is built from about 10 Flashblocks.

Read pre-confirmed state over HTTP

If you need request-response access rather than a stream, the pending block tag reflects the latest Flashblock on Chainstack Base endpoints. eth_getBlockByNumber("pending"), eth_getTransactionReceipt, and eth_call with the pending tag all return pre-confirmed state:
The pending block is one block ahead of latest, with a zero hash and fewer transactions, because the sequencer is still building it.

Production considerations

  • Pre-confirmations are not final. Flashblock state can change until the 2-second block seals, so for settlement confirm the transaction against latest or a finalized block.
  • Empty hashes are expected. blockHash is null on streamed transactions and zero on logs and Flashblocks until the block seals — read the final hash from the sealed block.
  • The stream is best-effort. Flashblocks can arrive in bursts or pause briefly; if the stream stops, fall back to the finalized block from the node.
  • Re-subscribe on reconnect. A subscription ends when the WebSocket drops, so re-send the eth_subscribe request after reconnecting.
  • Throughput tracks network activity. In tests against Base mainnet, newFlashblockTransactions delivered roughly 130–330 transactions per second.
Last modified on October 22, 2026