Guide
July 16, 2026

Automating DeFi Incident Response with a WebSocket Exploit Feed

A production integration guide for the Defimon WebSocket feed: raw vs confirmed streams, reconnect handling, filtering alerts against your contracts and exposure, and what to automate versus page a human for.

Automating DeFi Incident Response with a WebSocket Exploit Feed

TLDR

Every serious DeFi incident response process has the same first step: find out that an attack is happening. Teams that rely on Twitter, Telegram groups, or a user report start their response hours late; teams that consume a machine-readable exploit feed start it in under a second. This guide walks through a production integration of the Defimon WebSocket feed for incident response: choosing between the raw and confirmed streams, connecting and staying connected, filtering alerts against the contracts you actually care about, and deciding what to automate versus what to page a human for. All code is runnable Python, and every field referenced is in the payload specification.

Two Feeds, Two Jobs

Defimon exposes two WebSocket endpoints, and an incident response pipeline generally wants both. The same API key works for either, and a single client may hold both connections at once.

/ws/attacks is the raw feed. It fires the instant a suspicious transaction is detected, typically under 300 milliseconds after execution, and includes some false positives such as aggressive MEV and arbitrage. This is the feed for actions where latency dominates and a false trigger is cheap: paging the on-call, snapshotting state, pre-warming a war room channel.

/ws/confirmed_attacks is the curated stream. An LLM pipeline reviews each detection, drops false positives, and emits a confirmed payload seconds to a couple of minutes later. The confirmed payload is a strict superset of the raw one, adding an always-present llm_explanation string and a uniform trio of victim_protocol_id, victim_protocol, and victim_label fields that are null when the attack does not touch a registered protected address. This is the feed for expensive actions: exiting positions, pausing contracts, posting public statements.

The practical pattern: hair-trigger actions key off the raw feed, irreversible actions wait for confirmation, and the two are correlated by transaction_hash.

Connecting

Authentication is a query parameter, so a connection is one line. The part that matters for incident response is what happens when the connection drops at 3 AM, which is why the loop below reconnects with capped exponential backoff and treats a silent socket as a dead one.

import asyncio import json import websockets API_KEY = "your-api-key" FEED = f"wss://ws.defimon.xyz/ws/confirmed_attacks?api_key={API_KEY}" async def consume(url, handler): backoff = 1 while True: try: async with websockets.connect(url, ping_interval=20, ping_timeout=10) as ws: backoff = 1 async for message in ws: await handler(json.loads(message)) except Exception as exc: print(f"feed disconnected ({exc}); retrying in {backoff}s") await asyncio.sleep(backoff) backoff = min(backoff * 2, 60)

Run one consume() task per feed. Alerts are single JSON objects, one per attack, so there is no framing or pagination to deal with.

Filtering: Does This Alert Concern Us?

A network-wide feed across 8 chains will deliver attacks you do not care about. The filtering question has two levels: does the attack touch our contracts directly, and does it touch something we are exposed to.

Direct matches are an address-set intersection. Check victim_address, exploit_address, and every entry in the enrichment's balance_changes array against a watchlist of your own deployments. Include your dependencies: the vaults you deposit into, the pools that hold your protocol-owned liquidity, the bridges backing the wrapped assets you accept as collateral. As argued in the bridge exploits guide, an exploit of infrastructure you depend on is an exploit of your balance sheet.

WATCHLIST = {addr.lower() for addr in [ "0x1111111111111111111111111111111111111111", # our vault "0x2222222222222222222222222222222222222222", # our staking pool "0x3333333333333333333333333333333333333333", # bridge we depend on ]} def touches_us(alert): candidates = { alert.get("victim_address"), alert.get("exploit_address"), alert.get("attacker_address"), } enrichment = alert.get("protocols") or {} for change in enrichment.get("balance_changes", []): candidates.add(change.get("address")) return any(a and a.lower() in WATCHLIST for a in candidates)

Exposure matches use the enrichment instead of your watchlist. Each alert carries the victim protocol's name, protocol_id, and TVL when known, plus the attacker's USD profit in balance_change. A risk desk holding positions across DeFi can maintain a map of protocol_id to current exposure and react only when the two intersect, with thresholds like balance_change > 1_000_000 or severity == "CRITICAL" keeping the noise floor low. If you register your contracts as protected addresses, the feed does this matching server-side: the confirmed stream sets victim_protocol_id to a non-null value whenever a registered address is hit, so the entire filter collapses to one null check.

Acting: Page, Exit, Pause

What to wire the filter to depends on how reversible the action is.

Paging is free to trigger, so key it off the raw feed with a generous filter. A webhook into PagerDuty or a bot message into the team channel carrying transaction_hash, network, and the llm_explanation (once the confirmed alert lands) gives the on-call everything needed to open the transaction in a trace explorer and make the first judgment call.

Position exits are costlier but recoverable, and they are the most common automation among feed consumers. One fund with a nine-figure DeFi book consumes this feed and automatically unwinds exposure to any protocol the moment a confirmed attack against it arrives, turning a detection into an exit in under a second. The Balancer V2 incident shows why this matters: the attack rolled across multiple chains for hours, and holders of affected pool tokens who reacted to the first confirmed alert got out long before the damage was fully priced in.

Automated pausing is the sharpest tool and deserves the most guardrails. A reasonable design pauses only when a confirmed alert names your own contract as the victim (victim_protocol_id matches, or victim_address is in your watchlist), requires the pause transaction to be pre-signed and tested, and always pages humans in parallel. A protocol that can be paused by any raw alert is a denial-of-service surface; a protocol that can only be paused by a human reading Twitter is a victim. The middle exists and it is well understood.

Reliability Details That Bite Later

Three details separate a demo integration from a production one. First, deduplicate by transaction_hash: the same attack can legitimately appear on both feeds, and your handler should treat the confirmed alert as an upgrade of the raw one, not a new incident. Second, parse defensively in exactly the ways the spec says you must: severity, victim_address, balance_change, and the whole protocols object are nullable, enrichment comes in three shapes, and on the raw feed the victim_protocol_* fields are simply absent unless a protected address was hit. Third, monitor the monitor: alert if no message of any kind arrives for an abnormally long window, and log proc_time against your own receive time so you notice if your consumer starts lagging.

Test the pipeline before an incident tests it for you. Store real payloads from the feed and replay them through your handler in CI, including a multi-chain sequence and an alert with protocols: null. The postmortems on this blog double as scenario material: replay a flash loan attack against a watchlisted address and verify the pager fires, the dedup holds when the confirmed alert follows, and the pause path stays quiet for alerts that merely resemble trouble.

The full integration described here is a WebSocket connection, a JSON parser, and an afternoon of routing logic against your own infrastructure. WebSocket access is $200 per month, self-serve, with the API key issued the moment payment confirms.

Be Among The First to Know

In DeFi, a small delay costs millions. Get the threat intelligence to rely on.

@DefimonAlerts

© 2026 Defimon by Decurity

Powered by QuickNode