import React, { useEffect, useMemo, useState } from "react";
import { motion } from "framer-motion";
import { Search, Activity, TrendingDown, Zap, Filter, RefreshCw, Wifi, WifiOff, Bell, ChevronRight } from "lucide-react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
const MOCK_DROPS = [
{
id: "pm-1",
market: "Will Bitcoin hit $120k before June 30?",
category: "Crypto",
outcome: "YES",
currentPrice: 0.58,
previousPrice: 0.67,
dropPct: 13.43,
volume24h: 184200,
lastTradeUsd: 12450,
aggressiveFlowUsd: 48210,
confidence: 91,
slug: "bitcoin-120k-before-june-30",
updatedAt: "10s ago",
signal: "Hard drop",
traderHint: "Large market sells hit the YES side",
},
{
id: "pm-2",
market: "Will Trump meet Xi before August?",
category: "Politics",
outcome: "YES",
currentPrice: 0.41,
previousPrice: 0.48,
dropPct: 14.58,
volume24h: 291100,
lastTradeUsd: 31800,
aggressiveFlowUsd: 72900,
confidence: 95,
slug: "trump-xi-meeting-before-august",
updatedAt: "24s ago",
signal: "Whale flow",
traderHint: "Several large prints clustered within 20 seconds",
},
{
id: "pm-3",
market: "Will Ethereum ETF staking be approved in 2026?",
category: "Crypto",
outcome: "NO",
currentPrice: 0.36,
previousPrice: 0.42,
dropPct: 14.29,
volume24h: 92200,
lastTradeUsd: 7400,
aggressiveFlowUsd: 19850,
confidence: 82,
slug: "eth-etf-staking-approved-2026",
updatedAt: "39s ago",
signal: "Fast selloff",
traderHint: "Orderbook got swept and best bid stepped down twice",
},
{
id: "pm-4",
market: "Will the Fed cut rates by July?",
category: "Macro",
outcome: "YES",
currentPrice: 0.52,
previousPrice: 0.56,
dropPct: 7.14,
volume24h: 404500,
lastTradeUsd: 26750,
aggressiveFlowUsd: 51400,
confidence: 77,
slug: "fed-cut-rates-by-july",
updatedAt: "1m ago",
signal: "Steady pressure",
traderHint: "Continuous offers leaning on the bid",
},
{
id: "pm-5",
market: "Will OpenAI launch GPT-6 before 2027?",
category: "Tech",
outcome: "YES",
currentPrice: 0.61,
previousPrice: 0.69,
dropPct: 11.59,
volume24h: 138800,
lastTradeUsd: 9100,
aggressiveFlowUsd: 23100,
confidence: 80,
slug: "openai-gpt6-before-2027",
updatedAt: "2m ago",
signal: "Sharp move",
traderHint: "Heavy matched volume moved the midpoint lower",
},
{
id: "pm-6",
market: "Will the Lakers make the playoffs?",
category: "Sports",
outcome: "YES",
currentPrice: 0.44,
previousPrice: 0.47,
dropPct: 6.38,
volume24h: 561000,
lastTradeUsd: 44100,
aggressiveFlowUsd: 80300,
confidence: 73,
slug: "lakers-make-playoffs",
updatedAt: "3m ago",
signal: "Liquid move",
traderHint: "Deep market but strong sell flow still moved price",
},
];
function formatUsd(value) {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 0,
}).format(value);
}
function formatProb(value) {
return `${(value * 100).toFixed(1)}%`;
}
function StatCard({ title, value, sub, icon: Icon }) {
return (
);
}
export default function PolymarketDropTerminal() {
const [search, setSearch] = useState("");
const [category, setCategory] = useState("All");
const [minDrop, setMinDrop] = useState(5);
const [liveMode, setLiveMode] = useState(false);
const [connected, setConnected] = useState(false);
const [selectedId, setSelectedId] = useState(MOCK_DROPS[0].id);
useEffect(() => {
if (!liveMode) {
setConnected(false);
return;
}
const timer = setTimeout(() => setConnected(true), 850);
return () => clearTimeout(timer);
}, [liveMode]);
const categories = useMemo(() => {
return ["All", ...Array.from(new Set(MOCK_DROPS.map((x) => x.category)))];
}, []);
const filtered = useMemo(() => {
return MOCK_DROPS
.filter((item) => category === "All" || item.category === category)
.filter((item) => item.dropPct >= minDrop)
.filter((item) => {
const q = search.trim().toLowerCase();
if (!q) return true;
return (
item.market.toLowerCase().includes(q) ||
item.category.toLowerCase().includes(q) ||
item.signal.toLowerCase().includes(q)
);
})
.sort((a, b) => b.dropPct - a.dropPct);
}, [search, category, minDrop]);
const selected = filtered.find((x) => x.id === selectedId) || filtered[0] || null;
useEffect(() => {
if (!selected && filtered[0]) setSelectedId(filtered[0].id);
}, [selected, filtered]);
const totalFlow = filtered.reduce((sum, item) => sum + item.aggressiveFlowUsd, 0);
const avgDrop = filtered.length ? filtered.reduce((sum, item) => sum + item.dropPct, 0) / filtered.length : 0;
const hardestDrop = filtered[0]?.dropPct ?? 0;
return (
Detect sharp Polymarket price drops
POD-style terminal for Polymarket markets. Focused on fast downside moves, aggressive orderflow,
and markets where price gets hit hard in a short time window.
setLiveMode((v) => !v)}
>
{liveMode ? : }
{liveMode ? "Live mode on" : "Demo mode"}
Create alert
{categories.map((item) => (
setCategory(item)}
className={`rounded-full border px-3 py-1.5 text-sm transition ${
category === item
? "border-white bg-white text-black"
: "border-white/10 bg-white/5 text-white/65 hover:bg-white/10"
}`}
>
{item}
))}
Market
Outcome
Now
Drop
24h Vol
Signal
{filtered.map((item) => {
const active = item.id === selected?.id;
return (
setSelectedId(item.id)}
className={`grid w-full grid-cols-[1.8fr_0.7fr_0.7fr_0.9fr_0.8fr_0.8fr] gap-3 px-4 py-4 text-left transition ${
active ? "bg-white/10" : "bg-transparent hover:bg-white/5"
}`}
>
{item.market}
{item.category} ยท {item.updatedAt}
{item.outcome}
{formatProb(item.currentPrice)}
-{item.dropPct.toFixed(2)}%
{formatUsd(item.volume24h)}
{item.signal}
);
})}
{!filtered.length && (
No markets match your current filters.
)}
Signal detail
{selected ? (
Selected market
{selected.market}
{selected.category}
{selected.outcome}
{selected.signal}
Previous price
{formatProb(selected.previousPrice)}
Current price
{formatProb(selected.currentPrice)}
Last trade
{formatUsd(selected.lastTradeUsd)}
Aggressive flow
{formatUsd(selected.aggressiveFlowUsd)}
Drop confidence
{selected.confidence}%
{selected.traderHint}
How this should work live
Pull active markets from Gamma, subscribe to token IDs over the public market WebSocket,
compare current midpoint or last trade versus your baseline, and raise an alert when the drop
threshold, flow threshold, and speed threshold are all hit.
) : (
Choose a market on the left.
)}
Implementation notes
1. Discovery
Gamma API for active markets, categories, slugs, event metadata, and token IDs.
2. Live feed
Public Polymarket market WebSocket for orderbook, price changes, and trade executions.
3. Drop logic
Alert on rapid midpoint or last-trade deterioration, repeated sweeps, widening spread, and clustered volume.
4. Whale layer
Optional enrichment from trades and activity endpoints to surface wallets, pseudonyms, and repeated large buyers or sellers.
);
}