← Back
import { useState, useEffect, useCallback } from 'react';

export interface WhaleInsider {
  marketId: string;
  question: string | null;
  slug: string | null;
  address: string;
  outcome: string;              // 'Yes' | 'No' — the side the whale bought
  amountUsd: number;
  avgPrice: number;             // 0..1 volume-weighted entry of the whale
  currentPrice: number | null;  // 0..1 current price of that side
  lastTradeAt: string | null;
  winRate: number | null;       // 0..1 whale's positive-resolution win rate
  closedPositions: number | null;
  pnl7d: number | null;
}

interface Options { hours?: number; minAmount?: number; limit?: number; }

// Fresh BUYs by quality whales ("smart money just entered"). One row per
// (market, whale, side). Backed by /api/signals/whales/insider.
export function useWhaleInsider(options: Options = {}) {
  const { hours = 24, minAmount = 5000, limit = 40 } = options;
  const [rows, setRows] = useState<WhaleInsider[]>([]);
  const [loading, setLoading] = useState(true);

  const fetchData = useCallback(async () => {
    setLoading(true);
    try {
      const params = new URLSearchParams({ hours: String(hours), min_amount: String(minAmount), limit: String(limit) });
      const res = await fetch(`/api/signals/whales/insider?${params}`);
      const d = await res.json();
      if (d.success) setRows(d.data ?? []);
    } catch { /* ignore */ }
    finally { setLoading(false); }
  }, [hours, minAmount, limit]);

  useEffect(() => {
    const t = setTimeout(fetchData, 0);
    const interval = setInterval(fetchData, 5 * 60_000);
    return () => { clearTimeout(t); clearInterval(interval); };
  }, [fetchData]);

  return { rows, loading, refresh: fetchData };
}

📜 Git History

b9c19bfchore(poli): reconcile local Flow/Insider/manual-trade work with deployed state3 days ago
Show last diff
Loading...