pending block tag, not through WebSocket subscriptions. To follow transactions in real time on Optimism, poll the pending block roughly every 250 ms and track the transactions that are new since the last poll. This guide does that with tested Python and JavaScript, then covers the pre-confirmed read methods.
For how Flashblocks works on Optimism, see Flashblocks on Optimism. For Base, which also exposes Flashblocks as WebSocket subscriptions, see Stream real-time transactions on Base with Flashblocks.
Prerequisites
- An Optimism mainnet HTTPS endpoint. On Chainstack, copy it from your Optimism node’s Access and credentials tab — it looks like
https://optimism-mainnet.core.chainstack.com/<key>. The examples useYOUR_OPTIMISM_HTTPS_ENDPOINTas a placeholder. - Python 3.8+ with the
requestslibrary (pip install requests), or Node.js 18+ (thefetchAPI is built in, so there are no dependencies to install).
Why Optimism uses the pending tag, not eth_subscribe
On Optimism, the Flashblocks subscriptions that exist on Base —eth_subscribe("newFlashblockTransactions"), newFlashblocks, and pendingLogs — are not exposed; calling them returns -32602 Invalid params. And like every OP Stack chain, Optimism has no public mempool, so eth_subscribe("newPendingTransactions") is effectively empty (see Mempool configurations). The supported real-time interface is the pending block tag, which reflects the latest Flashblock and advances every ~250 ms.
Track pre-confirmed transactions
Polleth_getBlockByNumber("pending", false) every 250 ms and emit transaction hashes you have not seen before. Each poll returns the block the sequencer is currently building; within one block number the transaction list grows every ~250 ms as new Flashblocks arrive.
seen set de-duplicates hashes that repeat across polls of the same in-progress block. In a test against Optimism mainnet this emitted roughly 33 new transactions per second, tracking network activity.
How the pending block evolves
Each poll of thepending tag returns the same block number with more transactions and a different pre-confirmation hash, until the block seals and the number advances. Sampled every 250 ms:
pending hash is non-zero and changes with each Flashblock — so track transactions by their own hash, not by the block hash.
Read pre-confirmed state
Thepending tag also serves request-response reads against pre-confirmed state, returning answers in ~250 ms instead of waiting ~2 s for the next canonical block:
eth_getBlockByNumber,eth_call,eth_getBalance,eth_getTransactionCount,eth_getCode,eth_getStorageAt, andeth_estimateGaswith thependingtag.eth_getTransactionReceiptandeth_getTransactionByHashreturn the pre-confirmed receipt or transaction as soon as it lands in a Flashblock.eth_sendRawTransactionSyncsubmits a signed transaction and returns its pre-confirmed receipt in the same response.
Production considerations
- Pre-confirmations are not final. The pending block can change until the 2-second canonical block seals, so for settlement confirm against
latestor a finalized block. - Poll at ~250 ms. That matches the Flashblock cadence; polling much faster mostly returns the same state.
- De-duplicate by transaction hash. The same transaction appears in every poll of the block it belongs to until that block seals.
newPendingTransactionswill not help. Optimism has no public mempool, so the subscription is effectively empty — thependingtag is the real-time source.
Related
- Flashblocks on Optimism — how Flashblocks works on Optimism, including the Optimism vs. Base comparison
- Stream real-time transactions on Base with Flashblocks — Base’s WebSocket-subscription approach
- Mempool configurations — mempool availability by protocol
eth_getBlockByNumber