chore: initial trade-visualizer import
This commit is contained in:
52
src/features/ticks/useTicks.ts
Normal file
52
src/features/ticks/useTicks.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { DriftTick, fetchLatestTicks } from '../../lib/hasura';
|
||||
import { useInterval } from '../../app/hooks/useInterval';
|
||||
|
||||
type Params = {
|
||||
symbol: string;
|
||||
source?: string;
|
||||
limit: number;
|
||||
pollMs: number;
|
||||
};
|
||||
|
||||
type Result = {
|
||||
ticks: DriftTick[];
|
||||
latest: DriftTick | null;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
refresh: () => Promise<void>;
|
||||
};
|
||||
|
||||
export function useTicks({ symbol, source, limit, pollMs }: Params): Result {
|
||||
const [ticks, setTicks] = useState<DriftTick[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const inFlight = useRef(false);
|
||||
|
||||
const fetchOnce = useCallback(async () => {
|
||||
if (inFlight.current) return;
|
||||
inFlight.current = true;
|
||||
setLoading(true);
|
||||
try {
|
||||
const next = await fetchLatestTicks(symbol, limit, source?.trim() ? source : undefined);
|
||||
setTicks(next);
|
||||
setError(null);
|
||||
} catch (e: any) {
|
||||
setError(String(e?.message || e));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
inFlight.current = false;
|
||||
}
|
||||
}, [symbol, limit, source]);
|
||||
|
||||
useEffect(() => {
|
||||
void fetchOnce();
|
||||
}, [fetchOnce]);
|
||||
|
||||
useInterval(() => void fetchOnce(), pollMs);
|
||||
|
||||
const latest = useMemo(() => (ticks.length ? ticks[ticks.length - 1] : null), [ticks]);
|
||||
|
||||
return { ticks, latest, loading, error, refresh: fetchOnce };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user