import { ApiSettings, MarketType, OrderType, StockItem } from '../types'; import { API_BASE_URL, getHeaders } from './config'; /** * Korea Investment & Securities (KIS) Open API Service * Now connected to Real Backend */ export class KisService { private settings: ApiSettings; constructor(settings: ApiSettings) { this.settings = settings; } async issueAccessToken() { // Backend manages token automatically. return "backend-managed-token"; } async inquirePrice(code: string): Promise { // Default to Domestic for now, or infer from code length const market = code.length === 6 ? "Domestic" : "Overseas"; try { const res = await fetch(`${API_BASE_URL}/kis/price?market=${market}&code=${code}`); if (!res.ok) return 0; const data = await res.json(); return parseFloat(data.price) || 0; } catch (e) { return 0; } } /** * Fetch Market Data */ async fetchMasterStocks(market: MarketType): Promise { try { // Use Rankings as the default "List" const marketParam = market === MarketType.DOMESTIC ? "Domestic" : "Overseas"; const res = await fetch(`${API_BASE_URL}/discovery/rankings?limit=50`); if (!res.ok) return []; const data = await res.json(); // Transform logic if needed. Ranking API returns StockItem which matches frontend type mostly. return data.map((item: any) => ({ code: item.code, name: item.name, price: item.price, change: item.change, changePercent: item.changePercent, market: market, volume: 0, // Rankings might not return volume yet, or it does if enabled aiScoreBuy: 50, // Placeholder as backend doesn't have AI score in StockItem yet aiScoreSell: 50, themes: [] })); } catch (e) { return []; } } async orderCash(code: string, type: OrderType, quantity: number, price: number = 0) { return this._placeOrder("Domestic", code, type, quantity, price); } async orderOverseas(code: string, type: OrderType, quantity: number, price: number) { return this._placeOrder("Overseas", code, type, quantity, price); } private async _placeOrder(market: string, code: string, type: OrderType, quantity: number, price: number) { const payload = { market: market, side: type === OrderType.BUY ? "buy" : "sell", code: code, quantity: quantity, price: price }; const res = await fetch(`${API_BASE_URL}/kis/order`, { method: 'POST', headers: getHeaders(), body: JSON.stringify(payload) }); if (!res.ok) { const err = await res.json(); throw new Error(err.detail || "Order Failed"); } return await res.json(); } async inquireBalance() { // Default Domestic const res = await fetch(`${API_BASE_URL}/kis/balance?market=Domestic`); if (!res.ok) return { output1: [], output2: {} }; return await res.json(); } async inquireBalanceOverseas() { const res = await fetch(`${API_BASE_URL}/kis/balance?market=Overseas`); if (!res.ok) return { output1: [], output2: {} }; return await res.json(); } }