pending block tag, not through dedicated WebSocket subscriptions. To follow transactions in real time on Optimism, poll the pending block roughly every 200 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 Subblocks work on Optimism, see Subblocks on Optimism. For Base, which 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. Like every OP Stack chain, Optimism has no public mempool (see Mempool configurations), so eth_subscribe("newPendingTransactions") reports only transaction hashes as the sequencer includes them in subblocks. The pending block tag gives you the transactions themselves and the pre-confirmed state, and it reflects the latest subblock and advances every ~200 ms.
Track pre-confirmed transactions
Polleth_getBlockByNumber("pending", false) every 200 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 ~200 ms as new subblocks arrive.
seen set de-duplicates hashes that repeat across polls of the same in-progress block. In a 30-second test against Optimism Mainnet, the script emitted 230 transaction hashes, about 8 per second.
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. Polled with a 200 ms pause between requests:
pending hash is non-zero and changes with each subblock. The pending hash is not the hash of the sealed block, and the pending block’s stateRoot is all zeros. 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, which updates about every 200 ms instead of every 2 s with each 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 subblock.eth_sendRawTransactionSyncsubmits a signed transaction and returns its pre-confirmed receipt in the same response.
Production considerations
- Pre-confirmations are not final. The sequencer can abandon or reorganize the block in progress until the 2-second canonical block seals, so for settlement confirm against
latestor a finalized block. - Poll at ~200 ms. That matches the subblock 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.
- A poll that lands after a block seals misses the transactions added to that block since the previous poll. To capture every transaction, also read each sealed block with
eth_getBlockByNumber. newPendingTransactionscarries transaction hashes only. Optimism has no public mempool, so the subscription reports a transaction when the sequencer includes it in a subblock. For transaction details, receipts, and pre-confirmed state, use thependingtag.
Related
- Subblocks on Optimism — how Subblocks work 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