2026-04-25 · 1F Engineering

Blockchain mempool monitoring API: build a pre-confirmation alert in 10 minutes

Step-by-step: subscribe to mempool transactions across 13 EVM chains plus Bitcoin via WebSocket, filter by token or protocol, and fire alerts before transactions confirm. Drop-in code samples.

The most underused weapon in a security or compliance team's stack is pre-confirmation alerting — knowing about a transaction in the mempool before it lands in a block. This post shows how to wire it up against the 1F real-time stream API in ten minutes.

Why pre-confirmation matters

A confirmed-tx alert tells you what happened. A pending-tx alert tells you what's about to happen — with 12 seconds of lead time on Ethereum, 3 seconds on BSC, sub-second on Arbitrum and Optimism.

That gap is the difference between:

The subscription model

1F's mempool stream sits on top of the pendingTransactions WebSocket subscription on every EVM chain we ingest. You give it a filter; the server pushes JSON frames as matching pending txs arrive.

# 1. Create the subscription
SID=$(curl -s -X POST https://1f.ai/api/stream/subscribe \
  -H "X-API-Key: $KEY" -H "content-type: application/json" \
  -d '{
    "chains": ["bsc"],
    "tokens": ["0x2170ed0880ac9a755fd29b2688956bd959f933f8"],
    "protocols": ["uniswapV2", "pancake"],
    "includePending": true,
    "includeConfirmed": false
  }' | jq -r .subscriptionId)

# 2. Open WebSocket
websocat "wss://1f.ai/api/stream/ws?subscriptionId=$SID&apiKey=$KEY"

You'll get one frame per matching pending tx:

{
  "type": "pending",
  "chain": "bsc",
  "txHash": "0x14cb…0e13f",
  "from": "0x9bbcf…34fa4",
  "to":   "0x10ed4…56024e",
  "valueWei": 1000000,
  "decodedProtocol": "uniswapV2.swap",
  "seenAtUtc": "2026-04-25T15:32:42Z"
}

Filter by token (catches swap-internal references)

A naive filter matches only when tx.to == tokenContract. That misses 99% of real activity because most token movement is inside a router call. The 1F filter does a calldata substring scan for the bare hex address — Uniswap/Pancake-style routers embed tokenIn and tokenOut as 20-byte words inline, so the filter catches them.

Set tokens: ["0x...weth", "0x...usdt"] and you'll get every pending swap that touches WETH or USDT, regardless of which router or aggregator it goes through.

Filter by protocol family

Use protocols: ["uniswapV2", "pancake", "curve", "aave"] to subset by decoder family. The /api/decoders endpoint lists every decoded protocol. Family-prefix matches work — "pancake" matches pancake.v3.exactInputSingle, pancake.router02.swapExactETHForTokens, and so on.

Cross-chain bridge filter

The killer use case: alert me when an attacker bridges from Ethereum to BSC. Set originChain: "ethereum" and the filter fires on confirmed BSC events whose source-side bridge tx was on Ethereum (joined deterministically by message-id across LayerZero, Wormhole, CCTP, Stargate, Hop, Across, Synapse, deBridge, native bridges).

{
  "chains": ["bsc"],
  "originChain": "ethereum",
  "addresses": ["0xVictim1", "0xVictim2"]
}

Plan-tier rate caps

Plan Events/sec
Free 5
Starter ($50/mo) 50
Pro ($200/mo) 500
Enterprise unlimited

Over-cap clients get {"type":"throttled","dropped":N} heartbeats every 5 seconds instead of disconnect — the client knows it's hitting the cap and can either upgrade or narrow the filter. See Pricing.

Mempool visibility

The depth of mempool 1F sees depends on the upstream RPC endpoint configured per chain. Public endpoints sample aggressively. For production-grade visibility on a busy chain (BSC, Polygon, Solana mempool), wire in a paid endpoint via the per-chain env override:

ChainGraph__Chains__bsc__wssUrl=wss://bsc.nodereal.io/ws/v1/YOUR_KEY

The endpoint surface and filter semantics are identical regardless of upstream — only the visibility ceiling changes.

Code sample (Node.js)

import WebSocket from 'ws';

const SID = await fetch('https://1f.ai/api/stream/subscribe', {
  method: 'POST',
  headers: { 'X-API-Key': process.env.ONEF_KEY, 'content-type': 'application/json' },
  body: JSON.stringify({
    chains: ['ethereum', 'bsc', 'polygon'],
    tokens: ['0xdac17f958d2ee523a2206206994597c13d831ec7'], // USDT
    includePending: true
  })
}).then(r => r.json()).then(d => d.subscriptionId);

const ws = new WebSocket(`wss://1f.ai/api/stream/ws?subscriptionId=${SID}&apiKey=${process.env.ONEF_KEY}`);
ws.on('message', (msg) => {
  const ev = JSON.parse(msg);
  if (ev.type === 'pending') {
    console.log(`pending USDT touch on ${ev.chain}: ${ev.txHash} ${ev.decodedProtocol}`);
    // → fire alert / freeze deposit / page on-call
  }
});

Try it

Sign up at /auth?signup=1 — free tier covers up to 5 events/sec with no credit card required. Same code works against the demo key (X-API-Key: dev-test-key-123) for quick docs samples.


Related: Investigating a bridge exploit in 5 minutes, Alchemy vs QuickNode vs 1F, OFAC sanctions screening.

← All posts