chore: initial import

This commit is contained in:
u1
2026-01-06 12:33:47 +01:00
commit ed37565e25
38 changed files with 5707 additions and 0 deletions

View 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) },
};
}