Real-time EVM mempool monitoring with pluggable filters. Streams pending transactions over WebSocket, fetches the full transaction body for each, runs your filter, and prints structured events with decoded method signatures.
Useful for: building MEV detectors, watching specific addresses, tracking large value transfers, monitoring DEX swap activity, debugging pending-tx behavior, or just learning how mempool data actually flows.
git clone https://github.com/swiftnodes/mempool-watcher
cd mempool-watcher
cp .env.example .env # add your SwiftNodes API key
npm install
CHAIN=base npm startSample output:
2026-05-13T14:31:22.118Z
from: 0xab12...90cd
to: 0x4752ba5DBc23F44D87826276BF6Fd6b1C372aD24
value: 0.0 ETH
method: 0x7ff36ab5 (swapExactETHForTokens(uint256,address[],address,uint256))
gas: 0.42 gwei (maxFee)
tx: https://basescan.org/tx/0xdeadbeef...
Six chains out of the box, easy to extend:
- Ethereum (
eth) - Base (
base) - BNB Smart Chain (
bsc) - Arbitrum One (
arbitrum) - Optimism (
optimism) - Polygon (
polygon)
Powered by SwiftNodes — full mempool access available on every plan (most providers gate this on premium tiers).
src/
chains.js ← Per-chain config: WebSocket URL, native symbol, explorer
filters.js ← Composable filter primitives (allOf, anyOf, methodSelector, etc.)
index.js ← Subscribes, fetches tx bodies, applies filter, prints
- Subscribe to
eth_subscribe("newPendingTransactions")via WebSocket. - For each pending tx hash, fetch the full transaction body with
eth_getTransactionByHash. - Apply your filter (composable function) — drop if it doesn't match.
- Decode the method selector against a known-signature table.
- Print a structured event.
Average tx-to-print latency: 50-300ms depending on network. Mempool firehose volume varies wildly by chain — Ethereum ~50-200 pending/sec, Base ~100-500 pending/sec, BSC ~1000+ pending/sec during peak.
The default filter captures: ETH transfers ≥ 1 native unit, token approvals, and major DEX swaps. Edit FILTER in src/index.js:
import { allOf, anyOf, not, toAddress, methodSelector, minValueWei, isEthTransfer } from "./filters.js";
// Watch a specific whale wallet
const FILTER = anyOf(
fromAddress("0x...whale..."),
toAddress("0x...whale..."),
);
// Watch all transactions to a specific contract
const FILTER = toAddress("0x...vault...");
// Watch large value transfers (>= 100 ETH)
const FILTER = allOf(isEthTransfer(), minValueWei(100n * 10n ** 18n));
// Watch Uniswap Universal Router calls only
const FILTER = methodSelector("0x3593564c");
// Compose: watch a whale's swap activity specifically
const FILTER = allOf(
fromAddress("0x...whale..."),
anyOf(
methodSelector("0x7ff36ab5"), // swapExactETHForTokens
methodSelector("0x38ed1739"), // swapExactTokensForTokens
),
);Filter primitives in src/filters.js:
| Primitive | What it does |
|---|---|
toAddress(addr) |
Match txs sent TO this address |
fromAddress(addr) |
Match txs sent FROM this address |
methodSelector(hex) |
Match by 4-byte function selector |
minValueWei(wei) |
Match txs with value ≥ N |
isEthTransfer() |
Match value transfers (no calldata) |
isContractCall() |
Match contract interactions |
allOf(...) |
AND combinator |
anyOf(...) |
OR combinator |
not(filter) |
NOT combinator |
const FILTER = allOf(isEthTransfer(), minValueWei(50n * 10n ** 18n));const FILTER = anyOf(fromAddress(WHALE), toAddress(WHALE));const FILTER = toAddress("0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"); // Uniswap V3 routerconst FILTER = (tx) => tx.to === null;Swap console.log(...) in onTransactions for an fetch() to your Discord/Slack/Telegram webhook URL. Two-line change.
Most RPC providers either don't expose newPendingTransactions at all, or gate it on premium tiers ($1500+/mo with some). SwiftNodes:
- Full mempool WebSocket subscriptions on every plan, including free tier
- 6 chains here, 75+ total with the same API
- No-KYC signup so you can experiment without paperwork
Run this in production for serious MEV use cases? You'll want a paid tier for higher rate limits and dedicated WebSocket connection slots, but the free tier is enough to experiment and validate.
- You're not the only one watching. Public mempool is competitive. By the time your bot acts on a pending tx, a thousand others have too. Latency edge is everything for actual MEV.
- Some chains have private mempools. BSC and Polygon have validator-only "MEV pools" you can't see from public RPC. You'll miss those.
- Subscription depth varies. Different upstream nodes have different mempool views; what you see depends on which node your subscription routes to.
- Bandwidth is real. Full firehose with no filter on Ethereum mainnet is ~5 MB/s sustained. Filter aggressively.
MIT — fork, modify, ship.
PRs welcome for:
- More method signatures in
KNOWN_METHODS - Additional chains
- Filter primitives for common patterns (token transfers by ERC20 contract, etc.)
- Notification integrations