import type { KisRuntimeCredentials } from "@/features/dashboard/store/use-kis-runtime-store"; import type { DashboardChartTimeframe, DashboardStockCashOrderRequest, DashboardStockCashOrderResponse, DashboardStockChartResponse, DashboardStockOrderBookResponse, DashboardStockOverviewResponse, DashboardStockSearchResponse, } from "@/features/dashboard/types/dashboard.types"; /** * 종목 검색 API 호출 * @param keyword 검색어 */ export async function fetchStockSearch( keyword: string, signal?: AbortSignal, ): Promise { const response = await fetch( `/api/kis/domestic/search?q=${encodeURIComponent(keyword)}`, { cache: "no-store", signal, }, ); const payload = (await response.json()) as | DashboardStockSearchResponse | { error?: string }; if (!response.ok) { throw new Error( "error" in payload ? payload.error : "종목 검색 중 오류가 발생했습니다.", ); } return payload as DashboardStockSearchResponse; } /** * 종목 상세 개요 조회 API 호출 * @param symbol 종목코드 * @param credentials KIS 인증 정보 */ export async function fetchStockOverview( symbol: string, credentials: KisRuntimeCredentials, ): Promise { const response = await fetch( `/api/kis/domestic/overview?symbol=${encodeURIComponent(symbol)}`, { method: "GET", headers: { "x-kis-app-key": credentials.appKey, "x-kis-app-secret": credentials.appSecret, "x-kis-trading-env": credentials.tradingEnv, }, cache: "no-store", }, ); const payload = (await response.json()) as | DashboardStockOverviewResponse | { error?: string }; if (!response.ok) { throw new Error( "error" in payload ? payload.error : "종목 조회 중 오류가 발생했습니다.", ); } return payload as DashboardStockOverviewResponse; } /** * 종목 호가 조회 API 호출 * @param symbol 종목코드 * @param credentials KIS 인증 정보 */ export async function fetchStockOrderBook( symbol: string, credentials: KisRuntimeCredentials, signal?: AbortSignal, ): Promise { const response = await fetch( `/api/kis/domestic/orderbook?symbol=${encodeURIComponent(symbol)}`, { method: "GET", headers: { "x-kis-app-key": credentials.appKey, "x-kis-app-secret": credentials.appSecret, "x-kis-trading-env": credentials.tradingEnv, }, cache: "no-store", // 호가는 실시간성이 중요하므로 항상 최신 데이터 조회 signal, }, ); const payload = (await response.json()) as | DashboardStockOrderBookResponse | { error?: string }; if (!response.ok) { throw new Error( "error" in payload ? payload.error : "호가 조회 중 오류가 발생했습니다.", ); } return payload as DashboardStockOrderBookResponse; } /** * 종목 차트(분봉/일봉/주봉) 조회 API 호출 */ export async function fetchStockChart( symbol: string, timeframe: DashboardChartTimeframe, credentials: KisRuntimeCredentials, cursor?: string, ): Promise { const query = new URLSearchParams({ symbol, timeframe, }); if (cursor) query.set("cursor", cursor); const response = await fetch(`/api/kis/domestic/chart?${query.toString()}`, { method: "GET", headers: { "x-kis-app-key": credentials.appKey, "x-kis-app-secret": credentials.appSecret, "x-kis-trading-env": credentials.tradingEnv, }, cache: "no-store", }); const payload = (await response.json()) as | DashboardStockChartResponse | { error?: string }; if (!response.ok) { throw new Error( "error" in payload ? payload.error : "차트 조회 중 오류가 발생했습니다.", ); } return payload as DashboardStockChartResponse; } /** * 주식 현금 주문 API 호출 * @param request 주문 요청 데이터 * @param credentials KIS 인증 정보 */ export async function fetchOrderCash( request: DashboardStockCashOrderRequest, credentials: KisRuntimeCredentials, ): Promise { const response = await fetch("/api/kis/domestic/order-cash", { method: "POST", headers: { "content-type": "application/json", "x-kis-app-key": credentials.appKey, "x-kis-app-secret": credentials.appSecret, "x-kis-trading-env": credentials.tradingEnv, }, body: JSON.stringify(request), cache: "no-store", }); const payload = (await response.json()) as DashboardStockCashOrderResponse; if (!response.ok) { throw new Error(payload.message || "주문 전송 중 오류가 발생했습니다."); } return payload; }