ccxt 4.5.17 → 4.5.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +8 -5
  2. package/dist/ccxt.browser.min.js +2 -2
  3. package/dist/cjs/ccxt.js +6 -1
  4. package/dist/cjs/src/abstract/deepcoin.js +11 -0
  5. package/dist/cjs/src/apex.js +33 -15
  6. package/dist/cjs/src/base/Exchange.js +3 -3
  7. package/dist/cjs/src/base/ws/Client.js +8 -7
  8. package/dist/cjs/src/bigone.js +20 -0
  9. package/dist/cjs/src/binanceus.js +31 -1
  10. package/dist/cjs/src/blofin.js +4 -1
  11. package/dist/cjs/src/bybit.js +3 -0
  12. package/dist/cjs/src/deepcoin.js +3024 -0
  13. package/dist/cjs/src/pro/ascendex.js +2 -2
  14. package/dist/cjs/src/pro/binance.js +100 -3
  15. package/dist/cjs/src/pro/binanceus.js +19 -0
  16. package/dist/cjs/src/pro/blofin.js +11 -2
  17. package/dist/cjs/src/pro/deepcoin.js +1225 -0
  18. package/dist/cjs/src/pro/kraken.js +5 -1
  19. package/js/ccxt.d.ts +8 -2
  20. package/js/ccxt.js +6 -2
  21. package/js/src/abstract/bybit.d.ts +3 -0
  22. package/js/src/abstract/deepcoin.d.ts +60 -0
  23. package/js/src/abstract/deepcoin.js +11 -0
  24. package/js/src/apex.d.ts +2 -0
  25. package/js/src/apex.js +33 -15
  26. package/js/src/base/Exchange.js +3 -3
  27. package/js/src/base/ws/Client.js +8 -7
  28. package/js/src/bigone.js +20 -0
  29. package/js/src/binanceus.js +31 -1
  30. package/js/src/blofin.js +4 -1
  31. package/js/src/bybit.js +3 -0
  32. package/js/src/deepcoin.d.ts +498 -0
  33. package/js/src/deepcoin.js +3022 -0
  34. package/js/src/pro/ascendex.d.ts +1 -1
  35. package/js/src/pro/ascendex.js +2 -2
  36. package/js/src/pro/binance.d.ts +35 -1
  37. package/js/src/pro/binance.js +97 -3
  38. package/js/src/pro/binanceus.js +19 -0
  39. package/js/src/pro/blofin.d.ts +5 -0
  40. package/js/src/pro/blofin.js +11 -2
  41. package/js/src/pro/deepcoin.d.ts +169 -0
  42. package/js/src/pro/deepcoin.js +1224 -0
  43. package/js/src/pro/kraken.js +5 -1
  44. package/package.json +1 -1
@@ -0,0 +1,1224 @@
1
+ // ----------------------------------------------------------------------------
2
+
3
+ // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
4
+ // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
+ // EDIT THE CORRESPONDENT .ts FILE INSTEAD
6
+
7
+ // ---------------------------------------------------------------------------
8
+ import deepcoinRest from '../deepcoin.js';
9
+ import { BadRequest, ExchangeError } from '../base/errors.js';
10
+ import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
11
+ // ---------------------------------------------------------------------------
12
+ export default class deepcoin extends deepcoinRest {
13
+ describe() {
14
+ return this.deepExtend(super.describe(), {
15
+ 'has': {
16
+ 'ws': true,
17
+ 'watchTicker': true,
18
+ 'watchMarkPrice': false,
19
+ 'watchMarkPrices': false,
20
+ 'watchTickers': false,
21
+ 'watchBidsAsks': false,
22
+ 'watchOrderBook': true,
23
+ 'watchTrades': true,
24
+ 'watchTradesForSymbols': false,
25
+ 'watchOrderBookForSymbols': false,
26
+ 'watchBalance': false,
27
+ 'watchLiquidations': false,
28
+ 'watchLiquidationsForSymbols': false,
29
+ 'watchMyLiquidations': false,
30
+ 'watchMyLiquidationsForSymbols': false,
31
+ 'watchOHLCV': true,
32
+ 'watchOHLCVForSymbols': false,
33
+ 'watchOrders': true,
34
+ 'watchMyTrades': true,
35
+ 'watchPositions': true,
36
+ 'watchFundingRate': false,
37
+ 'watchFundingRates': false,
38
+ 'createOrderWs': false,
39
+ 'editOrderWs': false,
40
+ 'cancelOrderWs': false,
41
+ 'cancelOrdersWs': false,
42
+ 'cancelAllOrdersWs': false,
43
+ 'unWatchTicker': true,
44
+ 'unWatchTrades': true,
45
+ 'unWatchOHLCV': true,
46
+ 'unWatchOrderBook': true,
47
+ },
48
+ 'urls': {
49
+ 'api': {
50
+ 'ws': {
51
+ 'public': {
52
+ 'spot': 'wss://stream.deepcoin.com/streamlet/trade/public/spot?platform=api',
53
+ 'swap': 'wss://stream.deepcoin.com/streamlet/trade/public/swap?platform=api',
54
+ },
55
+ 'private': 'wss://stream.deepcoin.com/v1/private',
56
+ },
57
+ },
58
+ },
59
+ 'options': {
60
+ 'lastRequestId': undefined,
61
+ 'listenKey': undefined,
62
+ 'listenKeyExpiryTimestamp': undefined,
63
+ 'authenticate': {
64
+ 'method': 'privateGetDeepcoinListenkeyExtend', // refresh existing listen key or 'privateGetDeepcoinListenkeyAcquire' - get a new one
65
+ },
66
+ 'timeframes': {
67
+ '1m': '1m',
68
+ '5m': '5m',
69
+ '15m': '15m',
70
+ '30m': '30m',
71
+ '1h': '1h',
72
+ '4h': '4h',
73
+ '12h': '12h',
74
+ '1d': '1d',
75
+ '1w': '1w',
76
+ '1M': '1o',
77
+ '1y': '1y',
78
+ },
79
+ },
80
+ 'streaming': {
81
+ 'ping': this.ping,
82
+ },
83
+ });
84
+ }
85
+ ping(client) {
86
+ const url = client.url;
87
+ if (url.indexOf('private') >= 0) {
88
+ client.lastPong = this.milliseconds();
89
+ // prevent automatic disconnects on private channel
90
+ }
91
+ return 'ping';
92
+ }
93
+ handlePong(client, message) {
94
+ client.lastPong = this.milliseconds();
95
+ return message;
96
+ }
97
+ requestId() {
98
+ const previousValue = this.safeInteger(this.options, 'lastRequestId', 0);
99
+ const newValue = this.sum(previousValue, 1);
100
+ this.options['lastRequestId'] = newValue;
101
+ return newValue;
102
+ }
103
+ createPublicRequest(market, requestId, topicID, suffix = '', unWatch = false) {
104
+ let marketId = market['symbol']; // spot markets use symbol with slash
105
+ if (market['type'] === 'swap') {
106
+ marketId = market['baseId'] + market['quoteId']; // swap markets use symbol without slash
107
+ }
108
+ let action = '1'; // subscribe
109
+ if (unWatch) {
110
+ action = '0'; // unsubscribe
111
+ }
112
+ const request = {
113
+ 'sendTopicAction': {
114
+ 'Action': action,
115
+ 'FilterValue': 'DeepCoin_' + marketId + suffix,
116
+ 'LocalNo': requestId,
117
+ 'ResumeNo': -1,
118
+ 'TopicID': topicID,
119
+ },
120
+ };
121
+ return request;
122
+ }
123
+ async watchPublic(market, messageHash, topicID, params = {}, suffix = '') {
124
+ const url = this.urls['api']['ws']['public'][market['type']];
125
+ const requestId = this.requestId();
126
+ const request = this.createPublicRequest(market, requestId, topicID, suffix);
127
+ const subscription = {
128
+ 'subHash': messageHash,
129
+ 'id': requestId,
130
+ };
131
+ return await this.watch(url, messageHash, this.deepExtend(request, params), messageHash, subscription);
132
+ }
133
+ async unWatchPublic(market, messageHash, topicID, params = {}, subscription = {}, suffix = '') {
134
+ const url = this.urls['api']['ws']['public'][market['type']];
135
+ const requestId = this.requestId();
136
+ const client = this.client(url);
137
+ const existingSubscription = this.safeDict(client.subscriptions, messageHash);
138
+ if (existingSubscription === undefined) {
139
+ throw new BadRequest(this.id + ' no subscription for ' + messageHash);
140
+ }
141
+ const subId = this.safeInteger(existingSubscription, 'id');
142
+ const request = this.createPublicRequest(market, subId, topicID, suffix, true); // unsubscribe message uses the same id as the original subscribe message
143
+ const unsubHash = 'unsubscribe::' + messageHash;
144
+ subscription = this.extend(subscription, {
145
+ 'subHash': messageHash,
146
+ 'unsubHash': unsubHash,
147
+ 'symbols': [market['symbol']],
148
+ 'id': requestId,
149
+ });
150
+ return await this.watch(url, unsubHash, this.deepExtend(request, params), unsubHash, subscription);
151
+ }
152
+ async watchPrivate(messageHash, params = {}) {
153
+ const listenKey = await this.authenticate();
154
+ const url = this.urls['api']['ws']['private'] + '?listenKey=' + listenKey;
155
+ return await this.watch(url, messageHash, undefined, 'private', params);
156
+ }
157
+ async authenticate(params = {}) {
158
+ this.checkRequiredCredentials();
159
+ const time = this.milliseconds();
160
+ let listenKeyExpiryTimestamp = this.safeInteger(this.options, 'listenKeyExpiryTimestamp', time);
161
+ const expired = (time - listenKeyExpiryTimestamp) > 60000; // 1 minute before expiry
162
+ let listenKey = this.safeString(this.options, 'listenKey');
163
+ let response = undefined;
164
+ if (listenKey === undefined) {
165
+ response = await this.privateGetDeepcoinListenkeyAcquire(params);
166
+ }
167
+ else if (expired) {
168
+ const method = this.safeString(this.options, 'method', 'privateGetDeepcoinListenkeyExtend');
169
+ const getNewKey = (method === 'privateGetDeepcoinListenkeyAcquire');
170
+ if (getNewKey) {
171
+ response = await this.privateGetDeepcoinListenkeyAcquire(params);
172
+ }
173
+ else {
174
+ const request = {
175
+ 'listenkey': listenKey,
176
+ };
177
+ response = await this.privateGetDeepcoinListenkeyExtend(this.extend(request, params));
178
+ }
179
+ }
180
+ if (response !== undefined) {
181
+ const data = this.safeDict(response, 'data', {});
182
+ listenKey = this.safeString(data, 'listenkey');
183
+ listenKeyExpiryTimestamp = this.safeTimestamp(data, 'expire_time');
184
+ this.options['listenKey'] = listenKey;
185
+ this.options['listenKeyExpiryTimestamp'] = listenKeyExpiryTimestamp;
186
+ }
187
+ return listenKey;
188
+ }
189
+ /**
190
+ * @method
191
+ * @name deepcoin#watchTicker
192
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
193
+ * @see https://www.deepcoin.com/docs/publicWS/latestMarketData
194
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
195
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
196
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
197
+ */
198
+ async watchTicker(symbol, params = {}) {
199
+ await this.loadMarkets();
200
+ const market = this.market(symbol);
201
+ const messageHash = 'ticker' + '::' + market['symbol'];
202
+ return await this.watchPublic(market, messageHash, '7', params);
203
+ }
204
+ /**
205
+ * @method
206
+ * @name deepcoin#unWatchTicker
207
+ * @description unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
208
+ * @see https://www.deepcoin.com/docs/publicWS/latestMarketData
209
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
210
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
211
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
212
+ */
213
+ async unWatchTicker(symbol, params = {}) {
214
+ await this.loadMarkets();
215
+ const market = this.market(symbol);
216
+ const messageHash = 'ticker' + '::' + market['symbol'];
217
+ const subscription = {
218
+ 'topic': 'ticker',
219
+ };
220
+ return await this.unWatchPublic(market, messageHash, '7', params, subscription);
221
+ }
222
+ handleTicker(client, message) {
223
+ //
224
+ // a: 'PO',
225
+ // m: 'Success',
226
+ // tt: 1760913034780,
227
+ // mt: 1760913034780,
228
+ // r: [
229
+ // {
230
+ // d: {
231
+ // I: 'BTC/USDT',
232
+ // U: 1760913034742,
233
+ // PF: 0,
234
+ // E: 0,
235
+ // O: 108479.9,
236
+ // H: 109449.9,
237
+ // L: 108238,
238
+ // V: 789.3424915,
239
+ // T: 43003872.3705223,
240
+ // N: 109345,
241
+ // M: 87294.7,
242
+ // D: 0,
243
+ // V2: 3086.4496105,
244
+ // T2: 332811624.339836,
245
+ // F: 0,
246
+ // C: 0,
247
+ // BP1: 109344.9,
248
+ // AP1: 109345.2
249
+ // }
250
+ // }
251
+ // ]
252
+ //
253
+ const response = this.safeList(message, 'r', []);
254
+ const first = this.safeDict(response, 0, {});
255
+ const data = this.safeDict(first, 'd', {});
256
+ const marketId = this.safeString(data, 'I');
257
+ const market = this.safeMarket(marketId, undefined, '/');
258
+ const symbol = this.safeSymbol(marketId, market);
259
+ const parsedTicker = this.parseWsTicker(data, market);
260
+ const messageHash = 'ticker' + '::' + symbol;
261
+ this.tickers[symbol] = parsedTicker;
262
+ client.resolve(parsedTicker, messageHash);
263
+ }
264
+ parseWsTicker(ticker, market = undefined) {
265
+ //
266
+ // {
267
+ // I: 'BTC/USDT',
268
+ // U: 1760913034742,
269
+ // PF: 0,
270
+ // E: 0,
271
+ // O: 108479.9,
272
+ // H: 109449.9,
273
+ // L: 108238,
274
+ // V: 789.3424915,
275
+ // T: 43003872.3705223,
276
+ // N: 109345,
277
+ // M: 87294.7,
278
+ // D: 0,
279
+ // V2: 3086.4496105,
280
+ // T2: 332811624.339836,
281
+ // F: 0,
282
+ // C: 0,
283
+ // BP1: 109344.9,
284
+ // AP1: 109345.2
285
+ // }
286
+ //
287
+ const timestamp = this.safeInteger(ticker, 'U');
288
+ const high = this.safeNumber(ticker, 'H');
289
+ const low = this.safeNumber(ticker, 'L');
290
+ const open = this.safeNumber(ticker, 'O');
291
+ const last = this.safeNumber(ticker, 'N');
292
+ const bid = this.safeNumber(ticker, 'BP1');
293
+ const ask = this.safeNumber(ticker, 'AP1');
294
+ let baseVolume = this.safeNumber(ticker, 'V');
295
+ let quoteVolume = this.safeNumber(ticker, 'T');
296
+ if (market['inverse']) {
297
+ const temp = baseVolume;
298
+ baseVolume = quoteVolume;
299
+ quoteVolume = temp;
300
+ }
301
+ return this.safeTicker({
302
+ 'symbol': market['symbol'],
303
+ 'timestamp': timestamp,
304
+ 'datetime': this.iso8601(timestamp),
305
+ 'high': high,
306
+ 'low': low,
307
+ 'bid': bid,
308
+ 'bidVolume': undefined,
309
+ 'ask': ask,
310
+ 'askVolume': undefined,
311
+ 'vwap': undefined,
312
+ 'open': open,
313
+ 'close': last,
314
+ 'last': last,
315
+ 'previousClose': undefined,
316
+ 'change': undefined,
317
+ 'percentage': undefined,
318
+ 'average': undefined,
319
+ 'baseVolume': baseVolume,
320
+ 'quoteVolume': quoteVolume,
321
+ 'info': ticker,
322
+ }, market);
323
+ }
324
+ /**
325
+ * @method
326
+ * @name deepcoin#watchTrades
327
+ * @description watches information on multiple trades made in a market
328
+ * @see https://www.deepcoin.com/docs/publicWS/lastTransactions
329
+ * @param {string} symbol unified market symbol of the market trades were made in
330
+ * @param {int} [since] the earliest time in ms to fetch orders for
331
+ * @param {int} [limit] the maximum number of trade structures to retrieve
332
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
333
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
334
+ */
335
+ async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
336
+ await this.loadMarkets();
337
+ const market = this.market(symbol);
338
+ const messageHash = 'trades' + '::' + market['symbol'];
339
+ const trades = await this.watchPublic(market, messageHash, '2', params);
340
+ if (this.newUpdates) {
341
+ limit = trades.getLimit(symbol, limit);
342
+ }
343
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
344
+ }
345
+ /**
346
+ * @method
347
+ * @name deepcoin#unWatchTrades
348
+ * @description unWatches the list of most recent trades for a particular symbol
349
+ * @see https://www.deepcoin.com/docs/publicWS/lastTransactions
350
+ * @param {string} symbol unified symbol of the market to fetch trades for
351
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
352
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
353
+ */
354
+ async unWatchTrades(symbol, params = {}) {
355
+ await this.loadMarkets();
356
+ const market = this.market(symbol);
357
+ const messageHash = 'trades' + '::' + market['symbol'];
358
+ const subscription = {
359
+ 'topic': 'trades',
360
+ };
361
+ return await this.unWatchPublic(market, messageHash, '2', params, subscription);
362
+ }
363
+ handleTrades(client, message) {
364
+ //
365
+ // {
366
+ // "a": "PMT",
367
+ // "b": 0,
368
+ // "tt": 1760968672380,
369
+ // "mt": 1760968672380,
370
+ // "r": [
371
+ // {
372
+ // "d": {
373
+ // "TradeID": "1001056452325378",
374
+ // "I": "BTC/USDT",
375
+ // "D": "1",
376
+ // "P": 111061,
377
+ // "V": 0.00137,
378
+ // "T": 1760968672
379
+ // }
380
+ // }
381
+ // ]
382
+ // }
383
+ //
384
+ const response = this.safeList(message, 'r', []);
385
+ const first = this.safeDict(response, 0, {});
386
+ const data = this.safeDict(first, 'd', {});
387
+ const marketId = this.safeString(data, 'I');
388
+ const market = this.safeMarket(marketId, undefined, '/');
389
+ const symbol = this.safeSymbol(marketId, market);
390
+ if (!(symbol in this.trades)) {
391
+ const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
392
+ this.trades[symbol] = new ArrayCache(limit);
393
+ }
394
+ const strored = this.trades[symbol];
395
+ if (data !== undefined) {
396
+ const trade = this.parseWsTrade(data, market);
397
+ strored.append(trade);
398
+ }
399
+ const messageHash = 'trades' + '::' + symbol;
400
+ client.resolve(strored, messageHash);
401
+ }
402
+ parseWsTrade(trade, market = undefined) {
403
+ //
404
+ // watchTrades
405
+ // {
406
+ // "TradeID": "1001056452325378",
407
+ // "I": "BTC/USDT",
408
+ // "D": "1",
409
+ // "P": 111061,
410
+ // "V": 0.00137,
411
+ // "T": 1760968672
412
+ // }
413
+ //
414
+ // watchMyTrades
415
+ // {
416
+ // "A": "9256245",
417
+ // "CC": "USDT",
418
+ // "CP": 0,
419
+ // "D": "0",
420
+ // "F": 0.152,
421
+ // "I": "DOGE/USDT",
422
+ // "IT": 1761048103,
423
+ // "M": "9256245",
424
+ // "OS": "1001437462198486",
425
+ // "P": 0.19443,
426
+ // "T": 14.77668,
427
+ // "TI": "1001056459096708",
428
+ // "TT": 1761048103,
429
+ // "V": 76,
430
+ // "f": "DOGE",
431
+ // "l": 1,
432
+ // "m": "1",
433
+ // "o": "0"
434
+ // }
435
+ //
436
+ const direction = this.safeString(trade, 'D');
437
+ const timestamp = this.safeTimestamp2(trade, 'TT', 'T');
438
+ const matchRole = this.safeString(trade, 'm');
439
+ let fee = undefined;
440
+ const feeCost = this.safeString(trade, 'F');
441
+ if (feeCost !== undefined) {
442
+ fee = {
443
+ 'cost': feeCost,
444
+ 'currency': this.safeCurrencyCode(this.safeString(trade, 'f')),
445
+ };
446
+ }
447
+ return this.safeTrade({
448
+ 'info': trade,
449
+ 'timestamp': timestamp,
450
+ 'datetime': this.iso8601(timestamp),
451
+ 'symbol': market['symbol'],
452
+ 'id': this.safeString2(trade, 'TradeID', 'TI'),
453
+ 'order': this.safeString(trade, 'OS'),
454
+ 'type': undefined,
455
+ 'takerOrMaker': this.handleTakerOrMaker(matchRole),
456
+ 'side': this.parseTradeSide(direction),
457
+ 'price': this.safeString(trade, 'P'),
458
+ 'amount': this.safeString(trade, 'V'),
459
+ 'cost': this.safeString(trade, 'T'),
460
+ 'fee': fee,
461
+ }, market);
462
+ }
463
+ parseTradeSide(direction) {
464
+ const sides = {
465
+ '0': 'buy',
466
+ '1': 'sell',
467
+ };
468
+ return this.safeString(sides, direction, direction);
469
+ }
470
+ handleTakerOrMaker(matchRole) {
471
+ const roles = {
472
+ '0': 'maker',
473
+ '1': 'taker',
474
+ };
475
+ return this.safeString(roles, matchRole, matchRole);
476
+ }
477
+ /**
478
+ * @method
479
+ * @name deepcoin#watchOHLCV
480
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
481
+ * @see https://www.deepcoin.com/docs/publicWS/KLines
482
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
483
+ * @param {string} [timeframe] the length of time each candle represents
484
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
485
+ * @param {int} [limit] the maximum amount of candles to fetch
486
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
487
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
488
+ */
489
+ async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
490
+ await this.loadMarkets();
491
+ const market = this.market(symbol);
492
+ symbol = market['symbol'];
493
+ const timeframes = this.safeDict(this.options, 'timeframes', {});
494
+ const interval = this.safeString(timeframes, timeframe, timeframe);
495
+ const messageHash = 'ohlcv' + '::' + symbol + '::' + timeframe;
496
+ const suffix = '_' + interval;
497
+ const ohlcv = await this.watchPublic(market, messageHash, '11', params, suffix);
498
+ if (this.newUpdates) {
499
+ limit = ohlcv.getLimit(symbol, limit);
500
+ }
501
+ return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
502
+ }
503
+ /**
504
+ * @method
505
+ * @name deepcoin#unWatchOHLCV
506
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
507
+ * @see https://docs.backpack.exchange/#tag/Streams/Public/K-Line
508
+ * @param {string} symbol unified symbol of the market to fetch OHLCV data for
509
+ * @param {string} [timeframe] the length of time each candle represents
510
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
511
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
512
+ */
513
+ async unWatchOHLCV(symbol, timeframe = '1m', params = {}) {
514
+ await this.loadMarkets();
515
+ const market = this.market(symbol);
516
+ symbol = market['symbol'];
517
+ const timeframes = this.safeDict(this.options, 'timeframes', {});
518
+ const interval = this.safeString(timeframes, timeframe, timeframe);
519
+ const messageHash = 'ohlcv' + '::' + symbol + '::' + timeframe;
520
+ const suffix = '_' + interval;
521
+ const subscription = {
522
+ 'topic': 'ohlcv',
523
+ 'symbolsAndTimeframes': [[symbol, timeframe]],
524
+ };
525
+ return await this.unWatchPublic(market, messageHash, '11', params, subscription, suffix);
526
+ }
527
+ handleOHLCV(client, message) {
528
+ //
529
+ // {
530
+ // "a": "PK",
531
+ // "tt": 1760972831580,
532
+ // "mt": 1760972831580,
533
+ // "r": [
534
+ // {
535
+ // "d": {
536
+ // "I": "BTC/USDT",
537
+ // "P": "1m",
538
+ // "B": 1760972820,
539
+ // "O": 111373,
540
+ // "C": 111382.9,
541
+ // "H": 111382.9,
542
+ // "L": 111373,
543
+ // "V": 0.2414172,
544
+ // "M": 26888.19693324
545
+ // },
546
+ // "t": "LK"
547
+ // }
548
+ // ]
549
+ // }
550
+ //
551
+ const response = this.safeList(message, 'r', []);
552
+ const first = this.safeDict(response, 0, {});
553
+ const data = this.safeDict(first, 'd', {});
554
+ const marketId = this.safeString(data, 'I');
555
+ const market = this.safeMarket(marketId, undefined, '/');
556
+ const symbol = this.safeSymbol(marketId, market);
557
+ const interval = this.safeString(data, 'P');
558
+ const timeframe = this.findTimeframe(interval);
559
+ if (!(symbol in this.ohlcvs)) {
560
+ this.ohlcvs[symbol] = {};
561
+ }
562
+ if (!(timeframe in this.ohlcvs[symbol])) {
563
+ const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
564
+ this.ohlcvs[symbol][timeframe] = new ArrayCacheByTimestamp(limit);
565
+ }
566
+ const stored = this.ohlcvs[symbol][timeframe];
567
+ if (data !== undefined) {
568
+ const ohlcv = this.parseWsOHLCV(data, market);
569
+ stored.append(ohlcv);
570
+ }
571
+ const messageHash = 'ohlcv' + '::' + symbol + '::' + timeframe;
572
+ client.resolve(stored, messageHash);
573
+ }
574
+ parseWsOHLCV(ohlcv, market = undefined) {
575
+ //
576
+ // {
577
+ // "I": "BTC/USDT",
578
+ // "P": "1m",
579
+ // "B": 1760972820,
580
+ // "O": 111373,
581
+ // "C": 111382.9,
582
+ // "H": 111382.9,
583
+ // "L": 111373,
584
+ // "V": 0.2414172,
585
+ // "M": 26888.19693324
586
+ // }
587
+ //
588
+ return [
589
+ this.safeTimestamp(ohlcv, 'B'),
590
+ this.safeNumber(ohlcv, 'O'),
591
+ this.safeNumber(ohlcv, 'H'),
592
+ this.safeNumber(ohlcv, 'L'),
593
+ this.safeNumber(ohlcv, 'C'),
594
+ this.safeNumber(ohlcv, 'V'),
595
+ ];
596
+ }
597
+ /**
598
+ * @method
599
+ * @name deepcoin#watchOrderBook
600
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
601
+ * @see https://www.deepcoin.com/docs/publicWS/25LevelIncrementalMarketData
602
+ * @param {string} symbol unified symbol of the market to fetch the order book for
603
+ * @param {int} [limit] the maximum amount of order book entries to return.
604
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
605
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
606
+ */
607
+ async watchOrderBook(symbol, limit = undefined, params = {}) {
608
+ await this.loadMarkets();
609
+ const market = this.market(symbol);
610
+ const messageHash = 'orderbook' + '::' + market['symbol'];
611
+ const suffix = '_0.1';
612
+ const orderbook = await this.watchPublic(market, messageHash, '25', params, suffix);
613
+ return orderbook.limit();
614
+ }
615
+ /**
616
+ * @method
617
+ * @name deepcoin#unWatchOrderBook
618
+ * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
619
+ * @see https://www.deepcoin.com/docs/publicWS/25LevelIncrementalMarketData
620
+ * @param {string} symbol unified array of symbols
621
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
622
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
623
+ */
624
+ async unWatchOrderBook(symbol, params = {}) {
625
+ await this.loadMarkets();
626
+ const market = this.market(symbol);
627
+ const messageHash = 'orderbook' + '::' + market['symbol'];
628
+ const suffix = '_0.1';
629
+ const subscription = {
630
+ 'topic': 'orderbook',
631
+ };
632
+ return await this.unWatchPublic(market, messageHash, '25', params, subscription, suffix);
633
+ }
634
+ handleOrderBook(client, message) {
635
+ //
636
+ // {
637
+ // "a": "PMO",
638
+ // "t": "i", // i - update, f - snapshot
639
+ // "r": [
640
+ // {
641
+ // "d": { "I": "ETH/USDT", "D": "1", "P": 4021, "V": 54.39979 }
642
+ // },
643
+ // {
644
+ // "d": { "I": "ETH/USDT", "D": "0", "P": 4021.1, "V": 49.56724 }
645
+ // }
646
+ // ],
647
+ // "tt": 1760975816446,
648
+ // "mt": 1760975816446
649
+ // }
650
+ //
651
+ const response = this.safeList(message, 'r', []);
652
+ const first = this.safeDict(response, 0, {});
653
+ const data = this.safeDict(first, 'd', {});
654
+ const marketId = this.safeString(data, 'I');
655
+ const market = this.safeMarket(marketId, undefined, '/');
656
+ const symbol = this.safeSymbol(marketId, market);
657
+ if (!(symbol in this.orderbooks)) {
658
+ this.orderbooks[symbol] = this.orderBook();
659
+ }
660
+ const orderbook = this.orderbooks[symbol];
661
+ const type = this.safeString(message, 't');
662
+ if (orderbook['timestamp'] === undefined) {
663
+ if (type === 'f') {
664
+ // snapshot
665
+ this.handleOrderBookSnapshot(client, message);
666
+ }
667
+ else {
668
+ // cache the updates until the snapshot is received
669
+ orderbook.cache.push(message);
670
+ }
671
+ }
672
+ else {
673
+ this.handleOrderBookMessage(client, message, orderbook);
674
+ const messageHash = 'orderbook' + '::' + symbol;
675
+ client.resolve(orderbook, messageHash);
676
+ }
677
+ }
678
+ handleOrderBookSnapshot(client, message) {
679
+ const entries = this.safeList(message, 'r', []);
680
+ const first = this.safeDict(entries, 0, {});
681
+ const data = this.safeDict(first, 'd', {});
682
+ const marketId = this.safeString(data, 'I');
683
+ const market = this.safeMarket(marketId, undefined, '/');
684
+ const symbol = this.safeSymbol(marketId, market);
685
+ const orderbook = this.orderbooks[symbol];
686
+ const orderedEntries = {
687
+ 'bids': [],
688
+ 'asks': [],
689
+ };
690
+ for (let i = 0; i < entries.length; i++) {
691
+ const entry = entries[i];
692
+ const entryData = this.safeDict(entry, 'd', {});
693
+ const side = this.safeString(entryData, 'D');
694
+ const price = this.safeNumber(entryData, 'P');
695
+ const volume = this.safeNumber(entryData, 'V');
696
+ if (side === '0') {
697
+ // bid
698
+ orderedEntries['bids'].push([price, volume]);
699
+ }
700
+ else if (side === '1') {
701
+ // ask
702
+ orderedEntries['asks'].push([price, volume]);
703
+ }
704
+ }
705
+ const timestamp = this.safeInteger(message, 'mt');
706
+ const snapshot = this.parseOrderBook(orderedEntries, symbol, timestamp);
707
+ orderbook.reset(snapshot);
708
+ const cachedMessages = orderbook.cache;
709
+ for (let j = 0; j < cachedMessages.length; j++) {
710
+ const cachedMessage = cachedMessages[j];
711
+ this.handleOrderBookMessage(client, cachedMessage, orderbook);
712
+ }
713
+ orderbook.cache = [];
714
+ const messageHash = 'orderbook' + '::' + symbol;
715
+ client.resolve(orderbook, messageHash);
716
+ }
717
+ handleOrderBookMessage(client, message, orderbook) {
718
+ // {
719
+ // "a": "PMO",
720
+ // "t": "i", // i - update, f - snapshot
721
+ // "r": [
722
+ // {
723
+ // "d": { "I": "ETH/USDT", "D": "1", "P": 4021, "V": 54.39979 }
724
+ // },
725
+ // {
726
+ // "d": { "I": "ETH/USDT", "D": "0", "P": 4021.1, "V": 49.56724 }
727
+ // }
728
+ // ],
729
+ // "tt": 1760975816446,
730
+ // "mt": 1760975816446
731
+ // }
732
+ //
733
+ const timestamp = this.safeInteger(message, 'mt');
734
+ if (timestamp > orderbook['timestamp']) {
735
+ const response = this.safeList(message, 'r', []);
736
+ this.handleDeltas(orderbook, response);
737
+ orderbook['timestamp'] = timestamp;
738
+ orderbook['datetime'] = this.iso8601(timestamp);
739
+ }
740
+ }
741
+ handleDelta(orderbook, entry) {
742
+ const data = this.safeDict(entry, 'd', {});
743
+ const bids = orderbook['bids'];
744
+ const asks = orderbook['asks'];
745
+ const side = this.safeString(data, 'D');
746
+ const price = this.safeNumber(data, 'P');
747
+ const volume = this.safeNumber(data, 'V');
748
+ if (side === '0') {
749
+ // bid
750
+ bids.store(price, volume);
751
+ }
752
+ else if (side === '1') {
753
+ // ask
754
+ asks.store(price, volume);
755
+ }
756
+ }
757
+ /**
758
+ * @method
759
+ * @name deepcoin#watchMyTrades
760
+ * @description watches information on multiple trades made by the user
761
+ * @see https://www.deepcoin.com/docs/privateWS/Trade
762
+ * @param {string} symbol unified market symbol of the market orders were made in
763
+ * @param {int} [since] the earliest time in ms to fetch orders for
764
+ * @param {int} [limit] the maximum number of order structures to retrieve
765
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
766
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
767
+ */
768
+ async watchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
769
+ let messageHash = 'myTrades';
770
+ await this.loadMarkets();
771
+ if (symbol !== undefined) {
772
+ symbol = this.symbol(symbol);
773
+ messageHash += '::' + symbol;
774
+ }
775
+ const trades = await this.watchPrivate(messageHash, params);
776
+ if (this.newUpdates) {
777
+ limit = trades.getLimit(symbol, limit);
778
+ }
779
+ return this.filterBySymbolSinceLimit(trades, symbol, since, limit, true);
780
+ }
781
+ handleMyTrade(client, message) {
782
+ //
783
+ // {
784
+ // "action": "PushTrade",
785
+ // "result": [
786
+ // {
787
+ // "table": "Trade",
788
+ // "data": {
789
+ // "A": "9256245",
790
+ // "CC": "USDT",
791
+ // "CP": 0,
792
+ // "D": "0",
793
+ // "F": 0.152,
794
+ // "I": "DOGE/USDT",
795
+ // "IT": 1761048103,
796
+ // "M": "9256245",
797
+ // "OS": "1001437462198486",
798
+ // "P": 0.19443,
799
+ // "T": 14.77668,
800
+ // "TI": "1001056459096708",
801
+ // "TT": 1761048103,
802
+ // "V": 76,
803
+ // "f": "DOGE",
804
+ // "l": 1,
805
+ // "m": "1",
806
+ // "o": "0"
807
+ // }
808
+ // }
809
+ // ]
810
+ // }
811
+ //
812
+ const result = this.safeList(message, 'result', []);
813
+ const first = this.safeDict(result, 0, {});
814
+ const data = this.safeDict(first, 'data', {});
815
+ const marketId = this.safeString(data, 'I');
816
+ const market = this.safeMarket(marketId, undefined, '/');
817
+ const symbol = this.safeSymbol(marketId, market);
818
+ const messageHash = 'myTrades';
819
+ const symbolMessageHash = messageHash + '::' + symbol;
820
+ if ((messageHash in client.futures) || (symbolMessageHash in client.futures)) {
821
+ if (this.myTrades === undefined) {
822
+ const limit = this.safeInteger(this.options, 'tradesLimit', 1000);
823
+ this.myTrades = new ArrayCacheBySymbolById(limit);
824
+ }
825
+ const stored = this.myTrades;
826
+ const parsed = this.parseWsTrade(data, market);
827
+ stored.append(parsed);
828
+ client.resolve(stored, messageHash);
829
+ client.resolve(stored, symbolMessageHash);
830
+ }
831
+ }
832
+ /**
833
+ * @method
834
+ * @name deepcoin#watchOrders
835
+ * @description watches information on multiple orders made by the user
836
+ * @see https://www.deepcoin.com/docs/privateWS/order
837
+ * @param {string} symbol unified market symbol of the market orders were made in
838
+ * @param {int} [since] the earliest time in ms to fetch orders for
839
+ * @param {int} [limit] the maximum number of order structures to retrieve
840
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
841
+ * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
842
+ */
843
+ async watchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
844
+ let messageHash = 'orders';
845
+ await this.loadMarkets();
846
+ if (symbol !== undefined) {
847
+ symbol = this.symbol(symbol);
848
+ messageHash += '::' + symbol;
849
+ }
850
+ const orders = await this.watchPrivate(messageHash, params);
851
+ if (this.newUpdates) {
852
+ limit = orders.getLimit(symbol, limit);
853
+ }
854
+ return this.filterBySymbolSinceLimit(orders, symbol, since, limit, true);
855
+ }
856
+ handleOrder(client, message) {
857
+ //
858
+ // {
859
+ // "action": "PushOrder",
860
+ // "result": [
861
+ // {
862
+ // "table": "Order",
863
+ // "data": {
864
+ // "D": "0",
865
+ // "I": "DOGE/USDT",
866
+ // "IT": 1761051006,
867
+ // "L": "1001437480817468",
868
+ // "OPT": "4",
869
+ // "OS": "1001437480817468",
870
+ // "OT": "0",
871
+ // "Or": "1",
872
+ // "P": 0.19537,
873
+ // "T": 14.84128,
874
+ // "U": 1761051006,
875
+ // "V": 76,
876
+ // "VT": 76,
877
+ // "i": 1,
878
+ // "l": 1,
879
+ // "o": "0",
880
+ // "p": "0",
881
+ // "t": 0.19528
882
+ // }
883
+ // }
884
+ // ]
885
+ // }
886
+ //
887
+ const result = this.safeList(message, 'result', []);
888
+ const first = this.safeDict(result, 0, {});
889
+ const data = this.safeDict(first, 'data', {});
890
+ const marketId = this.safeString(data, 'I');
891
+ const market = this.safeMarket(marketId, undefined, '/');
892
+ const symbol = this.safeSymbol(marketId, market);
893
+ const messageHash = 'orders';
894
+ const symbolMessageHash = messageHash + '::' + symbol;
895
+ if ((messageHash in client.futures) || (symbolMessageHash in client.futures)) {
896
+ if (this.orders === undefined) {
897
+ const limit = this.safeInteger(this.options, 'ordersLimit', 1000);
898
+ this.orders = new ArrayCacheBySymbolById(limit);
899
+ }
900
+ const parsed = this.parseWsOrder(data, market);
901
+ this.orders.append(parsed);
902
+ client.resolve(this.orders, messageHash);
903
+ client.resolve(this.orders, symbolMessageHash);
904
+ }
905
+ }
906
+ parseWsOrder(order, market = undefined) {
907
+ //
908
+ // {
909
+ // "D": "0",
910
+ // "I": "DOGE/USDT",
911
+ // "IT": 1761051006,
912
+ // "L": "1001437480817468",
913
+ // "OPT": "4",
914
+ // "OS": "1001437480817468",
915
+ // "OT": "0",
916
+ // "Or": "1",
917
+ // "P": 0.19537,
918
+ // "T": 14.84128,
919
+ // "U": 1761051006,
920
+ // "V": 76,
921
+ // "VT": 76,
922
+ // "i": 1,
923
+ // "l": 1,
924
+ // "o": "0",
925
+ // "p": "0",
926
+ // "t": 0.19528
927
+ // }
928
+ //
929
+ const state = this.safeString(order, 'Or');
930
+ const timestamp = this.safeTimestamp(order, 'IT');
931
+ const direction = this.safeString(order, 'D');
932
+ return this.safeOrder({
933
+ 'id': this.safeString(order, 'OS'),
934
+ 'clientOrderId': undefined,
935
+ 'datetime': this.iso8601(timestamp),
936
+ 'timestamp': timestamp,
937
+ 'lastTradeTimestamp': undefined,
938
+ 'lastUpdateTimestamp': this.safeTimestamp(order, 'U'),
939
+ 'status': this.parseWsOrderStatus(state),
940
+ 'symbol': market['symbol'],
941
+ 'type': undefined,
942
+ 'timeInForce': undefined,
943
+ 'side': this.parseTradeSide(direction),
944
+ 'price': this.safeString(order, 'P'),
945
+ 'average': this.safeString(order, 't'),
946
+ 'amount': this.safeString(order, 'V'),
947
+ 'filled': this.safeString(order, 'VT'),
948
+ 'remaining': undefined,
949
+ 'triggerPrice': undefined,
950
+ 'takeProfitPrice': this.safeString(order, 'TPT'),
951
+ 'stopLossPrice': this.safeString(order, 'SLT'),
952
+ 'cost': this.safeString(order, 'T'),
953
+ 'trades': undefined,
954
+ 'fee': undefined,
955
+ 'reduceOnly': undefined,
956
+ 'postOnly': undefined,
957
+ 'info': order,
958
+ }, market);
959
+ }
960
+ parseWsOrderStatus(status) {
961
+ const statuses = {
962
+ '1': 'closed',
963
+ '4': 'open',
964
+ '6': 'canceled',
965
+ };
966
+ return this.safeString(statuses, status, status);
967
+ }
968
+ /**
969
+ * @method
970
+ * @name deepcoin#watchPositions
971
+ * @description watch all open positions
972
+ * @see https://www.deepcoin.com/docs/privateWS/Position
973
+ * @param {string[]} [symbols] list of unified market symbols to watch positions for
974
+ * @param {int} [since] the earliest time in ms to fetch positions for
975
+ * @param {int} [limit] the maximum number of positions to retrieve
976
+ * @param {object} params extra parameters specific to the exchange API endpoint
977
+ * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
978
+ */
979
+ async watchPositions(symbols = undefined, since = undefined, limit = undefined, params = {}) {
980
+ await this.loadMarkets();
981
+ const listenKey = await this.authenticate();
982
+ symbols = this.marketSymbols(symbols);
983
+ const messageHash = 'positions';
984
+ const messageHashes = [];
985
+ if (symbols !== undefined) {
986
+ for (let i = 0; i < symbols.length; i++) {
987
+ const symbol = symbols[i];
988
+ const symbolMessageHash = messageHash + '::' + symbol;
989
+ messageHashes.push(symbolMessageHash);
990
+ }
991
+ }
992
+ else {
993
+ messageHashes.push(messageHash);
994
+ }
995
+ const url = this.urls['api']['ws']['private'] + '?listenKey=' + listenKey;
996
+ const positions = await this.watchMultiple(url, messageHashes, params, ['private']);
997
+ if (this.newUpdates) {
998
+ return positions;
999
+ }
1000
+ return this.filterBySymbolsSinceLimit(this.positions, symbols, since, limit, true);
1001
+ }
1002
+ handlePosition(client, message) {
1003
+ //
1004
+ // {
1005
+ // "action": "PushPosition",
1006
+ // "result": [
1007
+ // {
1008
+ // "table": "Position",
1009
+ // "data": {
1010
+ // "A": "9256245",
1011
+ // "CP": 0,
1012
+ // "I": "DOGE/USDT",
1013
+ // "M": "9256245",
1014
+ // "OP": 0.198845,
1015
+ // "Po": 151.696,
1016
+ // "U": 1761058213,
1017
+ // "i": 1,
1018
+ // "l": 1,
1019
+ // "p": "0",
1020
+ // "u": 0
1021
+ // }
1022
+ // }
1023
+ // ]
1024
+ // }
1025
+ //
1026
+ const result = this.safeList(message, 'result', []);
1027
+ const first = this.safeDict(result, 0, {});
1028
+ const data = this.safeDict(first, 'data', {});
1029
+ const marketId = this.safeString(data, 'I');
1030
+ const market = this.safeMarket(marketId, undefined, '/');
1031
+ const symbol = this.safeSymbol(marketId, market);
1032
+ const messageHash = 'positions';
1033
+ const symbolMessageHash = messageHash + '::' + symbol;
1034
+ if ((messageHash in client.futures) || (symbolMessageHash in client.futures)) {
1035
+ if (this.positions === undefined) {
1036
+ this.positions = new ArrayCacheBySymbolBySide();
1037
+ }
1038
+ const parsed = this.parseWsPosition(data, market);
1039
+ this.positions.append(parsed);
1040
+ client.resolve(this.positions, messageHash);
1041
+ client.resolve(this.positions, symbolMessageHash);
1042
+ }
1043
+ }
1044
+ parseWsPosition(position, market = undefined) {
1045
+ //
1046
+ // {
1047
+ // "A": "9256245",
1048
+ // "CP": 0,
1049
+ // "I": "DOGE/USDT",
1050
+ // "M": "9256245",
1051
+ // "OP": 0.198845,
1052
+ // "Po": 151.696,
1053
+ // "U": 1761058213,
1054
+ // "i": 1,
1055
+ // "l": 1,
1056
+ // "p": "0",
1057
+ // "u": 0
1058
+ // }
1059
+ //
1060
+ const timestamp = this.safeInteger(position, 'U');
1061
+ const direction = this.safeString(position, 'p');
1062
+ const marginMode = this.safeString(position, 'i');
1063
+ return this.safePosition({
1064
+ 'symbol': market['symbol'],
1065
+ 'id': undefined,
1066
+ 'timestamp': timestamp,
1067
+ 'datetime': this.iso8601(timestamp),
1068
+ 'contracts': this.safeString(position, 'Po'),
1069
+ 'contractSize': undefined,
1070
+ 'side': this.parsePositionSide(direction),
1071
+ 'notional': undefined,
1072
+ 'leverage': this.omitZero(this.safeString(position, 'l')),
1073
+ 'unrealizedPnl': undefined,
1074
+ 'realizedPnl': undefined,
1075
+ 'collateral': undefined,
1076
+ 'entryPrice': this.safeString(position, 'OP'),
1077
+ 'markPrice': undefined,
1078
+ 'liquidationPrice': undefined,
1079
+ 'marginMode': this.parseWsMarginMode(marginMode),
1080
+ 'hedged': true,
1081
+ 'maintenanceMargin': this.safeString(position, 'u'),
1082
+ 'maintenanceMarginPercentage': undefined,
1083
+ 'initialMargin': undefined,
1084
+ 'initialMarginPercentage': undefined,
1085
+ 'marginRatio': undefined,
1086
+ 'lastUpdateTimestamp': undefined,
1087
+ 'lastPrice': undefined,
1088
+ 'stopLossPrice': undefined,
1089
+ 'takeProfitPrice': undefined,
1090
+ 'percentage': undefined,
1091
+ 'info': position,
1092
+ });
1093
+ }
1094
+ parsePositionSide(direction) {
1095
+ if (direction === undefined) {
1096
+ return direction;
1097
+ }
1098
+ const directions = {
1099
+ '0': 'long',
1100
+ '1': 'short',
1101
+ };
1102
+ return this.safeString(directions, direction, direction);
1103
+ }
1104
+ parseWsMarginMode(marginMode) {
1105
+ if (marginMode === undefined) {
1106
+ return marginMode;
1107
+ }
1108
+ const modes = {
1109
+ '0': 'isolated',
1110
+ '1': 'cross',
1111
+ };
1112
+ return this.safeString(modes, marginMode, marginMode);
1113
+ }
1114
+ handleMessage(client, message) {
1115
+ if (message === 'pong') {
1116
+ this.handlePong(client, message);
1117
+ }
1118
+ else {
1119
+ const m = this.safeString(message, 'm');
1120
+ if ((m !== undefined) && (m !== 'Success')) {
1121
+ this.handleErrorMessage(client, message);
1122
+ }
1123
+ const action = this.safeString2(message, 'a', 'action');
1124
+ if (action === 'RecvTopicAction') {
1125
+ this.handleSubscriptionStatus(client, message);
1126
+ }
1127
+ else if (action === 'PO') {
1128
+ this.handleTicker(client, message);
1129
+ }
1130
+ else if (action === 'PMT') {
1131
+ this.handleTrades(client, message);
1132
+ }
1133
+ else if (action === 'PK') {
1134
+ this.handleOHLCV(client, message);
1135
+ }
1136
+ else if (action === 'PMO') {
1137
+ this.handleOrderBook(client, message);
1138
+ }
1139
+ else if (action === 'PushTrade') {
1140
+ this.handleMyTrade(client, message);
1141
+ }
1142
+ else if (action === 'PushOrder') {
1143
+ this.handleOrder(client, message);
1144
+ }
1145
+ else if (action === 'PushPosition') {
1146
+ this.handlePosition(client, message);
1147
+ }
1148
+ }
1149
+ }
1150
+ handleSubscriptionStatus(client, message) {
1151
+ //
1152
+ // {
1153
+ // "a": "RecvTopicAction",
1154
+ // "m": "Success",
1155
+ // "r": [
1156
+ // {
1157
+ // "d": {
1158
+ // "A": "0",
1159
+ // "L": 1,
1160
+ // "T": "7",
1161
+ // "F": "DeepCoin_BTC/USDT",
1162
+ // "R": -1
1163
+ // }
1164
+ // }
1165
+ // ]
1166
+ // }
1167
+ //
1168
+ const response = this.safeList(message, 'r', []);
1169
+ const first = this.safeDict(response, 0, {});
1170
+ const data = this.safeDict(first, 'd', {});
1171
+ const action = this.safeString(data, 'A'); // 1 = subscribe, 0 = unsubscribe
1172
+ if (action === '0') {
1173
+ const subscriptionsById = this.indexBy(client.subscriptions, 'id');
1174
+ const subId = this.safeInteger(data, 'L');
1175
+ const subscription = this.safeDict(subscriptionsById, subId, {}); // original watch subscription
1176
+ const subHash = this.safeString(subscription, 'subHash');
1177
+ const unsubHash = 'unsubscribe::' + subHash;
1178
+ const unsubsciption = this.safeDict(client.subscriptions, unsubHash, {}); // unWatch subscription
1179
+ this.handleUnSubscription(client, unsubsciption);
1180
+ }
1181
+ }
1182
+ handleUnSubscription(client, subscription) {
1183
+ const subHash = this.safeString(subscription, 'subHash');
1184
+ const unsubHash = this.safeString(subscription, 'unsubHash');
1185
+ this.cleanUnsubscription(client, subHash, unsubHash);
1186
+ this.cleanCache(subscription);
1187
+ }
1188
+ handleErrorMessage(client, message) {
1189
+ //
1190
+ // {
1191
+ // "a": "RecvTopicAction",
1192
+ // "m": "subscription cluster does not "exist": BTC/USD",
1193
+ // "r": [
1194
+ // {
1195
+ // "d": {
1196
+ // "A": "1",
1197
+ // "L": 1,
1198
+ // "T": "7",
1199
+ // "F": "DeepCoin_BTC/USD",
1200
+ // "R": -1
1201
+ // }
1202
+ // }
1203
+ // ]
1204
+ // }
1205
+ //
1206
+ const messageText = this.safeString(message, 'm', '');
1207
+ const response = this.safeList(message, 'r', []);
1208
+ const first = this.safeDict(response, 0, {});
1209
+ const data = this.safeDict(first, 'd', {});
1210
+ const requestId = this.safeInteger(data, 'L');
1211
+ const subscriptionsById = this.indexBy(client.subscriptions, 'id');
1212
+ const subscription = this.safeDict(subscriptionsById, requestId, {});
1213
+ const messageHash = this.safeString(subscription, 'subHash');
1214
+ const feedback = this.id + ' ' + this.json(message);
1215
+ try {
1216
+ this.throwExactlyMatchedException(this.exceptions['exact'], messageText, feedback);
1217
+ this.throwBroadlyMatchedException(this.exceptions['broad'], messageText, feedback);
1218
+ throw new ExchangeError(feedback);
1219
+ }
1220
+ catch (e) {
1221
+ client.reject(e, messageHash);
1222
+ }
1223
+ }
1224
+ }