대시보드 중간 커밋
This commit is contained in:
82
features/dashboard/apis/kis-auth.api.ts
Normal file
82
features/dashboard/apis/kis-auth.api.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import type { KisRuntimeCredentials } from "@/features/dashboard/store/use-kis-runtime-store";
|
||||
import type {
|
||||
DashboardKisRevokeResponse,
|
||||
DashboardKisValidateResponse,
|
||||
DashboardKisWsApprovalResponse,
|
||||
} from "@/features/dashboard/types/dashboard.types";
|
||||
|
||||
/**
|
||||
* KIS API 키 검증 요청
|
||||
* @param credentials 검증할 키 정보
|
||||
*/
|
||||
export async function validateKisCredentials(
|
||||
credentials: KisRuntimeCredentials,
|
||||
): Promise<DashboardKisValidateResponse> {
|
||||
const response = await fetch("/api/kis/validate", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(credentials),
|
||||
cache: "no-store",
|
||||
});
|
||||
|
||||
const payload = (await response.json()) as DashboardKisValidateResponse;
|
||||
|
||||
if (!response.ok || !payload.ok) {
|
||||
throw new Error(payload.message || "API 키 검증에 실패했습니다.");
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* KIS 접근토큰 폐기 요청
|
||||
* @param credentials 폐기할 키 정보
|
||||
*/
|
||||
export async function revokeKisCredentials(
|
||||
credentials: KisRuntimeCredentials,
|
||||
): Promise<DashboardKisRevokeResponse> {
|
||||
const response = await fetch("/api/kis/revoke", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(credentials),
|
||||
cache: "no-store",
|
||||
});
|
||||
|
||||
const payload = (await response.json()) as DashboardKisRevokeResponse;
|
||||
|
||||
if (!response.ok || !payload.ok) {
|
||||
throw new Error(payload.message || "API 키 접근 폐기에 실패했습니다.");
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* KIS 실시간 웹소켓 승인키 발급 요청
|
||||
* @param credentials 인증 정보
|
||||
*/
|
||||
export async function fetchKisWebSocketApproval(
|
||||
credentials: KisRuntimeCredentials,
|
||||
): Promise<DashboardKisWsApprovalResponse> {
|
||||
const response = await fetch("/api/kis/ws/approval", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(credentials),
|
||||
cache: "no-store",
|
||||
});
|
||||
|
||||
const payload = (await response.json()) as DashboardKisWsApprovalResponse;
|
||||
if (!response.ok || !payload.ok || !payload.approvalKey || !payload.wsUrl) {
|
||||
throw new Error(
|
||||
payload.message || "KIS 실시간 웹소켓 승인키 발급에 실패했습니다.",
|
||||
);
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
179
features/dashboard/apis/kis-stock.api.ts
Normal file
179
features/dashboard/apis/kis-stock.api.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
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<DashboardStockSearchResponse> {
|
||||
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<DashboardStockOverviewResponse> {
|
||||
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<DashboardStockOrderBookResponse> {
|
||||
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<DashboardStockChartResponse> {
|
||||
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<DashboardStockCashOrderResponse> {
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user