UNPKG

ccxws

Version:

Websocket client for 37 cryptocurrency exchanges

243 lines 8.9 kB
"use strict"; /* eslint-disable @typescript-eslint/member-ordering */ /* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ Object.defineProperty(exports, "__esModule", { value: true }); exports.UpbitClient = void 0; const BasicClient_1 = require("../BasicClient"); const Level2Point_1 = require("../Level2Point"); const Level2Snapshots_1 = require("../Level2Snapshots"); const NotImplementedFn_1 = require("../NotImplementedFn"); const Ticker_1 = require("../Ticker"); const Trade_1 = require("../Trade"); class UpbitClient extends BasicClient_1.BasicClient { constructor({ wssPath = "wss://api.upbit.com/websocket/v1", watcherMs } = {}) { super(wssPath, "Upbit", undefined, watcherMs); this._sendSubCandles = NotImplementedFn_1.NotImplementedFn; this._sendUnsubCandles = NotImplementedFn_1.NotImplementedFn; this._sendSubLevel2Updates = NotImplementedFn_1.NotImplementedFn; this._sendUnsubLevel2Updates = NotImplementedFn_1.NotImplementedFn; this._sendSubLevel3Snapshots = NotImplementedFn_1.NotImplementedFn; this._sendUnsubLevel3Snapshots = NotImplementedFn_1.NotImplementedFn; this._sendSubLevel3Updates = NotImplementedFn_1.NotImplementedFn; this._sendUnsubLevel3Updates = NotImplementedFn_1.NotImplementedFn; this.hasTickers = true; this.hasTrades = true; this.hasLevel2Snapshots = true; this.debouceTimeoutHandles = new Map(); this.debounceWait = 200; } _sendSubTicker() { this._debounce("sub-ticker", () => { if (!this._wss) return; const codes = Array.from(this._tickerSubs.keys()); this._wss.send(JSON.stringify([{ ticket: "tickers" }, { type: "ticker", codes: codes }])); }); } _sendUnsubTicker() { this._debounce("unsub-ticker", () => { if (!this._wss) return; const codes = Array.from(this._tickerSubs.keys()); this._wss.send(JSON.stringify([{ ticket: "tickers" }, { type: "ticker", codes: codes }])); }); } _sendSubTrades() { this._debounce("sub-trades", () => { if (!this._wss) return; const codes = Array.from(this._tradeSubs.keys()); this._wss.send(JSON.stringify([{ ticket: "trades" }, { type: "trade", codes: codes }])); }); } _sendUnsubTrades() { this._debounce("unsub-trades", () => { if (!this._wss) return; const codes = Array.from(this._tradeSubs.keys()); this._wss.send(JSON.stringify([{ ticket: "trades" }, { type: "trade", codes: codes }])); }); } _sendSubLevel2Snapshots() { this._debounce("sub-l2snapshots", () => { if (!this._wss) return; const codes = Array.from(this._level2SnapshotSubs.keys()); this._wss.send(JSON.stringify([{ ticket: "quotation" }, { type: "orderbook", codes: codes }])); }); } _sendUnsubLevel2Snapshots() { this._debounce("unsub-l2snapshots", () => { if (!this._wss) return; const codes = Array.from(this._level2SnapshotSubs.keys()); this._wss.send(JSON.stringify([{ ticket: "quotation" }, { type: "orderbook", codes: codes }])); }); } _debounce(type, fn) { clearTimeout(this.debouceTimeoutHandles.get(type)); this.debouceTimeoutHandles.set(type, setTimeout(fn, this.debounceWait)); } _onMessage(raw) { const rawStr = raw.toString("utf8"); const msgs = JSON.parse(rawStr.replace(/:(\d+\.{0,1}\d+)(,|\})/g, ':"$1"$2')); this._processsMessage(msgs); } _processsMessage(msg) { // console.log(msg); // trades if (msg.type === "trade") { const market = this._tradeSubs.get(msg.code); if (!market) return; const trade = this._constructTradesFromMessage(msg, market); this.emit("trade", trade, market); return; } // tickers if (msg.type === "ticker") { const market = this._tickerSubs.get(msg.code); if (!market) return; const ticker = this._constructTicker(msg, market); this.emit("ticker", ticker, market); return; } // l2 updates if (msg.type === "orderbook") { const market = this._level2SnapshotSubs.get(msg.code); if (!market) return; const snapshot = this._constructLevel2Snapshot(msg, market); this.emit("l2snapshot", snapshot, market); return; } } _constructTicker(msg, market) { /* { type: 'ticker', code: 'KRW-BTC', opening_price: '3980000.00000000', high_price: '4017000.00000000', low_price: '3967000.00000000', trade_price: '3982000.0', prev_closing_price: '3981000.00000000', acc_trade_price: '10534309614.237530000', change: 'RISE', change_price: '1000.00000000', signed_change_price: '1000.00000000', change_rate: '0.0002511932', signed_change_rate: '0.0002511932', ask_bid: 'ASK', trade_volume: '0.01562134', acc_trade_volume: '2641.03667958', trade_date: '20190213', trade_time: '132020', trade_timestamp: '1550064020000', acc_ask_volume: '1232.55205784', acc_bid_volume: '1408.48462174', highest_52_week_price: '14149000.00000000', highest_52_week_date: '2018-02-20', lowest_52_week_price: '3562000.00000000', lowest_52_week_date: '2018-12-15', trade_status: null, market_state: 'ACTIVE', market_state_for_ios: null, is_trading_suspended: false, delisting_date: null, market_warning: 'NONE', timestamp: '1550064020393', acc_trade_price_24h: null, acc_trade_volume_24h: null, stream_type: 'SNAPSHOT' } */ const { opening_price, trade_price, acc_trade_volume, change_rate, change_price, low_price, high_price, timestamp, } = msg; return new Ticker_1.Ticker({ exchange: this.name, base: market.base, quote: market.quote, timestamp: parseInt(timestamp), last: trade_price, open: opening_price, high: high_price, low: low_price, volume: acc_trade_volume, quoteVolume: (acc_trade_volume * trade_price).toFixed(8), change: change_price, changePercent: change_rate, }); } _constructTradesFromMessage(datum, market) { /* { "type":"trade", "code":"KRW-BTC", "timestamp":1549443263262, "trade_date":"2019-02-06", "trade_time":"08:54:23", "trade_timestamp":1549443263000, "trade_price":3794000.0, "trade_volume":0.00833522, "ask_bid":"BID", "prev_closing_price":3835000.00000000, "change":"FALL","change_price":41000.00000000, "sequential_id":1549443263000001, "stream_type":"REALTIME"} */ const { trade_timestamp, trade_price, trade_volume, ask_bid, sequential_id } = datum; const side = ask_bid === "BID" ? "buy" : "sell"; return new Trade_1.Trade({ exchange: this.name, base: market.base, quote: market.quote, tradeId: sequential_id, side: side, unix: parseInt(trade_timestamp), price: trade_price, amount: trade_volume, }); } _constructLevel2Snapshot(msg, market) { /* { type: 'orderbook', code: 'KRW-BTT', timestamp: 1549465903782, total_ask_size: 1550925205.4196181, total_bid_size: 2900599205.9702206, orderbook_units: [ { ask_price: 1.04, bid_price: 1.03, ask_size: 185206052.57158336, bid_size: 354443748.7514278 }, ... { ask_price: 1.13, bid_price: 0.94, ask_size: 198013382.3803366, bid_size: 267304509.61145836 } ], stream_type: 'SNAPSHOT' } */ const asks = msg.orderbook_units.map(p => new Level2Point_1.Level2Point(s(p.ask_price), s(p.ask_size))); const bids = msg.orderbook_units.map(p => new Level2Point_1.Level2Point(s(p.bid_price), s(p.bid_size))); return new Level2Snapshots_1.Level2Snapshot({ exchange: this.name, base: market.base, quote: market.quote, timestampMs: parseInt(msg.timestamp), asks, bids, }); } } exports.UpbitClient = UpbitClient; function s(v) { if (typeof v === "number") { return v.toFixed(8); } else { return v; } } //# sourceMappingURL=UpbitClient.js.map