2026-02-06 17:50:35 +09:00
|
|
|
|
/**
|
|
|
|
|
|
* @file lib/kis/config.ts
|
|
|
|
|
|
* @description KIS 거래 환경(real/mock) 설정과 키/도메인 로딩
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
export type KisTradingEnv = "real" | "mock";
|
|
|
|
|
|
|
|
|
|
|
|
export interface KisCredentialInput {
|
|
|
|
|
|
tradingEnv?: KisTradingEnv;
|
|
|
|
|
|
appKey?: string;
|
|
|
|
|
|
appSecret?: string;
|
|
|
|
|
|
baseUrl?: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface KisConfig {
|
|
|
|
|
|
tradingEnv: KisTradingEnv;
|
|
|
|
|
|
appKey: string;
|
|
|
|
|
|
appSecret: string;
|
|
|
|
|
|
baseUrl: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const DEFAULT_KIS_REAL_BASE_URL = "https://openapi.koreainvestment.com:9443";
|
|
|
|
|
|
const DEFAULT_KIS_MOCK_BASE_URL = "https://openapivts.koreainvestment.com:29443";
|
|
|
|
|
|
const DEFAULT_KIS_REAL_WS_URL = "ws://ops.koreainvestment.com:21000";
|
|
|
|
|
|
const DEFAULT_KIS_MOCK_WS_URL = "ws://ops.koreainvestment.com:31000";
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 거래 환경 문자열을 정규화합니다.
|
|
|
|
|
|
* @param value 환경값
|
|
|
|
|
|
* @returns real | mock
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function normalizeTradingEnv(value?: string): KisTradingEnv {
|
|
|
|
|
|
return (value ?? "mock").toLowerCase() === "real" ? "real" : "mock";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* KIS 웹소켓 URL을 반환합니다.
|
|
|
|
|
|
* @param tradingEnvInput 거래 모드(real/mock)
|
|
|
|
|
|
* @returns websocket base url
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function getKisWebSocketUrl(tradingEnvInput?: KisTradingEnv) {
|
|
|
|
|
|
const tradingEnv = normalizeTradingEnv(tradingEnvInput);
|
|
|
|
|
|
|
|
|
|
|
|
if (tradingEnv === "real") {
|
2026-02-13 15:44:41 +09:00
|
|
|
|
return DEFAULT_KIS_REAL_WS_URL;
|
2026-02-06 17:50:35 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-13 15:44:41 +09:00
|
|
|
|
return DEFAULT_KIS_MOCK_WS_URL;
|
2026-02-06 17:50:35 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 설정 준비 여부를 확인합니다.
|
|
|
|
|
|
* @param input 외부(사용자 입력) 키가 있으면 우선 사용
|
|
|
|
|
|
* @returns 사용 가능 여부
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function hasKisConfig(input?: KisCredentialInput) {
|
2026-02-13 15:44:41 +09:00
|
|
|
|
return Boolean(input?.appKey?.trim() && input?.appSecret?.trim());
|
2026-02-06 17:50:35 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* KIS 호출에 필요한 설정을 반환합니다.
|
|
|
|
|
|
* @param input 사용자 입력 키(선택)
|
|
|
|
|
|
* @returns tradingEnv/appKey/appSecret/baseUrl
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function getKisConfig(input?: KisCredentialInput): KisConfig {
|
2026-02-13 15:44:41 +09:00
|
|
|
|
if (input?.appKey?.trim() && input?.appSecret?.trim()) {
|
2026-02-06 17:50:35 +09:00
|
|
|
|
const tradingEnv = normalizeTradingEnv(input.tradingEnv);
|
|
|
|
|
|
const baseUrl =
|
|
|
|
|
|
input.baseUrl ??
|
|
|
|
|
|
(tradingEnv === "real" ? DEFAULT_KIS_REAL_BASE_URL : DEFAULT_KIS_MOCK_BASE_URL);
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
tradingEnv,
|
2026-02-13 15:44:41 +09:00
|
|
|
|
appKey: input.appKey.trim(),
|
|
|
|
|
|
appSecret: input.appSecret.trim(),
|
2026-02-06 17:50:35 +09:00
|
|
|
|
baseUrl,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-13 15:44:41 +09:00
|
|
|
|
throw new Error(
|
|
|
|
|
|
"KIS API 키가 없습니다. 설정 화면에서 앱 키와 앱 시크릿을 먼저 입력해 주세요.",
|
|
|
|
|
|
);
|
2026-02-06 17:50:35 +09:00
|
|
|
|
}
|