feat(market): add selectable chart ranges (24h/7d/30d/1y/all) with range-aware API caching and downsampling
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const MARKET_CHART_RANGES = ["24h", "7d", "30d", "1y", "all"] as const;
|
||||
export type MarketChartRange = (typeof MARKET_CHART_RANGES)[number];
|
||||
|
||||
export interface CryptoMarketResponse {
|
||||
code: string;
|
||||
name: string;
|
||||
@@ -7,7 +10,8 @@ export interface CryptoMarketResponse {
|
||||
change24hPct: number | null;
|
||||
marketCapUsd: number | null;
|
||||
volume24hUsd: number | null;
|
||||
priceHistory24h: Array<{
|
||||
priceHistoryRange: MarketChartRange;
|
||||
priceHistory: Array<{
|
||||
timestamp: string;
|
||||
priceUsd: number;
|
||||
}>;
|
||||
@@ -15,26 +19,38 @@ export interface CryptoMarketResponse {
|
||||
source: string;
|
||||
}
|
||||
|
||||
const marketResponseSchema = z.object({
|
||||
code: z.string(),
|
||||
name: z.string(),
|
||||
const pointSchema = z.object({
|
||||
timestamp: z.string(),
|
||||
priceUsd: z.number().positive(),
|
||||
change24hPct: z.number().nullable(),
|
||||
marketCapUsd: z.number().nullable(),
|
||||
volume24hUsd: z.number().nullable(),
|
||||
priceHistory24h: z
|
||||
.array(
|
||||
z.object({
|
||||
timestamp: z.string(),
|
||||
priceUsd: z.number().positive(),
|
||||
}),
|
||||
)
|
||||
.optional()
|
||||
.default([]),
|
||||
updatedAt: z.string(),
|
||||
source: z.string(),
|
||||
});
|
||||
|
||||
const marketResponseSchema = z
|
||||
.object({
|
||||
code: z.string(),
|
||||
name: z.string(),
|
||||
priceUsd: z.number().positive(),
|
||||
change24hPct: z.number().nullable(),
|
||||
marketCapUsd: z.number().nullable(),
|
||||
volume24hUsd: z.number().nullable(),
|
||||
priceHistoryRange: z.enum(MARKET_CHART_RANGES),
|
||||
priceHistory: z.array(pointSchema).optional(),
|
||||
priceHistory24h: z.array(pointSchema).optional(),
|
||||
updatedAt: z.string(),
|
||||
source: z.string(),
|
||||
})
|
||||
.transform((value) => ({
|
||||
code: value.code,
|
||||
name: value.name,
|
||||
priceUsd: value.priceUsd,
|
||||
change24hPct: value.change24hPct,
|
||||
marketCapUsd: value.marketCapUsd,
|
||||
volume24hUsd: value.volume24hUsd,
|
||||
priceHistoryRange: value.priceHistoryRange,
|
||||
priceHistory: value.priceHistory ?? value.priceHistory24h ?? [],
|
||||
updatedAt: value.updatedAt,
|
||||
source: value.source,
|
||||
}));
|
||||
|
||||
export function parseCryptoMarketResponse(
|
||||
payload: unknown,
|
||||
): CryptoMarketResponse {
|
||||
|
||||
Reference in New Issue
Block a user