UNPKG

@debate300/bithumb-pro

Version:

A real-time cryptocurrency price tracker for Bithumb (Pro).

117 lines (116 loc) 4.73 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Upbit = void 0; const ws_1 = __importDefault(require("ws")); const chalk_1 = __importDefault(require("chalk")); const axios_1 = __importDefault(require("axios")); const uuid_1 = require("uuid"); const common_1 = require("../common"); class Upbit extends common_1.Exchange { constructor(redrawCallback) { super(redrawCallback); this.name = "Upbit"; this.ws = null; this.isActive = false; this.wsUri = "wss://api.upbit.com/websocket/v1"; this.marketInfo = new Map(); this.iconMap = new Map(); } async fetchMarketInfo() { try { const response = await axios_1.default.get("https://api.upbit.com/v1/market/all"); if (response.status === 200) { const markets = response.data; markets.forEach((market) => { if (market.market.startsWith("KRW-")) { this.marketInfo.set(market.market, market); } }); } } catch (error) { console.error(chalk_1.default.red("Upbit 마켓 정보 로딩 오류:"), error); } } async connect(appConfig) { await this.fetchMarketInfo(); const upbitSymbols = appConfig.coins.map((coin) => { const symbol = `${coin.unit_currency}-${coin.symbol}`; this.iconMap.set(symbol, coin.icon); return symbol; }); if (this.ws) this.disconnect(); this.ws = new ws_1.default(this.wsUri); this.ws.on("open", () => { console.log(chalk_1.default.green("Upbit WebSocket에 연결되었습니다.")); const subscribeMsg = JSON.stringify([ { ticket: (0, uuid_1.v4)() }, { type: "ticker", codes: upbitSymbols }, ]); this.ws?.send(subscribeMsg); }); this.ws.on("message", (data) => { try { const message = JSON.parse(data.toString("utf8")); if (message.type === "ticker") { const coinConfig = appConfig.coins.find((c) => `${c.unit_currency}-${c.symbol}` === message.code); const standardizedData = this.standardize(message, coinConfig); this.realTimeData.set(standardizedData.symbol, standardizedData); this.redrawCallback(); } } catch (error) { console.error(chalk_1.default.red("Upbit 메시지 처리 오류:"), error); } }); this.ws.on("error", (error) => { console.error(chalk_1.default.red("Upbit WebSocket 오류 발생:"), error); }); this.ws.on("close", () => { console.log(chalk_1.default.yellow("Upbit WebSocket 연결이 종료되었습니다. 5초 후 재연결 시도...")); setTimeout(() => this.connect(appConfig), 5000); }); } disconnect() { this.isActive = false; if (this.ws) { this.ws.close(); this.ws = null; this.realTimeData.clear(); } } standardize(data, coinConfig) { const symbol = data.code.replace("KRW-", "") + "_KRW"; const koreanName = this.marketInfo.get(data.code)?.korean_name || symbol; let priceColor = chalk_1.default.white; if (data.change === "RISE") priceColor = chalk_1.default.redBright; else if (data.change === "FALL") priceColor = chalk_1.default.cyanBright; let profitLossRate; if (coinConfig && coinConfig.averagePurchasePrice > 0) { const avgPrice = coinConfig.averagePurchasePrice; profitLossRate = ((data.trade_price - avgPrice) / avgPrice) * 100; } return { symbol: symbol, koreanName: koreanName, icon: this.iconMap.get(data.code) || " ", currentPrice: data.trade_price, priceChangeRate: data.signed_change_rate * 100, priceChangeAmount: data.signed_change_price, highPrice: data.high_price, lowPrice: data.low_price, prevClosePrice: data.prev_closing_price, averagePurchasePrice: coinConfig?.averagePurchasePrice, profitLossRate: profitLossRate, priceColor: priceColor, volumePower: undefined, // Upbit ticker does not provide volume power }; } } exports.Upbit = Upbit;