ccxt 4.3.39 → 4.3.41

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 (81) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.min.js +3 -3
  3. package/dist/cjs/ccxt.js +1 -1
  4. package/dist/cjs/src/binance.js +4 -0
  5. package/dist/cjs/src/bitfinex2.js +1 -1
  6. package/dist/cjs/src/bithumb.js +9 -1
  7. package/dist/cjs/src/bitstamp.js +38 -2
  8. package/dist/cjs/src/coinlist.js +20 -1
  9. package/dist/cjs/src/coinmate.js +19 -3
  10. package/dist/cjs/src/coinone.js +1 -1
  11. package/dist/cjs/src/coinspot.js +13 -2
  12. package/dist/cjs/src/hitbtc.js +2 -2
  13. package/dist/cjs/src/independentreserve.js +33 -1
  14. package/dist/cjs/src/indodax.js +43 -2
  15. package/dist/cjs/src/okx.js +7 -0
  16. package/dist/cjs/src/pro/alpaca.js +5 -5
  17. package/dist/cjs/src/pro/ascendex.js +3 -3
  18. package/dist/cjs/src/pro/bingx.js +293 -47
  19. package/dist/cjs/src/pro/bitget.js +6 -5
  20. package/dist/cjs/src/pro/bitrue.js +3 -4
  21. package/dist/cjs/src/pro/currencycom.js +6 -5
  22. package/dist/cjs/src/pro/exmo.js +5 -6
  23. package/dist/cjs/src/pro/gemini.js +4 -3
  24. package/dist/cjs/src/pro/independentreserve.js +7 -7
  25. package/dist/cjs/src/pro/lbank.js +4 -4
  26. package/dist/cjs/src/pro/phemex.js +5 -5
  27. package/dist/cjs/src/pro/probit.js +4 -4
  28. package/dist/cjs/src/pro/upbit.js +318 -2
  29. package/dist/cjs/src/pro/wazirx.js +12 -12
  30. package/dist/cjs/src/upbit.js +17 -9
  31. package/dist/cjs/src/woo.js +6 -2
  32. package/dist/cjs/src/woofipro.js +8 -2
  33. package/js/ccxt.d.ts +1 -1
  34. package/js/ccxt.js +1 -1
  35. package/js/src/abstract/binance.d.ts +2 -0
  36. package/js/src/abstract/binancecoinm.d.ts +2 -0
  37. package/js/src/abstract/binanceus.d.ts +2 -0
  38. package/js/src/abstract/binanceusdm.d.ts +2 -0
  39. package/js/src/abstract/okx.d.ts +7 -0
  40. package/js/src/binance.js +4 -0
  41. package/js/src/bitfinex2.js +1 -1
  42. package/js/src/bithumb.d.ts +2 -2
  43. package/js/src/bithumb.js +9 -1
  44. package/js/src/bitstamp.d.ts +2 -2
  45. package/js/src/bitstamp.js +38 -2
  46. package/js/src/coinlist.d.ts +1 -1
  47. package/js/src/coinlist.js +20 -1
  48. package/js/src/coinmate.d.ts +1 -3
  49. package/js/src/coinmate.js +19 -3
  50. package/js/src/coinone.d.ts +1 -1
  51. package/js/src/coinone.js +1 -1
  52. package/js/src/coinspot.d.ts +1 -1
  53. package/js/src/coinspot.js +13 -2
  54. package/js/src/hitbtc.js +2 -2
  55. package/js/src/independentreserve.d.ts +1 -1
  56. package/js/src/independentreserve.js +33 -1
  57. package/js/src/indodax.d.ts +1 -1
  58. package/js/src/indodax.js +43 -2
  59. package/js/src/okx.js +7 -0
  60. package/js/src/pro/alpaca.js +5 -5
  61. package/js/src/pro/ascendex.js +3 -3
  62. package/js/src/pro/bingx.d.ts +6 -1
  63. package/js/src/pro/bingx.js +294 -48
  64. package/js/src/pro/bitget.js +6 -5
  65. package/js/src/pro/bitrue.js +3 -4
  66. package/js/src/pro/currencycom.js +6 -5
  67. package/js/src/pro/exmo.js +5 -6
  68. package/js/src/pro/gemini.js +4 -3
  69. package/js/src/pro/independentreserve.js +7 -7
  70. package/js/src/pro/lbank.js +4 -4
  71. package/js/src/pro/phemex.js +5 -5
  72. package/js/src/pro/probit.js +4 -4
  73. package/js/src/pro/upbit.d.ts +13 -1
  74. package/js/src/pro/upbit.js +319 -3
  75. package/js/src/pro/wazirx.js +12 -12
  76. package/js/src/upbit.js +17 -9
  77. package/js/src/woo.d.ts +1 -1
  78. package/js/src/woo.js +6 -2
  79. package/js/src/woofipro.d.ts +4 -2
  80. package/js/src/woofipro.js +8 -2
  81. package/package.json +1 -1
@@ -14,11 +14,13 @@ class bingx extends bingx$1 {
14
14
  'ws': true,
15
15
  'watchTrades': true,
16
16
  'watchOrderBook': true,
17
+ 'watchOrderBookForSymbols': true,
17
18
  'watchOHLCV': true,
19
+ 'watchOHLCVForSymbols': true,
18
20
  'watchOrders': true,
19
21
  'watchMyTrades': true,
20
22
  'watchTicker': true,
21
- 'watchTickers': false,
23
+ 'watchTickers': true,
22
24
  'watchBalance': true,
23
25
  },
24
26
  'urls': {
@@ -66,6 +68,14 @@ class bingx extends bingx$1 {
66
68
  'fetchBalanceSnapshot': true,
67
69
  'awaitBalanceSnapshot': false, // whether to wait for the balance snapshot before providing updates
68
70
  },
71
+ 'watchOrderBook': {
72
+ 'depth': 100,
73
+ 'interval': 500, // 100, 200, 500, 1000
74
+ },
75
+ 'watchOrderBookForSymbols': {
76
+ 'depth': 100,
77
+ 'interval': 500, // 100, 200, 500, 1000
78
+ },
69
79
  },
70
80
  'streaming': {
71
81
  'keepAlive': 1800000, // 30 minutes
@@ -89,16 +99,17 @@ class bingx extends bingx$1 {
89
99
  if (url === undefined) {
90
100
  throw new errors.BadRequest(this.id + ' watchTrades is not supported for ' + marketType + ' markets.');
91
101
  }
92
- const messageHash = market['id'] + '@ticker';
102
+ const subscriptionHash = market['id'] + '@ticker';
103
+ const messageHash = this.getMessageHash('ticker', market['symbol']);
93
104
  const uuid = this.uuid();
94
105
  const request = {
95
106
  'id': uuid,
96
- 'dataType': messageHash,
107
+ 'dataType': subscriptionHash,
97
108
  };
98
109
  if (marketType === 'swap') {
99
110
  request['reqType'] = 'sub';
100
111
  }
101
- return await this.watch(url, messageHash, this.extend(request, query), messageHash);
112
+ return await this.watch(url, messageHash, this.extend(request, query), subscriptionHash);
102
113
  }
103
114
  handleTicker(client, message) {
104
115
  //
@@ -164,8 +175,10 @@ class bingx extends bingx$1 {
164
175
  const symbol = market['symbol'];
165
176
  const ticker = this.parseWsTicker(data, market);
166
177
  this.tickers[symbol] = ticker;
167
- const messageHash = market['id'] + '@ticker';
168
- client.resolve(ticker, messageHash);
178
+ client.resolve(ticker, this.getMessageHash('ticker', symbol));
179
+ if (this.safeString(message, 'dataType') === 'all@ticker') {
180
+ client.resolve(ticker, this.getMessageHash('ticker'));
181
+ }
169
182
  }
170
183
  parseWsTicker(message, market = undefined) {
171
184
  //
@@ -217,6 +230,206 @@ class bingx extends bingx$1 {
217
230
  'info': message,
218
231
  }, market);
219
232
  }
233
+ async watchTickers(symbols = undefined, params = {}) {
234
+ /**
235
+ * @method
236
+ * @name bingx#watchTickers
237
+ * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for all markets of a specific list
238
+ * @see https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20to%2024-hour%20price%20changes%20of%20all%20trading%20pairs
239
+ * @param {string[]} symbols unified symbol of the market to watch the tickers for
240
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
241
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
242
+ */
243
+ await this.loadMarkets();
244
+ symbols = this.marketSymbols(symbols, undefined, true, true, false);
245
+ let firstMarket = undefined;
246
+ let marketType = undefined;
247
+ const symbolsDefined = (symbols !== undefined);
248
+ if (symbolsDefined) {
249
+ firstMarket = this.market(symbols[0]);
250
+ }
251
+ [marketType, params] = this.handleMarketTypeAndParams('watchTickers', firstMarket, params);
252
+ if (marketType === 'spot') {
253
+ throw new errors.NotSupported(this.id + ' watchTickers is not supported for spot markets yet');
254
+ }
255
+ const messageHashes = [];
256
+ const subscriptionHashes = ['all@ticker'];
257
+ if (symbolsDefined) {
258
+ for (let i = 0; i < symbols.length; i++) {
259
+ const symbol = symbols[i];
260
+ const market = this.market(symbol);
261
+ messageHashes.push(this.getMessageHash('ticker', market['symbol']));
262
+ }
263
+ }
264
+ else {
265
+ messageHashes.push(this.getMessageHash('ticker'));
266
+ }
267
+ const url = this.safeString(this.urls['api']['ws'], marketType);
268
+ const uuid = this.uuid();
269
+ const request = {
270
+ 'id': uuid,
271
+ 'dataType': 'all@ticker',
272
+ };
273
+ if (marketType === 'swap') {
274
+ request['reqType'] = 'sub';
275
+ }
276
+ const result = await this.watchMultiple(url, messageHashes, this.deepExtend(request, params), subscriptionHashes);
277
+ if (this.newUpdates) {
278
+ const newDict = {};
279
+ newDict[result['symbol']] = result;
280
+ return newDict;
281
+ }
282
+ return this.tickers;
283
+ }
284
+ async watchOrderBookForSymbols(symbols, limit = undefined, params = {}) {
285
+ /**
286
+ * @method
287
+ * @name bingx#watchOrderBookForSymbols
288
+ * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
289
+ * @see https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20Market%20Depth%20Data%20of%20all%20trading%20pairs
290
+ * @param {string[]} symbols unified array of symbols
291
+ * @param {int} [limit] the maximum amount of order book entries to return
292
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
293
+ * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
294
+ */
295
+ symbols = this.marketSymbols(symbols, undefined, true, true, false);
296
+ let firstMarket = undefined;
297
+ let marketType = undefined;
298
+ const symbolsDefined = (symbols !== undefined);
299
+ if (symbolsDefined) {
300
+ firstMarket = this.market(symbols[0]);
301
+ }
302
+ [marketType, params] = this.handleMarketTypeAndParams('watchOrderBookForSymbols', firstMarket, params);
303
+ if (marketType === 'spot') {
304
+ throw new errors.NotSupported(this.id + ' watchOrderBookForSymbols is not supported for spot markets yet');
305
+ }
306
+ limit = this.getOrderBookLimitByMarketType(marketType, limit);
307
+ let interval = undefined;
308
+ [interval, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'interval', 500);
309
+ this.checkRequiredArgument('watchOrderBookForSymbols', interval, 'interval', [100, 200, 500, 1000]);
310
+ const channelName = 'depth' + limit.toString() + '@' + interval.toString() + 'ms';
311
+ const subscriptionHash = 'all@' + channelName;
312
+ const messageHashes = [];
313
+ if (symbolsDefined) {
314
+ for (let i = 0; i < symbols.length; i++) {
315
+ const symbol = symbols[i];
316
+ const market = this.market(symbol);
317
+ messageHashes.push(this.getMessageHash('orderbook', market['symbol']));
318
+ }
319
+ }
320
+ else {
321
+ messageHashes.push(this.getMessageHash('orderbook'));
322
+ }
323
+ const url = this.safeString(this.urls['api']['ws'], marketType);
324
+ const uuid = this.uuid();
325
+ const request = {
326
+ 'id': uuid,
327
+ 'dataType': subscriptionHash,
328
+ };
329
+ if (marketType === 'swap') {
330
+ request['reqType'] = 'sub';
331
+ }
332
+ const subscriptionArgs = {
333
+ 'symbols': symbols,
334
+ 'limit': limit,
335
+ 'interval': interval,
336
+ 'params': params,
337
+ };
338
+ const orderbook = await this.watchMultiple(url, messageHashes, this.deepExtend(request, params), [subscriptionHash], subscriptionArgs);
339
+ return orderbook.limit();
340
+ }
341
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
342
+ /**
343
+ * @method
344
+ * @name bingx#watchOHLCVForSymbols
345
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
346
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
347
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
348
+ * @param {int} [limit] the maximum amount of candles to fetch
349
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
350
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
351
+ */
352
+ const symbolsLength = symbolsAndTimeframes.length;
353
+ if (symbolsLength !== 0 && !Array.isArray(symbolsAndTimeframes[0])) {
354
+ throw new errors.ArgumentsRequired(this.id + " watchOHLCVForSymbols() requires a an array like [['BTC/USDT:USDT', '1m'], ['LTC/USDT:USDT', '5m']]");
355
+ }
356
+ await this.loadMarkets();
357
+ const messageHashes = [];
358
+ let marketType = undefined;
359
+ let chosenTimeframe = undefined;
360
+ if (symbolsLength !== 0) {
361
+ let symbols = this.getListFromObjectValues(symbolsAndTimeframes, 0);
362
+ symbols = this.marketSymbols(symbols, undefined, true, true, false);
363
+ const firstMarket = this.market(symbols[0]);
364
+ [marketType, params] = this.handleMarketTypeAndParams('watchOrderBookForSymbols', firstMarket, params);
365
+ if (marketType === 'spot') {
366
+ throw new errors.NotSupported(this.id + ' watchOrderBookForSymbols is not supported for spot markets yet');
367
+ }
368
+ }
369
+ const marketOptions = this.safeDict(this.options, marketType);
370
+ const timeframes = this.safeDict(marketOptions, 'timeframes', {});
371
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
372
+ const symbolAndTimeframe = symbolsAndTimeframes[i];
373
+ const sym = symbolAndTimeframe[0];
374
+ const tf = symbolAndTimeframe[1];
375
+ const market = this.market(sym);
376
+ const rawTimeframe = this.safeString(timeframes, tf, tf);
377
+ if (chosenTimeframe === undefined) {
378
+ chosenTimeframe = rawTimeframe;
379
+ }
380
+ else if (chosenTimeframe !== rawTimeframe) {
381
+ throw new errors.BadRequest(this.id + ' watchOHLCVForSymbols requires all timeframes to be the same');
382
+ }
383
+ messageHashes.push(this.getMessageHash('ohlcv', market['symbol'], chosenTimeframe));
384
+ }
385
+ const subscriptionHash = 'all@kline_' + chosenTimeframe;
386
+ const url = this.safeString(this.urls['api']['ws'], marketType);
387
+ const uuid = this.uuid();
388
+ const request = {
389
+ 'id': uuid,
390
+ 'dataType': subscriptionHash,
391
+ };
392
+ if (marketType === 'swap') {
393
+ request['reqType'] = 'sub';
394
+ }
395
+ const subscriptionArgs = {
396
+ 'limit': limit,
397
+ 'params': params,
398
+ };
399
+ const [symbol, timeframe, candles] = await this.watchMultiple(url, messageHashes, request, [subscriptionHash], subscriptionArgs);
400
+ if (this.newUpdates) {
401
+ limit = candles.getLimit(symbol, limit);
402
+ }
403
+ const filtered = this.filterBySinceLimit(candles, since, limit, 0, true);
404
+ return this.createOHLCVObject(symbol, timeframe, filtered);
405
+ }
406
+ getOrderBookLimitByMarketType(marketType, limit = undefined) {
407
+ if (limit === undefined) {
408
+ limit = 100;
409
+ }
410
+ else {
411
+ if (marketType === 'swap' || marketType === 'future') {
412
+ limit = this.findNearestCeiling([5, 10, 20, 50, 100], limit);
413
+ }
414
+ else if (marketType === 'spot') {
415
+ limit = this.findNearestCeiling([20, 100], limit);
416
+ }
417
+ }
418
+ return limit;
419
+ }
420
+ getMessageHash(unifiedChannel, symbol = undefined, extra = undefined) {
421
+ let hash = unifiedChannel;
422
+ if (symbol !== undefined) {
423
+ hash += '::' + symbol;
424
+ }
425
+ else {
426
+ hash += 's'; // tickers, orderbooks, ohlcvs ...
427
+ }
428
+ if (extra !== undefined) {
429
+ hash += '::' + extra;
430
+ }
431
+ return hash;
432
+ }
220
433
  async watchTrades(symbol, since = undefined, limit = undefined, params = {}) {
221
434
  /**
222
435
  * @method
@@ -352,35 +565,34 @@ class bingx extends bingx$1 {
352
565
  await this.loadMarkets();
353
566
  const market = this.market(symbol);
354
567
  const [marketType, query] = this.handleMarketTypeAndParams('watchOrderBook', market, params);
355
- if (limit === undefined) {
356
- limit = 100;
357
- }
358
- else {
359
- if (marketType === 'swap') {
360
- if ((limit !== 5) && (limit !== 10) && (limit !== 20) && (limit !== 50) && (limit !== 100)) {
361
- throw new errors.BadRequest(this.id + ' watchOrderBook() (swap) only supports limit 5, 10, 20, 50, and 100');
362
- }
363
- }
364
- else if (marketType === 'spot') {
365
- if ((limit !== 20) && (limit !== 100)) {
366
- throw new errors.BadRequest(this.id + ' watchOrderBook() (spot) only supports limit 20, and 100');
367
- }
368
- }
369
- }
568
+ limit = this.getOrderBookLimitByMarketType(marketType, limit);
569
+ let channelName = 'depth' + limit.toString();
370
570
  const url = this.safeValue(this.urls['api']['ws'], marketType);
371
571
  if (url === undefined) {
372
572
  throw new errors.BadRequest(this.id + ' watchOrderBook is not supported for ' + marketType + ' markets.');
373
573
  }
374
- const messageHash = market['id'] + '@depth' + limit.toString();
574
+ let interval = undefined;
575
+ if (marketType !== 'spot') {
576
+ [interval, params] = this.handleOptionAndParams(params, 'watchOrderBook', 'interval', 500);
577
+ this.checkRequiredArgument('watchOrderBook', interval, 'interval', [100, 200, 500, 1000]);
578
+ channelName = channelName + '@' + interval.toString() + 'ms';
579
+ }
580
+ const subscriptionHash = market['id'] + '@' + channelName;
581
+ const messageHash = this.getMessageHash('orderbook', market['symbol']);
375
582
  const uuid = this.uuid();
376
583
  const request = {
377
584
  'id': uuid,
378
- 'dataType': messageHash,
585
+ 'dataType': subscriptionHash,
379
586
  };
380
587
  if (marketType === 'swap') {
381
588
  request['reqType'] = 'sub';
382
589
  }
383
- const orderbook = await this.watch(url, messageHash, this.deepExtend(request, query), messageHash);
590
+ const subscriptionArgs = {
591
+ 'limit': limit,
592
+ 'interval': interval,
593
+ 'params': params,
594
+ };
595
+ const orderbook = await this.watch(url, messageHash, this.deepExtend(request, query), subscriptionHash, subscriptionArgs);
384
596
  return orderbook.limit();
385
597
  }
386
598
  handleDelta(bookside, delta) {
@@ -415,7 +627,7 @@ class bingx extends bingx$1 {
415
627
  //
416
628
  // {
417
629
  // "code": 0,
418
- // "dataType": "BTC-USDT@depth20",
630
+ // "dataType": "BTC-USDT@depth20@100ms", //or "all@depth20@100ms"
419
631
  // "data": {
420
632
  // "bids": [
421
633
  // [ '28852.9', "34.2621" ],
@@ -424,25 +636,39 @@ class bingx extends bingx$1 {
424
636
  // "asks": [
425
637
  // [ '28864.9', "23.4079" ],
426
638
  // ...
427
- // ]
639
+ // ],
640
+ // "symbol": "BTC-USDT", // this key exists only in "all" subscription
428
641
  // }
429
642
  // }
430
643
  //
431
- const data = this.safeValue(message, 'data', []);
432
- const messageHash = this.safeString(message, 'dataType');
433
- const marketId = messageHash.split('@')[0];
644
+ const data = this.safeDict(message, 'data', {});
645
+ const dataType = this.safeString(message, 'dataType');
646
+ const parts = dataType.split('@');
647
+ const firstPart = parts[0];
648
+ const isAllEndpoint = (firstPart === 'all');
649
+ const marketId = this.safeString(data, 'symbol', firstPart);
434
650
  const isSwap = client.url.indexOf('swap') >= 0;
435
651
  const marketType = isSwap ? 'swap' : 'spot';
436
652
  const market = this.safeMarket(marketId, undefined, undefined, marketType);
437
653
  const symbol = market['symbol'];
438
- let orderbook = this.safeValue(this.orderbooks, symbol);
439
- if (orderbook === undefined) {
440
- orderbook = this.orderBook();
654
+ if (this.safeValue(this.orderbooks, symbol) === undefined) {
655
+ // const limit = [ 5, 10, 20, 50, 100 ]
656
+ const subscriptionHash = dataType;
657
+ const subscription = client.subscriptions[subscriptionHash];
658
+ const limit = this.safeInteger(subscription, 'limit');
659
+ this.orderbooks[symbol] = this.orderBook({}, limit);
441
660
  }
661
+ const orderbook = this.orderbooks[symbol];
442
662
  const snapshot = this.parseOrderBook(data, symbol, undefined, 'bids', 'asks', 0, 1);
443
663
  orderbook.reset(snapshot);
444
664
  this.orderbooks[symbol] = orderbook;
665
+ const messageHash = this.getMessageHash('orderbook', symbol);
445
666
  client.resolve(orderbook, messageHash);
667
+ // resolve for "all"
668
+ if (isAllEndpoint) {
669
+ const messageHashForAll = this.getMessageHash('orderbook');
670
+ client.resolve(orderbook, messageHashForAll);
671
+ }
446
672
  }
447
673
  parseWsOHLCV(ohlcv, market = undefined) {
448
674
  //
@@ -513,34 +739,48 @@ class bingx extends bingx$1 {
513
739
  // ]
514
740
  // }
515
741
  //
516
- const data = this.safeValue(message, 'data', []);
742
+ const data = this.safeList(message, 'data', []);
517
743
  let candles = undefined;
518
744
  if (Array.isArray(data)) {
519
745
  candles = data;
520
746
  }
521
747
  else {
522
- candles = [this.safeValue(data, 'K', [])];
748
+ candles = [this.safeList(data, 'K', [])];
523
749
  }
524
- const messageHash = this.safeString(message, 'dataType');
525
- const timeframeId = messageHash.split('_')[1];
526
- const marketId = messageHash.split('@')[0];
750
+ const dataType = this.safeString(message, 'dataType');
527
751
  const isSwap = client.url.indexOf('swap') >= 0;
752
+ const parts = dataType.split('@');
753
+ const firstPart = parts[0];
754
+ const isAllEndpoint = (firstPart === 'all');
755
+ const marketId = this.safeString(message, 's', firstPart);
528
756
  const marketType = isSwap ? 'swap' : 'spot';
529
757
  const market = this.safeMarket(marketId, undefined, undefined, marketType);
530
758
  const symbol = market['symbol'];
531
759
  this.ohlcvs[symbol] = this.safeValue(this.ohlcvs, symbol, {});
532
- let stored = this.safeValue(this.ohlcvs[symbol], timeframeId);
533
- if (stored === undefined) {
534
- const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
535
- stored = new Cache.ArrayCacheByTimestamp(limit);
536
- this.ohlcvs[symbol][timeframeId] = stored;
760
+ const rawTimeframe = dataType.split('_')[1];
761
+ const marketOptions = this.safeDict(this.options, marketType);
762
+ const timeframes = this.safeDict(marketOptions, 'timeframes', {});
763
+ const unifiedTimeframe = this.findTimeframe(rawTimeframe, timeframes);
764
+ if (this.safeValue(this.ohlcvs[symbol], rawTimeframe) === undefined) {
765
+ const subscriptionHash = dataType;
766
+ const subscription = client.subscriptions[subscriptionHash];
767
+ const limit = this.safeInteger(subscription, 'limit');
768
+ this.ohlcvs[symbol][unifiedTimeframe] = new Cache.ArrayCacheByTimestamp(limit);
537
769
  }
770
+ const stored = this.ohlcvs[symbol][unifiedTimeframe];
538
771
  for (let i = 0; i < candles.length; i++) {
539
772
  const candle = candles[i];
540
773
  const parsed = this.parseWsOHLCV(candle, market);
541
774
  stored.append(parsed);
542
775
  }
543
- client.resolve(stored, messageHash);
776
+ const resolveData = [symbol, unifiedTimeframe, stored];
777
+ const messageHash = this.getMessageHash('ohlcv', symbol, unifiedTimeframe);
778
+ client.resolve(resolveData, messageHash);
779
+ // resolve for "all"
780
+ if (isAllEndpoint) {
781
+ const messageHashForAll = this.getMessageHash('ohlcv', undefined, unifiedTimeframe);
782
+ client.resolve(resolveData, messageHashForAll);
783
+ }
544
784
  }
545
785
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
546
786
  /**
@@ -565,17 +805,23 @@ class bingx extends bingx$1 {
565
805
  }
566
806
  const options = this.safeValue(this.options, marketType, {});
567
807
  const timeframes = this.safeValue(options, 'timeframes', {});
568
- const interval = this.safeString(timeframes, timeframe, timeframe);
569
- const messageHash = market['id'] + '@kline_' + interval;
808
+ const rawTimeframe = this.safeString(timeframes, timeframe, timeframe);
809
+ const messageHash = this.getMessageHash('ohlcv', market['symbol'], timeframe);
810
+ const subscriptionHash = market['id'] + '@kline_' + rawTimeframe;
570
811
  const uuid = this.uuid();
571
812
  const request = {
572
813
  'id': uuid,
573
- 'dataType': messageHash,
814
+ 'dataType': subscriptionHash,
574
815
  };
575
816
  if (marketType === 'swap') {
576
817
  request['reqType'] = 'sub';
577
818
  }
578
- const ohlcv = await this.watch(url, messageHash, this.extend(request, query), messageHash);
819
+ const subscriptionArgs = {
820
+ 'limit': limit,
821
+ 'params': params,
822
+ };
823
+ const result = await this.watch(url, messageHash, this.extend(request, query), subscriptionHash, subscriptionArgs);
824
+ const ohlcv = result[2];
579
825
  if (this.newUpdates) {
580
826
  limit = ohlcv.getLimit(symbol, limit);
581
827
  }
@@ -989,7 +989,7 @@ class bitget extends bitget$1 {
989
989
  [type, params] = this.handleMarketTypeAndParams('watchOrders', market, params);
990
990
  let subType = undefined;
991
991
  [subType, params] = this.handleSubTypeAndParams('watchOrders', market, params, 'linear');
992
- if ((type === 'spot') && (symbol === undefined)) {
992
+ if ((type === 'spot' || type === 'margin') && (symbol === undefined)) {
993
993
  throw new errors.ArgumentsRequired(this.id + ' watchOrders requires a symbol argument for ' + type + ' markets.');
994
994
  }
995
995
  if ((productType === undefined) && (type !== 'spot') && (symbol === undefined)) {
@@ -1012,7 +1012,7 @@ class bitget extends bitget$1 {
1012
1012
  if (isTrigger) {
1013
1013
  subscriptionHash = subscriptionHash + ':stop'; // we don't want to re-use the same subscription hash for stop orders
1014
1014
  }
1015
- const instId = (type === 'spot') ? marketId : 'default'; // different from other streams here the 'rest' id is required for spot markets, contract markets require default here
1015
+ const instId = (type === 'spot' || type === 'margin') ? marketId : 'default'; // different from other streams here the 'rest' id is required for spot markets, contract markets require default here
1016
1016
  let channel = isTrigger ? 'orders-algo' : 'orders';
1017
1017
  let marginMode = undefined;
1018
1018
  [marginMode, params] = this.handleMarginModeAndParams('watchOrders', params);
@@ -1072,9 +1072,10 @@ class bitget extends bitget$1 {
1072
1072
  // "ts": 1701923982497
1073
1073
  // }
1074
1074
  //
1075
- const arg = this.safeValue(message, 'arg', {});
1075
+ const arg = this.safeDict(message, 'arg', {});
1076
1076
  const channel = this.safeString(arg, 'channel');
1077
1077
  const instType = this.safeString(arg, 'instType');
1078
+ const argInstId = this.safeString(arg, 'instId');
1078
1079
  let marketType = undefined;
1079
1080
  if (instType === 'SPOT') {
1080
1081
  marketType = 'spot';
@@ -1100,7 +1101,7 @@ class bitget extends bitget$1 {
1100
1101
  const marketSymbols = {};
1101
1102
  for (let i = 0; i < data.length; i++) {
1102
1103
  const order = data[i];
1103
- const marketId = this.safeString(order, 'instId');
1104
+ const marketId = this.safeString(order, 'instId', argInstId);
1104
1105
  const market = this.safeMarket(marketId, undefined, undefined, marketType);
1105
1106
  const parsed = this.parseWsOrder(order, market);
1106
1107
  stored.append(parsed);
@@ -1311,7 +1312,7 @@ class bitget extends bitget$1 {
1311
1312
  totalAmount = this.safeString(order, 'size');
1312
1313
  cost = this.safeString(order, 'fillNotionalUsd');
1313
1314
  }
1314
- remaining = this.omitZero(Precise["default"].stringSub(totalAmount, totalFilled));
1315
+ remaining = Precise["default"].stringSub(totalAmount, totalFilled);
1315
1316
  return this.safeOrder({
1316
1317
  'info': order,
1317
1318
  'symbol': symbol,
@@ -346,13 +346,12 @@ class bitrue extends bitrue$1 {
346
346
  const symbol = market['symbol'];
347
347
  const timestamp = this.safeInteger(message, 'ts');
348
348
  const tick = this.safeValue(message, 'tick', {});
349
- let orderbook = this.safeValue(this.orderbooks, symbol);
350
- if (orderbook === undefined) {
351
- orderbook = this.orderBook();
349
+ if (!(symbol in this.orderbooks)) {
350
+ this.orderbooks[symbol] = this.orderBook();
352
351
  }
352
+ const orderbook = this.orderbooks[symbol];
353
353
  const snapshot = this.parseOrderBook(tick, symbol, timestamp, 'buys', 'asks');
354
354
  orderbook.reset(snapshot);
355
- this.orderbooks[symbol] = orderbook;
356
355
  const messageHash = 'orderbook:' + symbol;
357
356
  client.resolve(orderbook, messageHash);
358
357
  }
@@ -455,17 +455,18 @@ class currencycom extends currencycom$1 {
455
455
  const destination = 'depthMarketData.subscribe';
456
456
  const messageHash = destination + ':' + symbol;
457
457
  const timestamp = this.safeInteger(data, 'ts');
458
- let orderbook = this.safeValue(this.orderbooks, symbol);
459
- if (orderbook === undefined) {
460
- orderbook = this.orderBook();
458
+ // let orderbook = this.safeValue (this.orderbooks, symbol);
459
+ if (!(symbol in this.orderbooks)) {
460
+ this.orderbooks[symbol] = this.orderBook();
461
461
  }
462
+ const orderbook = this.orderbooks[symbol];
462
463
  orderbook.reset({
463
464
  'symbol': symbol,
464
465
  'timestamp': timestamp,
465
466
  'datetime': this.iso8601(timestamp),
466
467
  });
467
- const bids = this.safeValue(data, 'bid', {});
468
- const asks = this.safeValue(data, 'ofr', {});
468
+ const bids = this.safeDict(data, 'bid', {});
469
+ const asks = this.safeDict(data, 'ofr', {});
469
470
  this.handleDeltas(orderbook['bids'], bids);
470
471
  this.handleDeltas(orderbook['asks'], asks);
471
472
  this.orderbooks[symbol] = orderbook;
@@ -512,19 +512,18 @@ class exmo extends exmo$1 {
512
512
  const orderBook = this.safeValue(message, 'data', {});
513
513
  const messageHash = 'orderbook:' + symbol;
514
514
  const timestamp = this.safeInteger(message, 'ts');
515
- let orderbook = this.safeValue(this.orderbooks, symbol);
516
- if (orderbook === undefined) {
517
- orderbook = this.orderBook({});
518
- this.orderbooks[symbol] = orderbook;
515
+ if (!(symbol in this.orderbooks)) {
516
+ this.orderbooks[symbol] = this.orderBook({});
519
517
  }
518
+ const orderbook = this.orderbooks[symbol];
520
519
  const event = this.safeString(message, 'event');
521
520
  if (event === 'snapshot') {
522
521
  const snapshot = this.parseOrderBook(orderBook, symbol, timestamp, 'bid', 'ask');
523
522
  orderbook.reset(snapshot);
524
523
  }
525
524
  else {
526
- const asks = this.safeValue(orderBook, 'ask', []);
527
- const bids = this.safeValue(orderBook, 'bid', []);
525
+ const asks = this.safeList(orderBook, 'ask', []);
526
+ const bids = this.safeList(orderBook, 'bid', []);
528
527
  this.handleDeltas(orderbook['asks'], asks);
529
528
  this.handleDeltas(orderbook['bids'], bids);
530
529
  orderbook['timestamp'] = timestamp;
@@ -384,10 +384,11 @@ class gemini extends gemini$1 {
384
384
  const market = this.safeMarket(marketId);
385
385
  const symbol = market['symbol'];
386
386
  const messageHash = 'orderbook:' + symbol;
387
- let orderbook = this.safeValue(this.orderbooks, symbol);
388
- if (orderbook === undefined) {
389
- orderbook = this.orderBook();
387
+ // let orderbook = this.safeValue (this.orderbooks, symbol);
388
+ if (!(symbol in this.orderbooks)) {
389
+ this.orderbooks[symbol] = this.orderBook();
390
390
  }
391
+ const orderbook = this.orderbooks[symbol];
391
392
  for (let i = 0; i < changes.length; i++) {
392
393
  const delta = changes[i];
393
394
  const price = this.safeNumber(delta, 1);
@@ -173,24 +173,24 @@ class independentreserve extends independentreserve$1 {
173
173
  const base = this.safeCurrencyCode(baseId);
174
174
  const quote = this.safeCurrencyCode(quoteId);
175
175
  const symbol = base + '/' + quote;
176
- const orderBook = this.safeValue(message, 'Data', {});
176
+ const orderBook = this.safeDict(message, 'Data', {});
177
177
  const messageHash = 'orderbook:' + symbol + ':' + depth;
178
178
  const subscription = this.safeValue(client.subscriptions, messageHash, {});
179
179
  const receivedSnapshot = this.safeBool(subscription, 'receivedSnapshot', false);
180
180
  const timestamp = this.safeInteger(message, 'Time');
181
- let orderbook = this.safeValue(this.orderbooks, symbol);
182
- if (orderbook === undefined) {
183
- orderbook = this.orderBook({});
184
- this.orderbooks[symbol] = orderbook;
181
+ // let orderbook = this.safeValue (this.orderbooks, symbol);
182
+ if (!(symbol in this.orderbooks)) {
183
+ this.orderbooks[symbol] = this.orderBook({});
185
184
  }
185
+ const orderbook = this.orderbooks[symbol];
186
186
  if (event === 'OrderBookSnapshot') {
187
187
  const snapshot = this.parseOrderBook(orderBook, symbol, timestamp, 'Bids', 'Offers', 'Price', 'Volume');
188
188
  orderbook.reset(snapshot);
189
189
  subscription['receivedSnapshot'] = true;
190
190
  }
191
191
  else {
192
- const asks = this.safeValue(orderBook, 'Offers', []);
193
- const bids = this.safeValue(orderBook, 'Bids', []);
192
+ const asks = this.safeList(orderBook, 'Offers', []);
193
+ const bids = this.safeList(orderBook, 'Bids', []);
194
194
  this.handleDeltas(orderbook['asks'], asks);
195
195
  this.handleDeltas(orderbook['bids'], bids);
196
196
  orderbook['timestamp'] = timestamp;
@@ -778,11 +778,11 @@ class lbank extends lbank$1 {
778
778
  const orderBook = this.safeValue(message, 'depth', message);
779
779
  const datetime = this.safeString(message, 'TS');
780
780
  const timestamp = this.parse8601(datetime);
781
- let orderbook = this.safeValue(this.orderbooks, symbol);
782
- if (orderbook === undefined) {
783
- orderbook = this.orderBook({});
784
- this.orderbooks[symbol] = orderbook;
781
+ // let orderbook = this.safeValue (this.orderbooks, symbol);
782
+ if (!(symbol in this.orderbooks)) {
783
+ this.orderbooks[symbol] = this.orderBook({});
785
784
  }
785
+ const orderbook = this.orderbooks[symbol];
786
786
  const snapshot = this.parseOrderBook(orderBook, symbol, timestamp, 'bids', 'asks');
787
787
  orderbook.reset(snapshot);
788
788
  let messageHash = 'orderbook:' + symbol;