import React from "react"; import { motion } from "framer-motion"; import { getStats, type Stats } from "../api"; const REFRESH_MS = 45_000; export interface StatsSectionProps { /** Optional refetch trigger: when this value changes, stats are refetched. */ refetchTrigger?: number; } function AnimatedNumber({ value }: { value: number }) { return ( {value.toLocaleString()} ); } export function StatsSection({ refetchTrigger }: StatsSectionProps) { const [stats, setStats] = React.useState(null); const [loading, setLoading] = React.useState(true); const [refreshing, setRefreshing] = React.useState(false); const load = React.useCallback(async (userRefresh = false) => { if (userRefresh) setRefreshing(true); try { const s = await getStats(); setStats(s); } catch { setStats(null); } finally { setLoading(false); if (userRefresh) setRefreshing(false); } }, []); React.useEffect(() => { load(); const t = setInterval(load, REFRESH_MS); return () => clearInterval(t); }, [load, refetchTrigger]); if (loading && !stats) { return (
); } if (!stats) return

Stats unavailable

; const n = (v: number | undefined | null) => Number(v ?? 0); const ts = (v: number | undefined | null) => new Date(Number(v ?? 0) * 1000).toLocaleString(); const dailyBudget = Number(stats.dailyBudgetSats) || 1; const budgetUsed = n(stats.spentTodaySats); const budgetPct = Math.min(100, (budgetUsed / dailyBudget) * 100); return (

Faucet stats

sats

Pool balance

Daily budget: / sats
Total paid sats
Total claims
Claims (24h)
{stats.recentPayouts?.length > 0 && ( <>

Recent payouts

    {stats.recentPayouts.slice(0, 10).map((p, i) => (
  • {p.pubkey_prefix ?? "…"} — {n(p.payout_sats).toLocaleString()} sats — {ts(p.claimed_at)}
  • ))}
)}
); }