import { useState, useEffect, useCallback } from 'react';
export interface WhaleConsensus {
marketId: string;
question: string | null;
slug: string | null;
whales: number; // distinct whales trading this market
trades: number;
netSide: 'Yes' | 'No';
netFlowUsd: number; // |yes_flow - no_flow|
totalUsd: number; // yes_flow + no_flow
agreement: number; // 0.5 = split, 1.0 = unanimous
avgPrice: number; // 0..1 volume-weighted entry of the dominant side
currentPrice: number | null; // 0..1 current market price of the dominant side
lastTradeAt: string | null; // ISO timestamp of the most recent whale trade
}
interface Options {
days?: number;
minAmount?: number;
limit?: number;
}
export function useWhaleConsensus(options: Options = {}) {
const { days = 7, minAmount = 5000, limit = 40 } = options;
const [rows, setRows] = useState<WhaleConsensus[]>([]);
const [loading, setLoading] = useState(true);
const fetchConsensus = useCallback(async () => {
setLoading(true);
try {
const params = new URLSearchParams({
days: String(days),
min_amount: String(minAmount),
limit: String(limit),
});
const res = await fetch(`/api/signals/whales/consensus?${params}`);
const d = await res.json();
if (d.success) setRows(d.data ?? []);
} catch { /* ignore */ }
finally { setLoading(false); }
}, [days, minAmount, limit]);
useEffect(() => {
const t = setTimeout(fetchConsensus, 0);
const interval = setInterval(fetchConsensus, 5 * 60_000);
return () => { clearTimeout(t); clearInterval(interval); };
}, [fetchConsensus]);
return { rows, loading, refresh: fetchConsensus };
}
π Git History
f5cc0aefeat(poli): Flow consensus chunk 2 β entryβnow delta, freshness, sort, filters4 days ago
6c47fa4chore: local Polikopi project home + Phase 1 redesign artifacts12 days ago
Show last diff
Loading...