UNPKG

@kraken-crypto/ccxt

Version:

A cryptocurrency trading API with more than 100 exchanges in JavaScript / TypeScript / Python / C# / PHP / Go

1,210 lines (1,206 loc) 50.8 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var deepcoin$1 = require('../deepcoin.js'); var errors = require('../base/errors.js'); var Cache = require('../base/ws/Cache.js'); // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- class deepcoin extends deepcoin$1["default"] { describe() { return this.deepExtend(super.describe(), { 'has': { 'ws': true, 'watchTicker': true, 'watchMarkPrice': false, 'watchMarkPrices': false, 'watchTickers': false, 'watchBidsAsks': false, 'watchOrderBook': true, 'watchTrades': true, 'watchTradesForSymbols': false, 'watchOrderBookForSymbols': false, 'watchBalance': false, 'watchLiquidations': false, 'watchLiquidationsForSymbols': false, 'watchMyLiquidations': false, 'watchMyLiquidationsForSymbols': false, 'watchOHLCV': true, 'watchOHLCVForSymbols': false, 'watchOrders': true, 'watchMyTrades': true, 'watchPositions': true, 'watchFundingRate': false, 'watchFundingRates': false, 'createOrderWs': false, 'editOrderWs': false, 'cancelOrderWs': false, 'cancelOrdersWs': false, 'cancelAllOrdersWs': false, 'unWatchTicker': true, 'unWatchTrades': true, 'unWatchOHLCV': true, 'unWatchOrderBook': true, }, 'urls': { 'api': { 'ws': { 'public': { 'spot': 'wss://stream.deepcoin.com/streamlet/trade/public/spot?platform=api', 'swap': 'wss://stream.deepcoin.com/streamlet/trade/public/swap?platform=api', }, 'private': 'wss://stream.deepcoin.com/v1/private', }, }, }, 'options': { 'lastRequestId': undefined, 'listenKey': undefined, 'listenKeyExpiryTimestamp': undefined, 'authenticate': { 'method': 'privateGetDeepcoinListenkeyExtend', // refresh existing listen key or 'privateGetDeepcoinListenkeyAcquire' - get a new one }, 'timeframes': { '1m': '1m', '5m': '5m', '15m': '15m', '30m': '30m', '1h': '1h', '4h': '4h', '12h': '12h', '1d': '1d', '1w': '1w', '1M': '1o', '1y': '1y', }, }, 'streaming': { 'ping': this.ping, }, }); } ping(client) { const url = client.url; if (url.indexOf('private') >= 0) { client.lastPong = this.milliseconds(); // prevent automatic disconnects on private channel } return 'ping'; } handlePong(client, message) { client.lastPong = this.milliseconds(); return message; } requestId() { this.lockId(); const previousValue = this.safeInteger(this.options, 'lastRequestId', 0); const newValue = this.sum(previousValue, 1); this.options['lastRequestId'] = newValue; this.unlockId(); return newValue; } createPublicRequest(market, requestId, topicID, suffix = '', unWatch = false) { let marketId = market['symbol']; // spot markets use symbol with slash if (market['type'] === 'swap') { marketId = market['baseId'] + market['quoteId']; // swap markets use symbol without slash } let action = '1'; // subscribe if (unWatch) { action = '0'; // unsubscribe } const request = { 'sendTopicAction': { 'Action': action, 'FilterValue': 'DeepCoin_' + marketId + suffix, 'LocalNo': requestId, 'ResumeNo': -1, 'TopicID': topicID, }, }; return request; } async watchPublic(market, messageHash, topicID, params = {}, suffix = '') { const url = this.urls['api']['ws']['public'][market['type']]; const requestId = this.requestId(); const request = this.createPublicRequest(market, requestId, topicID, suffix); const subscription = { 'subHash': messageHash, 'id': requestId, }; return await this.watch(url, messageHash, this.deepExtend(request, params), messageHash, subscription); } async unWatchPublic(market, messageHash, topicID, params = {}, subscription = {}, suffix = '') { const url = this.urls['api']['ws']['public'][market['type']]; const requestId = this.requestId(); const client = this.client(url); const existingSubscription = this.safeDict(client.subscriptions, messageHash); if (existingSubscription === undefined) { throw new errors.BadRequest(this.id + ' no subscription for ' + messageHash); } const subId = this.safeInteger(existingSubscription, 'id'); const request = this.createPublicRequest(market, subId, topicID, suffix, true); // unsubscribe message uses the same id as the original subscribe message const unsubHash = 'unsubscribe::' + messageHash; subscription = this.extend(subscription, { 'subHash': messageHash, 'unsubHash': unsubHash, 'symbols': [market['symbol']], 'id': requestId, }); return await this.watch(url, unsubHash, this.deepExtend(request, params), unsubHash, subscription); } async watchPrivate(messageHash, params = {}) { const listenKey = await this.authenticate(); const url = this.urls['api']['ws']['private'] + '?listenKey=' + listenKey; return await this.watch(url, messageHash, undefined, 'private', params); } async authenticate(params = {}) { this.checkRequiredCredentials(); const time = this.milliseconds(); let listenKeyExpiryTimestamp = this.safeInteger(this.options, 'listenKeyExpiryTimestamp', time); const expired = (time - listenKeyExpiryTimestamp) > 60000; // 1 minute before expiry let listenKey = this.safeString(this.options, 'listenKey'); let response = undefined; if (listenKey === undefined) { response = await this.privateGetDeepcoinListenkeyAcquire(params); } else if (expired) { const method = this.safeString(this.options, 'method', 'privateGetDeepcoinListenkeyExtend'); const getNewKey = (method === 'privateGetDeepcoinListenkeyAcquire'); if (getNewKey) { response = await this.privateGetDeepcoinListenkeyAcquire(params); } else { const request = { 'listenkey': listenKey, }; response = await this.privateGetDeepcoinListenkeyExtend(this.extend(request, params)); } } if (response !== undefined) { const data = this.safeDict(response, 'data', {}); listenKey = this.safeString(data, 'listenkey'); listenKeyExpiryTimestamp = this.safeTimestamp(data, 'expire_time'); this.options['listenKey'] = listenKey; this.options['listenKeyExpiryTimestamp'] = listenKeyExpiryTimestamp; } return listenKey; } /** * @method * @name deepcoin#watchTicker * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @see https://www.deepcoin.com/docs/publicWS/latestMarketData * @param {string} symbol unified symbol of the market to fetch the ticker for * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure} */ async watchTicker(symbol, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const messageHash = 'ticker' + '::' + market['symbol']; return await this.watchPublic(market, messageHash, '7', params); } /** * @method * @name deepcoin#unWatchTicker * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @see https://www.deepcoin.com/docs/publicWS/latestMarketData * @param {string} symbol unified symbol of the market to fetch the ticker for * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure} */ async unWatchTicker(symbol, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const messageHash = 'ticker' + '::' + market['symbol']; const subscription = { 'topic': 'ticker', }; return await this.unWatchPublic(market, messageHash, '7', params, subscription); } handleTicker(client, message) { // // a: 'PO', // m: 'Success', // tt: 1760913034780, // mt: 1760913034780, // r: [ // { // d: { // I: 'BTC/USDT', // U: 1760913034742, // PF: 0, // E: 0, // O: 108479.9, // H: 109449.9, // L: 108238, // V: 789.3424915, // T: 43003872.3705223, // N: 109345, // M: 87294.7, // D: 0, // V2: 3086.4496105, // T2: 332811624.339836, // F: 0, // C: 0, // BP1: 109344.9, // AP1: 109345.2 // } // } // ] // const response = this.safeList(message, 'r', []); const first = this.safeDict(response, 0, {}); const data = this.safeDict(first, 'd', {}); const marketId = this.safeString(data, 'I'); const market = this.safeMarket(marketId, undefined, '/'); const symbol = this.safeSymbol(marketId, market); const parsedTicker = this.parseWsTicker(data, market); const messageHash = 'ticker' + '::' + symbol; this.tickers[symbol] = parsedTicker; client.resolve(parsedTicker, messageHash); } parseWsTicker(ticker, market = undefined) { // // { // I: 'BTC/USDT', // U: 1760913034742, // PF: 0, // E: 0, // O: 108479.9, // H: 109449.9, // L: 108238, // V: 789.3424915, // T: 43003872.3705223, // N: 109345, // M: 87294.7, // D: 0, // V2: 3086.4496105, // T2: 332811624.339836, // F: 0, // C: 0, // BP1: 109344.9, // AP1: 109345.2 // } // const timestamp = this.safeInteger(ticker, 'U'); const high = this.safeNumber(ticker, 'H'); const low = this.safeNumber(ticker, 'L'); const open = this.safeNumber(ticker, 'O'); const last = this.safeNumber(ticker, 'N'); const bid = this.safeNumber(ticker, 'BP1'); const ask = this.safeNumber(ticker, 'AP1'); let baseVolume = this.safeNumber(ticker, 'V'); let quoteVolume = this.safeNumber(ticker, 'T'); if (market['inverse']) { const temp = baseVolume; baseVolume = quoteVolume; quoteVolume = temp; } return this.safeTicker({ 'symbol': market['symbol'], 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'high': high, 'low': low, 'bid': bid, 'bidVolume': undefined, 'ask': ask, 'askVolume': undefined, 'vwap': undefined, 'open': open, 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, 'baseVolume': baseVolume, 'quoteVolume': quoteVolume, 'info': ticker, }, market); } /** * @method * @name deepcoin#watchTrades * @description watches information on multiple trades made in a market * @see https://www.deepcoin.com/docs/publicWS/lastTransactions * @param {string} symbol unified market symbol of the market trades were made in * @param {int} [since] the earliest time in ms to fetch orders for * @param {int} [limit] the maximum number of trade structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure} */ async watchTrades(symbol, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const messageHash = 'trades' + '::' + market['symbol']; const trades = await this.watchPublic(market, messageHash, '2', params); if (this.newUpdates) { limit = trades.getLimit(symbol, limit); } return this.filterBySinceLimit(trades, since, limit, 'timestamp', true); } /** * @method * @name deepcoin#unWatchTrades * @description unWatches the list of most recent trades for a particular symbol * @see https://www.deepcoin.com/docs/publicWS/lastTransactions * @param {string} symbol unified symbol of the market to fetch trades for * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades} */ async unWatchTrades(symbol, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const messageHash = 'trades' + '::' + market['symbol']; const subscription = { 'topic': 'trades', }; return await this.unWatchPublic(market, messageHash, '2', params, subscription); } handleTrades(client, message) { // // { // "a": "PMT", // "b": 0, // "tt": 1760968672380, // "mt": 1760968672380, // "r": [ // { // "d": { // "TradeID": "1001056452325378", // "I": "BTC/USDT", // "D": "1", // "P": 111061, // "V": 0.00137, // "T": 1760968672 // } // } // ] // } // const response = this.safeList(message, 'r', []); const first = this.safeDict(response, 0, {}); const data = this.safeDict(first, 'd', {}); const marketId = this.safeString(data, 'I'); const market = this.safeMarket(marketId, undefined, '/'); const symbol = this.safeSymbol(marketId, market); if (!(symbol in this.trades)) { const limit = this.safeInteger(this.options, 'tradesLimit', 1000); this.trades[symbol] = new Cache.ArrayCache(limit); } const strored = this.trades[symbol]; if (data !== undefined) { const trade = this.parseWsTrade(data, market); strored.append(trade); } const messageHash = 'trades' + '::' + symbol; client.resolve(strored, messageHash); } parseWsTrade(trade, market = undefined) { // // watchTrades // { // "TradeID": "1001056452325378", // "I": "BTC/USDT", // "D": "1", // "P": 111061, // "V": 0.00137, // "T": 1760968672 // } // // watchMyTrades // { // "A": "9256245", // "CC": "USDT", // "CP": 0, // "D": "0", // "F": 0.152, // "I": "DOGE/USDT", // "IT": 1761048103, // "M": "9256245", // "OS": "1001437462198486", // "P": 0.19443, // "T": 14.77668, // "TI": "1001056459096708", // "TT": 1761048103, // "V": 76, // "f": "DOGE", // "l": 1, // "m": "1", // "o": "0" // } // const direction = this.safeString(trade, 'D'); const timestamp = this.safeTimestamp2(trade, 'TT', 'T'); const matchRole = this.safeString(trade, 'm'); let fee = undefined; const feeCost = this.safeString(trade, 'F'); if (feeCost !== undefined) { fee = { 'cost': feeCost, 'currency': this.safeCurrencyCode(this.safeString(trade, 'f')), }; } return this.safeTrade({ 'info': trade, 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'symbol': market['symbol'], 'id': this.safeString2(trade, 'TradeID', 'TI'), 'order': this.safeString(trade, 'OS'), 'type': undefined, 'takerOrMaker': this.handleTakerOrMaker(matchRole), 'side': this.parseTradeSide(direction), 'price': this.safeString(trade, 'P'), 'amount': this.safeString(trade, 'V'), 'cost': this.safeString(trade, 'T'), 'fee': fee, }, market); } parseTradeSide(direction) { const sides = { '0': 'buy', '1': 'sell', }; return this.safeString(sides, direction, direction); } handleTakerOrMaker(matchRole) { const roles = { '0': 'maker', '1': 'taker', }; return this.safeString(roles, matchRole, matchRole); } /** * @method * @name deepcoin#watchOHLCV * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market * @see https://www.deepcoin.com/docs/publicWS/KLines * @param {string} symbol unified symbol of the market to fetch OHLCV data for * @param {string} [timeframe] the length of time each candle represents * @param {int} [since] timestamp in ms of the earliest candle to fetch * @param {int} [limit] the maximum amount of candles to fetch * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume */ async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); const market = this.market(symbol); symbol = market['symbol']; const timeframes = this.safeDict(this.options, 'timeframes', {}); const interval = this.safeString(timeframes, timeframe, timeframe); const messageHash = 'ohlcv' + '::' + symbol + '::' + timeframe; const suffix = '_' + interval; const ohlcv = await this.watchPublic(market, messageHash, '11', params, suffix); if (this.newUpdates) { limit = ohlcv.getLimit(symbol, limit); } return this.filterBySinceLimit(ohlcv, since, limit, 0, true); } /** * @method * @name deepcoin#unWatchOHLCV * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market * @see https://docs.backpack.exchange/#tag/Streams/Public/K-Line * @param {string} symbol unified symbol of the market to fetch OHLCV data for * @param {string} [timeframe] the length of time each candle represents * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume */ async unWatchOHLCV(symbol, timeframe = '1m', params = {}) { await this.loadMarkets(); const market = this.market(symbol); symbol = market['symbol']; const timeframes = this.safeDict(this.options, 'timeframes', {}); const interval = this.safeString(timeframes, timeframe, timeframe); const messageHash = 'ohlcv' + '::' + symbol + '::' + timeframe; const suffix = '_' + interval; const subscription = { 'topic': 'ohlcv', 'symbolsAndTimeframes': [[symbol, timeframe]], }; return await this.unWatchPublic(market, messageHash, '11', params, subscription, suffix); } handleOHLCV(client, message) { // // { // "a": "PK", // "tt": 1760972831580, // "mt": 1760972831580, // "r": [ // { // "d": { // "I": "BTC/USDT", // "P": "1m", // "B": 1760972820, // "O": 111373, // "C": 111382.9, // "H": 111382.9, // "L": 111373, // "V": 0.2414172, // "M": 26888.19693324 // }, // "t": "LK" // } // ] // } // const response = this.safeList(message, 'r', []); const first = this.safeDict(response, 0, {}); const data = this.safeDict(first, 'd', {}); const marketId = this.safeString(data, 'I'); const market = this.safeMarket(marketId, undefined, '/'); const symbol = this.safeSymbol(marketId, market); const interval = this.safeString(data, 'P'); const timeframe = this.findTimeframe(interval); if (!(symbol in this.ohlcvs)) { this.ohlcvs[symbol] = {}; } if (!(timeframe in this.ohlcvs[symbol])) { const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000); this.ohlcvs[symbol][timeframe] = new Cache.ArrayCacheByTimestamp(limit); } const stored = this.ohlcvs[symbol][timeframe]; if (data !== undefined) { const ohlcv = this.parseWsOHLCV(data, market); stored.append(ohlcv); } const messageHash = 'ohlcv' + '::' + symbol + '::' + timeframe; client.resolve(stored, messageHash); } parseWsOHLCV(ohlcv, market = undefined) { // // { // "I": "BTC/USDT", // "P": "1m", // "B": 1760972820, // "O": 111373, // "C": 111382.9, // "H": 111382.9, // "L": 111373, // "V": 0.2414172, // "M": 26888.19693324 // } // return [ this.safeTimestamp(ohlcv, 'B'), this.safeNumber(ohlcv, 'O'), this.safeNumber(ohlcv, 'H'), this.safeNumber(ohlcv, 'L'), this.safeNumber(ohlcv, 'C'), this.safeNumber(ohlcv, 'V'), ]; } /** * @method * @name deepcoin#watchOrderBook * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @see https://www.deepcoin.com/docs/publicWS/25LevelIncrementalMarketData * @param {string} symbol unified symbol of the market to fetch the order book for * @param {int} [limit] the maximum amount of order book entries to return. * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols */ async watchOrderBook(symbol, limit = undefined, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const messageHash = 'orderbook' + '::' + market['symbol']; const suffix = '_0.1'; const orderbook = await this.watchPublic(market, messageHash, '25', params, suffix); return orderbook.limit(); } /** * @method * @name deepcoin#unWatchOrderBook * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @see https://www.deepcoin.com/docs/publicWS/25LevelIncrementalMarketData * @param {string} symbol unified array of symbols * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols */ async unWatchOrderBook(symbol, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const messageHash = 'orderbook' + '::' + market['symbol']; const suffix = '_0.1'; const subscription = { 'topic': 'orderbook', }; return await this.unWatchPublic(market, messageHash, '25', params, subscription, suffix); } handleOrderBook(client, message) { // // { // "a": "PMO", // "t": "i", // i - update, f - snapshot // "r": [ // { // "d": { "I": "ETH/USDT", "D": "1", "P": 4021, "V": 54.39979 } // }, // { // "d": { "I": "ETH/USDT", "D": "0", "P": 4021.1, "V": 49.56724 } // } // ], // "tt": 1760975816446, // "mt": 1760975816446 // } // const response = this.safeList(message, 'r', []); const first = this.safeDict(response, 0, {}); const data = this.safeDict(first, 'd', {}); const marketId = this.safeString(data, 'I'); const market = this.safeMarket(marketId, undefined, '/'); const symbol = this.safeSymbol(marketId, market); if (!(symbol in this.orderbooks)) { this.orderbooks[symbol] = this.orderBook(); } const orderbook = this.orderbooks[symbol]; const type = this.safeString(message, 't'); if (orderbook['timestamp'] === undefined) { if (type === 'f') { // snapshot this.handleOrderBookSnapshot(client, message); } else { // cache the updates until the snapshot is received orderbook.cache.push(message); } } else { this.handleOrderBookMessage(client, message, orderbook); const messageHash = 'orderbook' + '::' + symbol; client.resolve(orderbook, messageHash); } } handleOrderBookSnapshot(client, message) { const entries = this.safeList(message, 'r', []); const first = this.safeDict(entries, 0, {}); const data = this.safeDict(first, 'd', {}); const marketId = this.safeString(data, 'I'); const market = this.safeMarket(marketId, undefined, '/'); const symbol = this.safeSymbol(marketId, market); const orderbook = this.orderbooks[symbol]; const orderedEntries = { 'bids': [], 'asks': [], }; for (let i = 0; i < entries.length; i++) { const entry = entries[i]; const entryData = this.safeDict(entry, 'd', {}); const side = this.safeString(entryData, 'D'); const price = this.safeNumber(entryData, 'P'); const volume = this.safeNumber(entryData, 'V'); if (side === '0') { // bid orderedEntries['bids'].push([price, volume]); } else if (side === '1') { // ask orderedEntries['asks'].push([price, volume]); } } const timestamp = this.safeInteger(message, 'mt'); const snapshot = this.parseOrderBook(orderedEntries, symbol, timestamp); orderbook.reset(snapshot); const cachedMessages = orderbook.cache; for (let j = 0; j < cachedMessages.length; j++) { const cachedMessage = cachedMessages[j]; this.handleOrderBookMessage(client, cachedMessage, orderbook); } orderbook.cache = []; const messageHash = 'orderbook' + '::' + symbol; client.resolve(orderbook, messageHash); } handleOrderBookMessage(client, message, orderbook) { // { // "a": "PMO", // "t": "i", // i - update, f - snapshot // "r": [ // { // "d": { "I": "ETH/USDT", "D": "1", "P": 4021, "V": 54.39979 } // }, // { // "d": { "I": "ETH/USDT", "D": "0", "P": 4021.1, "V": 49.56724 } // } // ], // "tt": 1760975816446, // "mt": 1760975816446 // } // const timestamp = this.safeInteger(message, 'mt'); if (timestamp > orderbook['timestamp']) { const response = this.safeList(message, 'r', []); this.handleDeltas(orderbook, response); orderbook['timestamp'] = timestamp; orderbook['datetime'] = this.iso8601(timestamp); } } handleDelta(orderbook, entry) { const data = this.safeDict(entry, 'd', {}); const bids = orderbook['bids']; const asks = orderbook['asks']; const side = this.safeString(data, 'D'); const price = this.safeNumber(data, 'P'); const volume = this.safeNumber(data, 'V'); if (side === '0') { // bid bids.store(price, volume); } else if (side === '1') { // ask asks.store(price, volume); } } /** * @method * @name deepcoin#watchMyTrades * @description watches information on multiple trades made by the user * @see https://www.deepcoin.com/docs/privateWS/Trade * @param {string} symbol unified market symbol of the market orders were made in * @param {int} [since] the earliest time in ms to fetch orders for * @param {int} [limit] the maximum number of order structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure} */ async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) { let messageHash = 'myTrades'; await this.loadMarkets(); if (symbol !== undefined) { symbol = this.symbol(symbol); messageHash += '::' + symbol; } const trades = await this.watchPrivate(messageHash, params); if (this.newUpdates) { limit = trades.getLimit(symbol, limit); } return this.filterBySymbolSinceLimit(trades, symbol, since, limit, true); } handleMyTrade(client, message) { // // { // "action": "PushTrade", // "result": [ // { // "table": "Trade", // "data": { // "A": "9256245", // "CC": "USDT", // "CP": 0, // "D": "0", // "F": 0.152, // "I": "DOGE/USDT", // "IT": 1761048103, // "M": "9256245", // "OS": "1001437462198486", // "P": 0.19443, // "T": 14.77668, // "TI": "1001056459096708", // "TT": 1761048103, // "V": 76, // "f": "DOGE", // "l": 1, // "m": "1", // "o": "0" // } // } // ] // } // const result = this.safeList(message, 'result', []); const first = this.safeDict(result, 0, {}); const data = this.safeDict(first, 'data', {}); const marketId = this.safeString(data, 'I'); const market = this.safeMarket(marketId, undefined, '/'); const symbol = this.safeSymbol(marketId, market); const messageHash = 'myTrades'; const symbolMessageHash = messageHash + '::' + symbol; if ((messageHash in client.futures) || (symbolMessageHash in client.futures)) { if (this.myTrades === undefined) { const limit = this.safeInteger(this.options, 'tradesLimit', 1000); this.myTrades = new Cache.ArrayCacheBySymbolById(limit); } const stored = this.myTrades; const parsed = this.parseWsTrade(data, market); stored.append(parsed); client.resolve(stored, messageHash); client.resolve(stored, symbolMessageHash); } } /** * @method * @name deepcoin#watchOrders * @description watches information on multiple orders made by the user * @see https://www.deepcoin.com/docs/privateWS/order * @param {string} symbol unified market symbol of the market orders were made in * @param {int} [since] the earliest time in ms to fetch orders for * @param {int} [limit] the maximum number of order structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure} */ async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) { let messageHash = 'orders'; await this.loadMarkets(); if (symbol !== undefined) { symbol = this.symbol(symbol); messageHash += '::' + symbol; } const orders = await this.watchPrivate(messageHash, params); if (this.newUpdates) { limit = orders.getLimit(symbol, limit); } return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true); } handleOrder(client, message) { // // { // "action": "PushOrder", // "result": [ // { // "table": "Order", // "data": { // "D": "0", // "I": "DOGE/USDT", // "IT": 1761051006, // "L": "1001437480817468", // "OPT": "4", // "OS": "1001437480817468", // "OT": "0", // "Or": "1", // "P": 0.19537, // "T": 14.84128, // "U": 1761051006, // "V": 76, // "VT": 76, // "i": 1, // "l": 1, // "o": "0", // "p": "0", // "t": 0.19528 // } // } // ] // } // const result = this.safeList(message, 'result', []); const first = this.safeDict(result, 0, {}); const data = this.safeDict(first, 'data', {}); const marketId = this.safeString(data, 'I'); const market = this.safeMarket(marketId, undefined, '/'); const symbol = this.safeSymbol(marketId, market); const messageHash = 'orders'; const symbolMessageHash = messageHash + '::' + symbol; if ((messageHash in client.futures) || (symbolMessageHash in client.futures)) { if (this.orders === undefined) { const limit = this.safeInteger(this.options, 'ordersLimit', 1000); this.orders = new Cache.ArrayCacheBySymbolById(limit); } const parsed = this.parseWsOrder(data, market); this.orders.append(parsed); client.resolve(this.orders, messageHash); client.resolve(this.orders, symbolMessageHash); } } parseWsOrder(order, market = undefined) { // // { // "D": "0", // "I": "DOGE/USDT", // "IT": 1761051006, // "L": "1001437480817468", // "OPT": "4", // "OS": "1001437480817468", // "OT": "0", // "Or": "1", // "P": 0.19537, // "T": 14.84128, // "U": 1761051006, // "V": 76, // "VT": 76, // "i": 1, // "l": 1, // "o": "0", // "p": "0", // "t": 0.19528 // } // const state = this.safeString(order, 'Or'); const timestamp = this.safeTimestamp(order, 'IT'); const direction = this.safeString(order, 'D'); return this.safeOrder({ 'id': this.safeString(order, 'OS'), 'clientOrderId': undefined, 'datetime': this.iso8601(timestamp), 'timestamp': timestamp, 'lastTradeTimestamp': undefined, 'lastUpdateTimestamp': this.safeTimestamp(order, 'U'), 'status': this.parseWsOrderStatus(state), 'symbol': market['symbol'], 'type': undefined, 'timeInForce': undefined, 'side': this.parseTradeSide(direction), 'price': this.safeString(order, 'P'), 'average': this.safeString(order, 't'), 'amount': this.safeString(order, 'V'), 'filled': this.safeString(order, 'VT'), 'remaining': undefined, 'triggerPrice': undefined, 'takeProfitPrice': this.safeString(order, 'TPT'), 'stopLossPrice': this.safeString(order, 'SLT'), 'cost': this.safeString(order, 'T'), 'trades': undefined, 'fee': undefined, 'reduceOnly': undefined, 'postOnly': undefined, 'info': order, }, market); } parseWsOrderStatus(status) { const statuses = { '1': 'closed', '4': 'open', '6': 'canceled', }; return this.safeString(statuses, status, status); } /** * @method * @name deepcoin#watchPositions * @description watch all open positions * @see https://www.deepcoin.com/docs/privateWS/Position * @param {string[]} [symbols] list of unified market symbols to watch positions for * @param {int} [since] the earliest time in ms to fetch positions for * @param {int} [limit] the maximum number of positions to retrieve * @param {object} params extra parameters specific to the exchange API endpoint * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure} */ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); const listenKey = await this.authenticate(); symbols = this.marketSymbols(symbols); const messageHash = 'positions'; const messageHashes = []; if (symbols !== undefined) { for (let i = 0; i < symbols.length; i++) { const symbol = symbols[i]; const symbolMessageHash = messageHash + '::' + symbol; messageHashes.push(symbolMessageHash); } } else { messageHashes.push(messageHash); } const url = this.urls['api']['ws']['private'] + '?listenKey=' + listenKey; const positions = await this.watchMultiple(url, messageHashes, params, ['private']); if (this.newUpdates) { return positions; } return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true); } handlePosition(client, message) { // // { // "action": "PushPosition", // "result": [ // { // "table": "Position", // "data": { // "A": "9256245", // "CP": 0, // "I": "DOGE/USDT", // "M": "9256245", // "OP": 0.198845, // "Po": 151.696, // "U": 1761058213, // "i": 1, // "l": 1, // "p": "0", // "u": 0 // } // } // ] // } // const result = this.safeList(message, 'result', []); const first = this.safeDict(result, 0, {}); const data = this.safeDict(first, 'data', {}); const marketId = this.safeString(data, 'I'); const market = this.safeMarket(marketId, undefined, '/'); const symbol = this.safeSymbol(marketId, market); const messageHash = 'positions'; const symbolMessageHash = messageHash + '::' + symbol; if ((messageHash in client.futures) || (symbolMessageHash in client.futures)) { if (this.positions === undefined) { this.positions = new Cache.ArrayCacheBySymbolBySide(); } const parsed = this.parseWsPosition(data, market); this.positions.append(parsed); client.resolve(this.positions, messageHash); client.resolve(this.positions, symbolMessageHash); } } parseWsPosition(position, market = undefined) { // // { // "A": "9256245", // "CP": 0, // "I": "DOGE/USDT", // "M": "9256245", // "OP": 0.198845, // "Po": 151.696, // "U": 1761058213, // "i": 1, // "l": 1, // "p": "0", // "u": 0 // } // const timestamp = this.safeInteger(position, 'U'); const direction = this.safeString(position, 'p'); const marginMode = this.safeString(position, 'i'); return this.safePosition({ 'symbol': market['symbol'], 'id': undefined, 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'contracts': this.safeString(position, 'Po'), 'contractSize': undefined, 'side': this.parsePositionSide(direction), 'notional': undefined, 'leverage': this.omitZero(this.safeString(position, 'l')), 'unrealizedPnl': undefined, 'realizedPnl': undefined, 'collateral': undefined, 'entryPrice': this.safeString(position, 'OP'), 'markPrice': undefined, 'liquidationPrice': undefined, 'marginMode': this.parseWsMarginMode(marginMode), 'hedged': true, 'maintenanceMargin': this.safeString(position, 'u'), 'maintenanceMarginPercentage': undefined, 'initialMargin': undefined, 'initialMarginPercentage': undefined, 'marginRatio': undefined, 'lastUpdateTimestamp': undefined, 'lastPrice': undefined, 'stopLossPrice': undefined, 'takeProfitPrice': undefined, 'percentage': undefined, 'info': position, }); } parsePositionSide(direction) { if (direction === undefined) { return direction; } const directions = { '0': 'long', '1': 'short', }; return this.safeString(directions, direction, direction); } parseWsMarginMode(marginMode) { if (marginMode === undefined) { return marginMode; } const modes = { '0': 'isolated', '1': 'cross', }; return this.safeString(modes, marginMode, marginMode); } handleMessage(client, message) { if (message === 'pong') { this.handlePong(client, message); } else { const m = this.safeString(message, 'm'); if ((m !== undefined) && (m !== 'Success')) { this.handleErrorMessage(client, message); } const action = this.safeString2(message, 'a', 'action'); if (action === 'RecvTopicAction') { this.handleSubscriptionStatus(client, message); } else if (action === 'PO') { this.handleTicker(client, message); } else if (action === 'PMT') { this.handleTrades(client, message); } else if (action === 'PK') { this.handleOHLCV(client, message); } else if (action === 'PMO') { this.handleOrderBook(client, message); } else if (action === 'PushTrade') { this.handleMyTrade(client, message); } else if (action === 'PushOrder') { this.handleOrder(client, message); } else if (action === 'PushPosition') { this.handlePosition(client, message); } } } handleSubscriptionStatus(client, message) { // // { // "a": "RecvTopicAction", // "m": "Success", // "r": [ // { // "d": { // "A": "0", // "L": 1, // "T": "7", // "F": "DeepCoin_BTC/USDT", // "R": -1 // } // } // ] // } // const response = this.safeList(message, 'r', []); const first = this.safeDict(response, 0, {}); const data = this.safeDict(first, 'd', {}); const action = this.safeString(data, 'A'); // 1 = subscribe, 0 = unsubscribe if (action === '0') { const subscriptionsById = this.indexBy(client.subscriptions, 'id'); const subId = this.safeInteger(data, 'L'); const subscription = this.safeDict(subscriptionsById, subId, {}); // original watch subscription const subHash = this.safeString(subscription, 'subHash'); const unsubHash = 'unsubscribe::' + subHash; const unsubsciption = this.safeDict(client.subscriptions, unsubHash, {}); // unWatch subscription this.handleUnSubscription(client, unsubsciption); } } handleUnSubscription(client, subscription) { const subHash = this.safeString(subscription, 'subHash'); const unsubHash = this.safeString(subscription, 'unsubHash'); this.cleanUnsubscription(client, subHash, unsubHash); this.cleanCache(subscription); } handleErrorMessage(client, message) { // // { // "a": "RecvTopicAction", // "m": "subscription cluster does not "exist": BTC/USD", // "r": [ // { // "d": { // "A": "1", // "L": 1, // "T": "7", // "F": "DeepCoin_BTC/USD", // "R": -1 // } // } // ] // } // const messageText = this.safeString(message, 'm', ''); const response = this.safeList(message, 'r', []); const first = this.safeDict(response, 0, {});