Files
boursecu_landing/src/api/zaarboxPriceHistory.ts
T

74 lines
2.2 KiB
TypeScript

/** تاریخچه قیمت عمومی بورس کالا (بدون توکن) — کاتد مس */
export const ZAANBOX_COPPER_CTHD_ID = '8c19e06a-446e-3d56-9cc0-750f7c6cd767'
export const ZAANBOX_HISTORY_URL = `https://price.zaarbox.ir/api/history/${ZAANBOX_COPPER_CTHD_ID}`
export type ZaanboxHistoryPoint = {
time: string
price: number
}
export type ZaanboxHistoryResponse = {
history?: ZaanboxHistoryPoint[]
data?: { history?: ZaanboxHistoryPoint[] }
}
export type LandingHistoryRange = 'DAILY' | 'WEEKLY' | 'MONTHLY'
/** نقطهٔ خام تاریخچه — قدیم → جدید */
export type LandingHistorySample = {
timeMs: number
price: number
}
const RANGE_MS: Record<LandingHistoryRange, number> = {
DAILY: 1 * 24 * 60 * 60 * 1000,
WEEKLY: 7 * 24 * 60 * 60 * 1000,
MONTHLY: 30 * 24 * 60 * 60 * 1000,
}
const HISTORY_LIMIT = 1_000_000_000
function resolveHistoryRows(payload: unknown): ZaanboxHistoryPoint[] {
if (!payload || typeof payload !== 'object') return []
const body = payload as ZaanboxHistoryResponse
if (Array.isArray(body.history)) return body.history
if (Array.isArray(body.data?.history)) return body.data!.history!
return []
}
/** نقاط خام بازه، مرتب از قدیم → جدید */
export async function fetchZaanboxPriceHistory(
range: LandingHistoryRange,
now = new Date(),
): Promise<LandingHistorySample[]> {
const end = now
const start = new Date(end.getTime() - RANGE_MS[range])
const url = new URL(ZAANBOX_HISTORY_URL)
url.searchParams.set('start', start.toISOString())
url.searchParams.set('end', end.toISOString())
url.searchParams.set('limit', String(HISTORY_LIMIT))
const response = await fetch(url.toString(), {
method: 'GET',
headers: { Accept: 'application/json' },
})
if (!response.ok) {
throw new Error(`Zaanbox history HTTP ${response.status}`)
}
const payload = (await response.json()) as unknown
const rows = resolveHistoryRows(payload)
return rows
.map((row) => {
const timeMs = Date.parse(String(row.time ?? ''))
const price = Number(row.price)
return { timeMs, price }
})
.filter((point) => Number.isFinite(point.timeMs) && Number.isFinite(point.price) && point.price > 0)
.sort((a, b) => a.timeMs - b.timeMs)
}