chore: initial import
This commit is contained in:
76
apps/visualizer/src/lib/api.ts
Normal file
76
apps/visualizer/src/lib/api.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
export type Candle = {
|
||||
time: number; // unix seconds
|
||||
open: number;
|
||||
high: number;
|
||||
low: number;
|
||||
close: number;
|
||||
volume?: number;
|
||||
oracle?: number | null;
|
||||
};
|
||||
|
||||
export type SeriesPoint = {
|
||||
time: number; // unix seconds
|
||||
value: number | null;
|
||||
};
|
||||
|
||||
export type ChartIndicators = {
|
||||
oracle?: SeriesPoint[];
|
||||
sma20?: SeriesPoint[];
|
||||
ema20?: SeriesPoint[];
|
||||
bb20?: { upper: SeriesPoint[]; lower: SeriesPoint[]; mid: SeriesPoint[] };
|
||||
rsi14?: SeriesPoint[];
|
||||
macd?: { macd: SeriesPoint[]; signal: SeriesPoint[] };
|
||||
};
|
||||
|
||||
export type ChartResponse = {
|
||||
ok: boolean;
|
||||
symbol?: string;
|
||||
source?: string | null;
|
||||
tf?: string;
|
||||
bucketSeconds?: number;
|
||||
candles?: Candle[];
|
||||
indicators?: ChartIndicators;
|
||||
error?: string;
|
||||
};
|
||||
|
||||
function getApiBaseUrl(): string {
|
||||
const v = (import.meta as any).env?.VITE_API_URL;
|
||||
if (v) return String(v);
|
||||
return '/api';
|
||||
}
|
||||
|
||||
export async function fetchChart(params: {
|
||||
symbol: string;
|
||||
source?: string;
|
||||
tf: string;
|
||||
limit: number;
|
||||
}): Promise<{ candles: Candle[]; indicators: ChartIndicators; meta: { tf: string; bucketSeconds: number } }> {
|
||||
const base = getApiBaseUrl();
|
||||
const u = new URL(base, window.location.origin);
|
||||
u.pathname = u.pathname && u.pathname !== '/' ? u.pathname.replace(/\/$/, '') + '/v1/chart' : '/v1/chart';
|
||||
u.searchParams.set('symbol', params.symbol);
|
||||
u.searchParams.set('tf', params.tf);
|
||||
u.searchParams.set('limit', String(params.limit));
|
||||
if (params.source && params.source.trim()) u.searchParams.set('source', params.source.trim());
|
||||
|
||||
const res = await fetch(u.toString());
|
||||
const text = await res.text();
|
||||
if (!res.ok) throw new Error(`API HTTP ${res.status}: ${text}`);
|
||||
const json = JSON.parse(text) as ChartResponse;
|
||||
if (!json.ok) throw new Error(json.error || 'API: error');
|
||||
return {
|
||||
candles: (json.candles || []).map((c) => ({
|
||||
...c,
|
||||
time: Number(c.time),
|
||||
open: Number(c.open),
|
||||
high: Number(c.high),
|
||||
low: Number(c.low),
|
||||
close: Number(c.close),
|
||||
volume: c.volume == null ? undefined : Number(c.volume),
|
||||
oracle: c.oracle == null ? null : Number(c.oracle),
|
||||
})),
|
||||
indicators: json.indicators || {},
|
||||
meta: { tf: String(json.tf || params.tf), bucketSeconds: Number(json.bucketSeconds || 0) },
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user