ccxt 4.3.89 → 4.3.91

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 (69) 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/alpaca.js +2 -2
  5. package/dist/cjs/src/ascendex.js +95 -97
  6. package/dist/cjs/src/binance.js +1 -1
  7. package/dist/cjs/src/bingx.js +31 -17
  8. package/dist/cjs/src/bitfinex2.js +21 -22
  9. package/dist/cjs/src/bitget.js +2 -2
  10. package/dist/cjs/src/bitmart.js +6 -9
  11. package/dist/cjs/src/coinbaseinternational.js +2 -1
  12. package/dist/cjs/src/coinex.js +1 -17
  13. package/dist/cjs/src/hitbtc.js +2 -0
  14. package/dist/cjs/src/htx.js +49 -49
  15. package/dist/cjs/src/huobijp.js +0 -9
  16. package/dist/cjs/src/kucoin.js +59 -21
  17. package/dist/cjs/src/kucoinfutures.js +26 -2
  18. package/dist/cjs/src/latoken.js +1 -0
  19. package/dist/cjs/src/okx.js +1 -8
  20. package/dist/cjs/src/pro/binance.js +323 -0
  21. package/dist/cjs/src/pro/bingx.js +263 -91
  22. package/dist/cjs/src/pro/bithumb.js +5 -1
  23. package/dist/cjs/src/pro/bybit.js +1 -1
  24. package/dist/cjs/src/pro/coinex.js +994 -679
  25. package/dist/cjs/src/pro/lbank.js +2 -3
  26. package/dist/cjs/src/pro/okx.js +159 -3
  27. package/dist/cjs/src/whitebit.js +5 -3
  28. package/dist/cjs/src/woo.js +1 -1
  29. package/js/ccxt.d.ts +1 -1
  30. package/js/ccxt.js +1 -1
  31. package/js/src/abstract/kucoin.d.ts +1 -0
  32. package/js/src/abstract/kucoinfutures.d.ts +1 -0
  33. package/js/src/alpaca.js +2 -2
  34. package/js/src/ascendex.js +95 -97
  35. package/js/src/binance.js +1 -1
  36. package/js/src/bingx.js +31 -17
  37. package/js/src/bitfinex2.d.ts +0 -1
  38. package/js/src/bitfinex2.js +21 -22
  39. package/js/src/bitget.js +2 -2
  40. package/js/src/bitmart.d.ts +0 -1
  41. package/js/src/bitmart.js +6 -9
  42. package/js/src/coinbaseinternational.js +2 -1
  43. package/js/src/coinex.d.ts +0 -2
  44. package/js/src/coinex.js +1 -17
  45. package/js/src/hitbtc.js +2 -0
  46. package/js/src/htx.js +49 -49
  47. package/js/src/huobijp.d.ts +0 -1
  48. package/js/src/huobijp.js +0 -9
  49. package/js/src/kucoin.d.ts +3 -1
  50. package/js/src/kucoin.js +59 -21
  51. package/js/src/kucoinfutures.d.ts +1 -0
  52. package/js/src/kucoinfutures.js +26 -2
  53. package/js/src/latoken.js +1 -0
  54. package/js/src/okx.d.ts +0 -1
  55. package/js/src/okx.js +1 -8
  56. package/js/src/pro/binance.d.ts +9 -1
  57. package/js/src/pro/binance.js +327 -1
  58. package/js/src/pro/bingx.d.ts +2 -2
  59. package/js/src/pro/bingx.js +263 -91
  60. package/js/src/pro/bithumb.js +5 -1
  61. package/js/src/pro/bybit.js +1 -1
  62. package/js/src/pro/coinex.d.ts +12 -6
  63. package/js/src/pro/coinex.js +996 -681
  64. package/js/src/pro/lbank.js +2 -3
  65. package/js/src/pro/okx.d.ts +7 -0
  66. package/js/src/pro/okx.js +162 -4
  67. package/js/src/whitebit.js +5 -3
  68. package/js/src/woo.js +1 -1
  69. package/package.json +1 -1
@@ -31,7 +31,8 @@ export default class bingx extends bingxRest {
31
31
  'api': {
32
32
  'ws': {
33
33
  'spot': 'wss://open-api-ws.bingx.com/market',
34
- 'swap': 'wss://open-api-swap.bingx.com/swap-market',
34
+ 'linear': 'wss://open-api-swap.bingx.com/swap-market',
35
+ 'inverse': 'wss://open-api-cswap-ws.bingx.com/market',
35
36
  },
36
37
  },
37
38
  },
@@ -91,17 +92,25 @@ export default class bingx extends bingxRest {
91
92
  * @method
92
93
  * @name bingx#watchTicker
93
94
  * @description watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
95
+ * @see https://bingx-api.github.io/docs/#/en-us/spot/socket/market.html#Subscribe%20to%2024-hour%20Price%20Change
94
96
  * @see https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20to%2024-hour%20price%20changes
97
+ * @see https://bingx-api.github.io/docs/#/en-us/cswap/socket/market.html#Subscribe%20to%2024-Hour%20Price%20Change
95
98
  * @param {string} symbol unified symbol of the market to fetch the ticker for
96
99
  * @param {object} [params] extra parameters specific to the exchange API endpoint
97
100
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
98
101
  */
99
102
  await this.loadMarkets();
100
103
  const market = this.market(symbol);
101
- const [marketType, query] = this.handleMarketTypeAndParams('watchTicker', market, params);
102
- const url = this.safeValue(this.urls['api']['ws'], marketType);
103
- if (url === undefined) {
104
- throw new BadRequest(this.id + ' watchTicker is not supported for ' + marketType + ' markets.');
104
+ let marketType = undefined;
105
+ let subType = undefined;
106
+ let url = undefined;
107
+ [marketType, params] = this.handleMarketTypeAndParams('watchTicker', market, params);
108
+ [subType, params] = this.handleSubTypeAndParams('watchTicker', market, params, 'linear');
109
+ if (marketType === 'swap') {
110
+ url = this.safeString(this.urls['api']['ws'], subType);
111
+ }
112
+ else {
113
+ url = this.safeString(this.urls['api']['ws'], marketType);
105
114
  }
106
115
  const subscriptionHash = market['id'] + '@ticker';
107
116
  const messageHash = this.getMessageHash('ticker', market['symbol']);
@@ -113,7 +122,7 @@ export default class bingx extends bingxRest {
113
122
  if (marketType === 'swap') {
114
123
  request['reqType'] = 'sub';
115
124
  }
116
- return await this.watch(url, messageHash, this.extend(request, query), subscriptionHash);
125
+ return await this.watch(url, messageHash, this.extend(request, params), subscriptionHash);
117
126
  }
118
127
  handleTicker(client, message) {
119
128
  //
@@ -248,14 +257,19 @@ export default class bingx extends bingxRest {
248
257
  symbols = this.marketSymbols(symbols, undefined, true, true, false);
249
258
  let firstMarket = undefined;
250
259
  let marketType = undefined;
260
+ let subType = undefined;
251
261
  const symbolsDefined = (symbols !== undefined);
252
262
  if (symbolsDefined) {
253
263
  firstMarket = this.market(symbols[0]);
254
264
  }
255
265
  [marketType, params] = this.handleMarketTypeAndParams('watchTickers', firstMarket, params);
266
+ [subType, params] = this.handleSubTypeAndParams('watchTickers', firstMarket, params, 'linear');
256
267
  if (marketType === 'spot') {
257
268
  throw new NotSupported(this.id + ' watchTickers is not supported for spot markets yet');
258
269
  }
270
+ if (subType === 'inverse') {
271
+ throw new NotSupported(this.id + ' watchTickers is not supported for inverse markets yet');
272
+ }
259
273
  const messageHashes = [];
260
274
  const subscriptionHashes = ['all@ticker'];
261
275
  if (symbolsDefined) {
@@ -268,7 +282,7 @@ export default class bingx extends bingxRest {
268
282
  else {
269
283
  messageHashes.push(this.getMessageHash('ticker'));
270
284
  }
271
- const url = this.safeString(this.urls['api']['ws'], marketType);
285
+ const url = this.safeString(this.urls['api']['ws'], subType);
272
286
  const uuid = this.uuid();
273
287
  const request = {
274
288
  'id': uuid,
@@ -299,14 +313,19 @@ export default class bingx extends bingxRest {
299
313
  symbols = this.marketSymbols(symbols, undefined, true, true, false);
300
314
  let firstMarket = undefined;
301
315
  let marketType = undefined;
316
+ let subType = undefined;
302
317
  const symbolsDefined = (symbols !== undefined);
303
318
  if (symbolsDefined) {
304
319
  firstMarket = this.market(symbols[0]);
305
320
  }
306
321
  [marketType, params] = this.handleMarketTypeAndParams('watchOrderBookForSymbols', firstMarket, params);
322
+ [subType, params] = this.handleSubTypeAndParams('watchOrderBookForSymbols', firstMarket, params, 'linear');
307
323
  if (marketType === 'spot') {
308
324
  throw new NotSupported(this.id + ' watchOrderBookForSymbols is not supported for spot markets yet');
309
325
  }
326
+ if (subType === 'inverse') {
327
+ throw new NotSupported(this.id + ' watchOrderBookForSymbols is not supported for inverse markets yet');
328
+ }
310
329
  limit = this.getOrderBookLimitByMarketType(marketType, limit);
311
330
  let interval = undefined;
312
331
  [interval, params] = this.handleOptionAndParams(params, 'watchOrderBookForSymbols', 'interval', 500);
@@ -324,7 +343,7 @@ export default class bingx extends bingxRest {
324
343
  else {
325
344
  messageHashes.push(this.getMessageHash('orderbook'));
326
345
  }
327
- const url = this.safeString(this.urls['api']['ws'], marketType);
346
+ const url = this.safeString(this.urls['api']['ws'], subType);
328
347
  const uuid = this.uuid();
329
348
  const request = {
330
349
  'id': uuid,
@@ -347,6 +366,7 @@ export default class bingx extends bingxRest {
347
366
  * @method
348
367
  * @name bingx#watchOHLCVForSymbols
349
368
  * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
369
+ * @see https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20K-Line%20Data%20of%20all%20trading%20pairs
350
370
  * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
351
371
  * @param {int} [since] timestamp in ms of the earliest candle to fetch
352
372
  * @param {int} [limit] the maximum amount of candles to fetch
@@ -360,15 +380,21 @@ export default class bingx extends bingxRest {
360
380
  await this.loadMarkets();
361
381
  const messageHashes = [];
362
382
  let marketType = undefined;
383
+ let subType = undefined;
363
384
  let chosenTimeframe = undefined;
385
+ let firstMarket = undefined;
364
386
  if (symbolsLength !== 0) {
365
387
  let symbols = this.getListFromObjectValues(symbolsAndTimeframes, 0);
366
388
  symbols = this.marketSymbols(symbols, undefined, true, true, false);
367
- const firstMarket = this.market(symbols[0]);
368
- [marketType, params] = this.handleMarketTypeAndParams('watchOrderBookForSymbols', firstMarket, params);
369
- if (marketType === 'spot') {
370
- throw new NotSupported(this.id + ' watchOrderBookForSymbols is not supported for spot markets yet');
371
- }
389
+ firstMarket = this.market(symbols[0]);
390
+ }
391
+ [marketType, params] = this.handleMarketTypeAndParams('watchOHLCVForSymbols', firstMarket, params);
392
+ [subType, params] = this.handleSubTypeAndParams('watchOHLCVForSymbols', firstMarket, params, 'linear');
393
+ if (marketType === 'spot') {
394
+ throw new NotSupported(this.id + ' watchOHLCVForSymbols is not supported for spot markets yet');
395
+ }
396
+ if (subType === 'inverse') {
397
+ throw new NotSupported(this.id + ' watchOHLCVForSymbols is not supported for inverse markets yet');
372
398
  }
373
399
  const marketOptions = this.safeDict(this.options, marketType);
374
400
  const timeframes = this.safeDict(marketOptions, 'timeframes', {});
@@ -387,7 +413,7 @@ export default class bingx extends bingxRest {
387
413
  messageHashes.push(this.getMessageHash('ohlcv', market['symbol'], chosenTimeframe));
388
414
  }
389
415
  const subscriptionHash = 'all@kline_' + chosenTimeframe;
390
- const url = this.safeString(this.urls['api']['ws'], marketType);
416
+ const url = this.safeString(this.urls['api']['ws'], subType);
391
417
  const uuid = this.uuid();
392
418
  const request = {
393
419
  'id': uuid,
@@ -439,8 +465,9 @@ export default class bingx extends bingxRest {
439
465
  * @method
440
466
  * @name bingx#watchTrades
441
467
  * @description watches information on multiple trades made in a market
442
- * @see https://bingx-api.github.io/docs/#/en-us/spot/socket/market.html#Subscription%20transaction%20by%20transaction
443
- * @see https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20the%20Latest%20Trade%20Detail
468
+ * @see https://bingx-api.github.io/docs/#/spot/socket/market.html#Subscribe%20to%20tick-by-tick
469
+ * @see https://bingx-api.github.io/docs/#/swapV2/socket/market.html#Subscribe%20the%20Latest%20Trade%20Detail
470
+ * @see https://bingx-api.github.io/docs/#/en-us/cswap/socket/market.html#Subscription%20transaction%20by%20transaction
444
471
  * @param {string} symbol unified market symbol of the market orders were made in
445
472
  * @param {int} [since] the earliest time in ms to fetch orders for
446
473
  * @param {int} [limit] the maximum number of order structures to retrieve
@@ -449,11 +476,17 @@ export default class bingx extends bingxRest {
449
476
  */
450
477
  await this.loadMarkets();
451
478
  const market = this.market(symbol);
479
+ symbol = market['symbol'];
452
480
  let marketType = undefined;
481
+ let subType = undefined;
482
+ let url = undefined;
453
483
  [marketType, params] = this.handleMarketTypeAndParams('watchTrades', market, params);
454
- const url = this.safeValue(this.urls['api']['ws'], marketType);
455
- if (url === undefined) {
456
- throw new BadRequest(this.id + ' watchTrades is not supported for ' + marketType + ' markets.');
484
+ [subType, params] = this.handleSubTypeAndParams('watchTrades', market, params, 'linear');
485
+ if (marketType === 'swap') {
486
+ url = this.safeString(this.urls['api']['ws'], subType);
487
+ }
488
+ else {
489
+ url = this.safeString(this.urls['api']['ws'], marketType);
457
490
  }
458
491
  const rawHash = market['id'] + '@trade';
459
492
  const messageHash = 'trade::' + symbol;
@@ -473,8 +506,7 @@ export default class bingx extends bingxRest {
473
506
  }
474
507
  handleTrades(client, message) {
475
508
  //
476
- // spot
477
- // first snapshot
509
+ // spot: first snapshot
478
510
  //
479
511
  // {
480
512
  // "id": "d83b78ce-98be-4dc2-b847-12fe471b5bc5",
@@ -483,7 +515,7 @@ export default class bingx extends bingxRest {
483
515
  // "timestamp": 1690214699854
484
516
  // }
485
517
  //
486
- // subsequent updates
518
+ // spot: subsequent updates
487
519
  //
488
520
  // {
489
521
  // "code": 0,
@@ -501,9 +533,7 @@ export default class bingx extends bingxRest {
501
533
  // "success": true
502
534
  // }
503
535
  //
504
- //
505
- // swap
506
- // first snapshot
536
+ // linear swap: first snapshot
507
537
  //
508
538
  // {
509
539
  // "id": "2aed93b1-6e1e-4038-aeba-f5eeaec2ca48",
@@ -513,8 +543,7 @@ export default class bingx extends bingxRest {
513
543
  // "data": null
514
544
  // }
515
545
  //
516
- // subsequent updates
517
- //
546
+ // linear swap: subsequent updates
518
547
  //
519
548
  // {
520
549
  // "code": 0,
@@ -531,6 +560,32 @@ export default class bingx extends bingxRest {
531
560
  // ]
532
561
  // }
533
562
  //
563
+ // inverse swap: first snapshot
564
+ //
565
+ // {
566
+ // "code": 0,
567
+ // "id": "a2e482ca-f71b-42f8-a83a-8ff85a713e64",
568
+ // "msg": "SUCCESS",
569
+ // "timestamp": 1722920589426
570
+ // }
571
+ //
572
+ // inverse swap: subsequent updates
573
+ //
574
+ // {
575
+ // "code": 0,
576
+ // "dataType": "BTC-USD@trade",
577
+ // "data": {
578
+ // "e": "trade",
579
+ // "E": 1722920589665,
580
+ // "s": "BTC-USD",
581
+ // "t": "39125001",
582
+ // "p": "55360.0",
583
+ // "q": "1",
584
+ // "T": 1722920589582,
585
+ // "m": false
586
+ // }
587
+ // }
588
+ //
534
589
  const data = this.safeValue(message, 'data', []);
535
590
  const rawHash = this.safeString(message, 'dataType');
536
591
  const marketId = rawHash.split('@')[0];
@@ -564,6 +619,7 @@ export default class bingx extends bingxRest {
564
619
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
565
620
  * @see https://bingx-api.github.io/docs/#/en-us/spot/socket/market.html#Subscribe%20Market%20Depth%20Data
566
621
  * @see https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20Market%20Depth%20Data
622
+ * @see https://bingx-api.github.io/docs/#/en-us/cswap/socket/market.html#Subscribe%20to%20Limited%20Depth
567
623
  * @param {string} symbol unified symbol of the market to fetch the order book for
568
624
  * @param {int} [limit] the maximum amount of order book entries to return
569
625
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -571,18 +627,26 @@ export default class bingx extends bingxRest {
571
627
  */
572
628
  await this.loadMarkets();
573
629
  const market = this.market(symbol);
574
- const [marketType, query] = this.handleMarketTypeAndParams('watchOrderBook', market, params);
630
+ let marketType = undefined;
631
+ let subType = undefined;
632
+ let url = undefined;
633
+ [marketType, params] = this.handleMarketTypeAndParams('watchOrderBook', market, params);
634
+ [subType, params] = this.handleSubTypeAndParams('watchOrderBook', market, params, 'linear');
635
+ if (marketType === 'swap') {
636
+ url = this.safeString(this.urls['api']['ws'], subType);
637
+ }
638
+ else {
639
+ url = this.safeString(this.urls['api']['ws'], marketType);
640
+ }
575
641
  limit = this.getOrderBookLimitByMarketType(marketType, limit);
576
642
  let channelName = 'depth' + limit.toString();
577
- const url = this.safeValue(this.urls['api']['ws'], marketType);
578
- if (url === undefined) {
579
- throw new BadRequest(this.id + ' watchOrderBook is not supported for ' + marketType + ' markets.');
580
- }
581
643
  let interval = undefined;
582
644
  if (marketType !== 'spot') {
583
- [interval, params] = this.handleOptionAndParams(params, 'watchOrderBook', 'interval', 500);
584
- this.checkRequiredArgument('watchOrderBook', interval, 'interval', [100, 200, 500, 1000]);
585
- channelName = channelName + '@' + interval.toString() + 'ms';
645
+ if (!market['inverse']) {
646
+ [interval, params] = this.handleOptionAndParams(params, 'watchOrderBook', 'interval', 500);
647
+ this.checkRequiredArgument('watchOrderBook', interval, 'interval', [100, 200, 500, 1000]);
648
+ channelName = channelName + '@' + interval.toString() + 'ms';
649
+ }
586
650
  }
587
651
  const subscriptionHash = market['id'] + '@' + channelName;
588
652
  const messageHash = this.getMessageHash('orderbook', market['symbol']);
@@ -594,24 +658,32 @@ export default class bingx extends bingxRest {
594
658
  if (marketType === 'swap') {
595
659
  request['reqType'] = 'sub';
596
660
  }
597
- const subscriptionArgs = {
598
- 'limit': limit,
599
- 'interval': interval,
600
- 'params': params,
601
- };
602
- const orderbook = await this.watch(url, messageHash, this.deepExtend(request, query), subscriptionHash, subscriptionArgs);
661
+ let subscriptionArgs = {};
662
+ if (market['inverse']) {
663
+ subscriptionArgs = {
664
+ 'count': limit,
665
+ 'params': params,
666
+ };
667
+ }
668
+ else {
669
+ subscriptionArgs = {
670
+ 'level': limit,
671
+ 'interval': interval,
672
+ 'params': params,
673
+ };
674
+ }
675
+ const orderbook = await this.watch(url, messageHash, this.deepExtend(request, params), subscriptionHash, subscriptionArgs);
603
676
  return orderbook.limit();
604
677
  }
605
678
  handleDelta(bookside, delta) {
606
- const price = this.safeFloat(delta, 0);
607
- const amount = this.safeFloat(delta, 1);
679
+ const price = this.safeFloat2(delta, 0, 'p');
680
+ const amount = this.safeFloat2(delta, 1, 'a');
608
681
  bookside.store(price, amount);
609
682
  }
610
683
  handleOrderBook(client, message) {
611
684
  //
612
685
  // spot
613
686
  //
614
- //
615
687
  // {
616
688
  // "code": 0,
617
689
  // "dataType": "BTC-USDT@depth20",
@@ -629,8 +701,7 @@ export default class bingx extends bingxRest {
629
701
  // "success": true
630
702
  // }
631
703
  //
632
- // swap
633
- //
704
+ // linear swap
634
705
  //
635
706
  // {
636
707
  // "code": 0,
@@ -648,6 +719,28 @@ export default class bingx extends bingxRest {
648
719
  // }
649
720
  // }
650
721
  //
722
+ // inverse swap
723
+ //
724
+ // {
725
+ // "code": 0,
726
+ // "dataType": "BTC-USD@depth100",
727
+ // "data": {
728
+ // {
729
+ // "symbol": "BTC-USD",
730
+ // "bids": [
731
+ // { "p": "58074.2", "a": "1.422318", "v": "826.0" },
732
+ // ...
733
+ // ],
734
+ // "asks": [
735
+ // { "p": "62878.0", "a": "0.001590", "v": "1.0" },
736
+ // ...
737
+ // ],
738
+ // "aggPrecision": "0.1",
739
+ // "timestamp": 1723705093529
740
+ // }
741
+ // }
742
+ // }
743
+ //
651
744
  const data = this.safeDict(message, 'data', {});
652
745
  const dataType = this.safeString(message, 'dataType');
653
746
  const parts = dataType.split('@');
@@ -666,7 +759,13 @@ export default class bingx extends bingxRest {
666
759
  this.orderbooks[symbol] = this.orderBook({}, limit);
667
760
  }
668
761
  const orderbook = this.orderbooks[symbol];
669
- const snapshot = this.parseOrderBook(data, symbol, undefined, 'bids', 'asks', 0, 1);
762
+ let snapshot = undefined;
763
+ if (market['inverse']) {
764
+ snapshot = this.parseOrderBook(data, symbol, undefined, 'bids', 'asks', 'p', 'a');
765
+ }
766
+ else {
767
+ snapshot = this.parseOrderBook(data, symbol, undefined, 'bids', 'asks', 0, 1);
768
+ }
670
769
  orderbook.reset(snapshot);
671
770
  this.orderbooks[symbol] = orderbook;
672
771
  const messageHash = this.getMessageHash('orderbook', symbol);
@@ -690,8 +789,11 @@ export default class bingx extends bingxRest {
690
789
  // }
691
790
  //
692
791
  // for spot, opening-time (t) is used instead of closing-time (T), to be compatible with fetchOHLCV
693
- // for swap, (T) is the opening time
694
- const timestamp = (market['spot']) ? 't' : 'T';
792
+ // for linear swap, (T) is the opening time
793
+ let timestamp = (market['spot']) ? 't' : 'T';
794
+ if (market['swap']) {
795
+ timestamp = (market['inverse']) ? 't' : 'T';
796
+ }
695
797
  return [
696
798
  this.safeInteger(ohlcv, timestamp),
697
799
  this.safeNumber(ohlcv, 'o'),
@@ -703,7 +805,7 @@ export default class bingx extends bingxRest {
703
805
  }
704
806
  handleOHLCV(client, message) {
705
807
  //
706
- // spot
808
+ // spot:
707
809
  //
708
810
  // {
709
811
  // "code": 0,
@@ -729,7 +831,8 @@ export default class bingx extends bingxRest {
729
831
  // "success": true
730
832
  // }
731
833
  //
732
- // swap
834
+ // linear swap:
835
+ //
733
836
  // {
734
837
  // "code": 0,
735
838
  // "dataType": "BTC-USDT@kline_1m",
@@ -746,15 +849,26 @@ export default class bingx extends bingxRest {
746
849
  // ]
747
850
  // }
748
851
  //
852
+ // inverse swap:
853
+ //
854
+ // {
855
+ // "code": 0,
856
+ // "timestamp": 1723769354547,
857
+ // "dataType": "BTC-USD@kline_1m",
858
+ // "data": {
859
+ // "t": 1723769340000,
860
+ // "o": 57485.1,
861
+ // "c": 57468,
862
+ // "l": 57464.9,
863
+ // "h": 57485.1,
864
+ // "a": 0.189663,
865
+ // "v": 109,
866
+ // "u": 92,
867
+ // "s": "BTC-USD"
868
+ // }
869
+ // }
870
+ //
749
871
  const isSwap = client.url.indexOf('swap') >= 0;
750
- let candles = undefined;
751
- if (isSwap) {
752
- candles = this.safeList(message, 'data', []);
753
- }
754
- else {
755
- const data = this.safeDict(message, 'data', {});
756
- candles = [this.safeDict(data, 'K', {})];
757
- }
758
872
  const dataType = this.safeString(message, 'dataType');
759
873
  const parts = dataType.split('@');
760
874
  const firstPart = parts[0];
@@ -762,6 +876,19 @@ export default class bingx extends bingxRest {
762
876
  const marketId = this.safeString(message, 's', firstPart);
763
877
  const marketType = isSwap ? 'swap' : 'spot';
764
878
  const market = this.safeMarket(marketId, undefined, undefined, marketType);
879
+ let candles = undefined;
880
+ if (isSwap) {
881
+ if (market['inverse']) {
882
+ candles = [this.safeDict(message, 'data', {})];
883
+ }
884
+ else {
885
+ candles = this.safeList(message, 'data', []);
886
+ }
887
+ }
888
+ else {
889
+ const data = this.safeDict(message, 'data', {});
890
+ candles = [this.safeDict(data, 'K', {})];
891
+ }
765
892
  const symbol = market['symbol'];
766
893
  this.ohlcvs[symbol] = this.safeValue(this.ohlcvs, symbol, {});
767
894
  const rawTimeframe = dataType.split('_')[1];
@@ -796,6 +923,7 @@ export default class bingx extends bingxRest {
796
923
  * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
797
924
  * @see https://bingx-api.github.io/docs/#/en-us/spot/socket/market.html#K-line%20Streams
798
925
  * @see https://bingx-api.github.io/docs/#/en-us/swapV2/socket/market.html#Subscribe%20K-Line%20Data
926
+ * @see https://bingx-api.github.io/docs/#/en-us/cswap/socket/market.html#Subscribe%20to%20Latest%20Trading%20Pair%20K-Line
799
927
  * @param {string} symbol unified symbol of the market to fetch OHLCV data for
800
928
  * @param {string} timeframe the length of time each candle represents
801
929
  * @param {int} [since] timestamp in ms of the earliest candle to fetch
@@ -805,8 +933,17 @@ export default class bingx extends bingxRest {
805
933
  */
806
934
  await this.loadMarkets();
807
935
  const market = this.market(symbol);
808
- const [marketType, query] = this.handleMarketTypeAndParams('watchOHLCV', market, params);
809
- const url = this.safeValue(this.urls['api']['ws'], marketType);
936
+ let marketType = undefined;
937
+ let subType = undefined;
938
+ let url = undefined;
939
+ [marketType, params] = this.handleMarketTypeAndParams('watchOHLCV', market, params);
940
+ [subType, params] = this.handleSubTypeAndParams('watchOHLCV', market, params, 'linear');
941
+ if (marketType === 'swap') {
942
+ url = this.safeString(this.urls['api']['ws'], subType);
943
+ }
944
+ else {
945
+ url = this.safeString(this.urls['api']['ws'], marketType);
946
+ }
810
947
  if (url === undefined) {
811
948
  throw new BadRequest(this.id + ' watchOHLCV is not supported for ' + marketType + ' markets.');
812
949
  }
@@ -824,10 +961,10 @@ export default class bingx extends bingxRest {
824
961
  request['reqType'] = 'sub';
825
962
  }
826
963
  const subscriptionArgs = {
827
- 'limit': limit,
964
+ 'interval': rawTimeframe,
828
965
  'params': params,
829
966
  };
830
- const result = await this.watch(url, messageHash, this.extend(request, query), subscriptionHash, subscriptionArgs);
967
+ const result = await this.watch(url, messageHash, this.extend(request, params), subscriptionHash, subscriptionArgs);
831
968
  const ohlcv = result[2];
832
969
  if (this.newUpdates) {
833
970
  limit = ohlcv.getLimit(symbol, limit);
@@ -838,11 +975,12 @@ export default class bingx extends bingxRest {
838
975
  /**
839
976
  * @method
840
977
  * @name bingx#watchOrders
841
- * @see https://bingx-api.github.io/docs/#/en-us/spot/socket/account.html#Subscription%20order%20update%20data
842
- * @see https://bingx-api.github.io/docs/#/en-us/swapV2/socket/account.html#Account%20balance%20and%20position%20update%20push
843
978
  * @description watches information on multiple orders made by the user
844
- * @param {string} symbol unified market symbol of the market orders were made in
845
- * @param {int} [since] the earliest time in ms to fetch orders for
979
+ * @see https://bingx-api.github.io/docs/#/en-us/spot/socket/account.html#Subscription%20order%20update%20data
980
+ * @see https://bingx-api.github.io/docs/#/en-us/swapV2/socket/account.html#Order%20update%20push
981
+ * @see https://bingx-api.github.io/docs/#/en-us/cswap/socket/account.html#Order%20update%20push
982
+ * @param {string} [symbol] unified market symbol of the market orders are made in
983
+ * @param {int} [since] the earliest time in ms to watch orders for
846
984
  * @param {int} [limit] the maximum number of order structures to retrieve
847
985
  * @param {object} [params] extra parameters specific to the exchange API endpoint
848
986
  * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
@@ -850,12 +988,14 @@ export default class bingx extends bingxRest {
850
988
  await this.loadMarkets();
851
989
  await this.authenticate();
852
990
  let type = undefined;
991
+ let subType = undefined;
853
992
  let market = undefined;
854
993
  if (symbol !== undefined) {
855
994
  market = this.market(symbol);
856
995
  symbol = market['symbol'];
857
996
  }
858
997
  [type, params] = this.handleMarketTypeAndParams('watchOrders', market, params);
998
+ [subType, params] = this.handleSubTypeAndParams('watchOrders', market, params, 'linear');
859
999
  const isSpot = (type === 'spot');
860
1000
  const spotHash = 'spot:private';
861
1001
  const swapHash = 'swap:private';
@@ -866,15 +1006,24 @@ export default class bingx extends bingxRest {
866
1006
  if (market !== undefined) {
867
1007
  messageHash += ':' + symbol;
868
1008
  }
869
- const url = this.urls['api']['ws'][type] + '?listenKey=' + this.options['listenKey'];
870
- let request = undefined;
871
1009
  const uuid = this.uuid();
872
- if (isSpot) {
1010
+ let baseUrl = undefined;
1011
+ let request = undefined;
1012
+ if (type === 'swap') {
1013
+ if (subType === 'inverse') {
1014
+ throw new NotSupported(this.id + ' watchOrders is not supported for inverse swap markets yet');
1015
+ }
1016
+ baseUrl = this.safeString(this.urls['api']['ws'], subType);
1017
+ }
1018
+ else {
1019
+ baseUrl = this.safeString(this.urls['api']['ws'], type);
873
1020
  request = {
874
1021
  'id': uuid,
1022
+ 'reqType': 'sub',
875
1023
  'dataType': 'spot.executionReport',
876
1024
  };
877
1025
  }
1026
+ const url = baseUrl + '?listenKey=' + this.options['listenKey'];
878
1027
  const orders = await this.watch(url, messageHash, request, subscriptionHash);
879
1028
  if (this.newUpdates) {
880
1029
  limit = orders.getLimit(symbol, limit);
@@ -885,43 +1034,55 @@ export default class bingx extends bingxRest {
885
1034
  /**
886
1035
  * @method
887
1036
  * @name bingx#watchMyTrades
888
- * @see https://bingx-api.github.io/docs/#/en-us/spot/socket/account.html#Subscription%20order%20update%20data
889
- * @see https://bingx-api.github.io/docs/#/en-us/swapV2/socket/account.html#Account%20balance%20and%20position%20update%20push
890
1037
  * @description watches information on multiple trades made by the user
891
- * @param {string} symbol unified market symbol of the market trades were made in
892
- * @param {int} [since] the earliest time in ms to trades orders for
893
- * @param {int} [limit] the maximum number of trades structures to retrieve
1038
+ * @see https://bingx-api.github.io/docs/#/en-us/spot/socket/account.html#Subscription%20order%20update%20data
1039
+ * @see https://bingx-api.github.io/docs/#/en-us/swapV2/socket/account.html#Order%20update%20push
1040
+ * @see https://bingx-api.github.io/docs/#/en-us/cswap/socket/account.html#Order%20update%20push
1041
+ * @param {string} [symbol] unified market symbol of the market the trades are made in
1042
+ * @param {int} [since] the earliest time in ms to watch trades for
1043
+ * @param {int} [limit] the maximum number of trade structures to retrieve
894
1044
  * @param {object} [params] extra parameters specific to the exchange API endpoint
895
1045
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
896
1046
  */
897
1047
  await this.loadMarkets();
898
1048
  await this.authenticate();
899
1049
  let type = undefined;
1050
+ let subType = undefined;
900
1051
  let market = undefined;
901
1052
  if (symbol !== undefined) {
902
1053
  market = this.market(symbol);
903
1054
  symbol = market['symbol'];
904
1055
  }
905
- [type, params] = this.handleMarketTypeAndParams('watchOrders', market, params);
1056
+ [type, params] = this.handleMarketTypeAndParams('watchMyTrades', market, params);
1057
+ [subType, params] = this.handleSubTypeAndParams('watchMyTrades', market, params, 'linear');
906
1058
  const isSpot = (type === 'spot');
907
- const spotSubHash = 'spot:private';
908
- const swapSubHash = 'swap:private';
909
- const subscriptionHash = isSpot ? spotSubHash : swapSubHash;
1059
+ const spotHash = 'spot:private';
1060
+ const swapHash = 'swap:private';
1061
+ const subscriptionHash = isSpot ? spotHash : swapHash;
910
1062
  const spotMessageHash = 'spot:mytrades';
911
1063
  const swapMessageHash = 'swap:mytrades';
912
1064
  let messageHash = isSpot ? spotMessageHash : swapMessageHash;
913
1065
  if (market !== undefined) {
914
1066
  messageHash += ':' + symbol;
915
1067
  }
916
- const url = this.urls['api']['ws'][type] + '?listenKey=' + this.options['listenKey'];
917
- let request = undefined;
918
1068
  const uuid = this.uuid();
919
- if (isSpot) {
1069
+ let baseUrl = undefined;
1070
+ let request = undefined;
1071
+ if (type === 'swap') {
1072
+ if (subType === 'inverse') {
1073
+ throw new NotSupported(this.id + ' watchMyTrades is not supported for inverse swap markets yet');
1074
+ }
1075
+ baseUrl = this.safeString(this.urls['api']['ws'], subType);
1076
+ }
1077
+ else {
1078
+ baseUrl = this.safeString(this.urls['api']['ws'], type);
920
1079
  request = {
921
1080
  'id': uuid,
1081
+ 'reqType': 'sub',
922
1082
  'dataType': 'spot.executionReport',
923
1083
  };
924
1084
  }
1085
+ const url = baseUrl + '?listenKey=' + this.options['listenKey'];
925
1086
  const trades = await this.watch(url, messageHash, request, subscriptionHash);
926
1087
  if (this.newUpdates) {
927
1088
  limit = trades.getLimit(symbol, limit);
@@ -932,16 +1093,19 @@ export default class bingx extends bingxRest {
932
1093
  /**
933
1094
  * @method
934
1095
  * @name bingx#watchBalance
1096
+ * @description query for balance and get the amount of funds available for trading or funds locked in orders
935
1097
  * @see https://bingx-api.github.io/docs/#/en-us/spot/socket/account.html#Subscription%20account%20balance%20push
936
1098
  * @see https://bingx-api.github.io/docs/#/en-us/swapV2/socket/account.html#Account%20balance%20and%20position%20update%20push
937
- * @description query for balance and get the amount of funds available for trading or funds locked in orders
1099
+ * @see https://bingx-api.github.io/docs/#/en-us/cswap/socket/account.html#Account%20balance%20and%20position%20update%20push
938
1100
  * @param {object} [params] extra parameters specific to the exchange API endpoint
939
1101
  * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
940
1102
  */
941
1103
  await this.loadMarkets();
942
1104
  await this.authenticate();
943
1105
  let type = undefined;
1106
+ let subType = undefined;
944
1107
  [type, params] = this.handleMarketTypeAndParams('watchBalance', undefined, params);
1108
+ [subType, params] = this.handleSubTypeAndParams('watchBalance', undefined, params, 'linear');
945
1109
  const isSpot = (type === 'spot');
946
1110
  const spotSubHash = 'spot:balance';
947
1111
  const swapSubHash = 'swap:private';
@@ -949,17 +1113,25 @@ export default class bingx extends bingxRest {
949
1113
  const swapMessageHash = 'swap:balance';
950
1114
  const messageHash = isSpot ? spotMessageHash : swapMessageHash;
951
1115
  const subscriptionHash = isSpot ? spotSubHash : swapSubHash;
952
- const url = this.urls['api']['ws'][type] + '?listenKey=' + this.options['listenKey'];
953
1116
  let request = undefined;
1117
+ let baseUrl = undefined;
954
1118
  const uuid = this.uuid();
955
- if (type === 'spot') {
1119
+ if (type === 'swap') {
1120
+ if (subType === 'inverse') {
1121
+ throw new NotSupported(this.id + ' watchBalance is not supported for inverse swap markets yet');
1122
+ }
1123
+ baseUrl = this.safeString(this.urls['api']['ws'], subType);
1124
+ }
1125
+ else {
1126
+ baseUrl = this.safeString(this.urls['api']['ws'], type);
956
1127
  request = {
957
1128
  'id': uuid,
958
1129
  'dataType': 'ACCOUNT_UPDATE',
959
1130
  };
960
1131
  }
1132
+ const url = baseUrl + '?listenKey=' + this.options['listenKey'];
961
1133
  const client = this.client(url);
962
- this.setBalanceCache(client, type, subscriptionHash, params);
1134
+ this.setBalanceCache(client, type, subType, subscriptionHash, params);
963
1135
  let fetchBalanceSnapshot = undefined;
964
1136
  let awaitBalanceSnapshot = undefined;
965
1137
  [fetchBalanceSnapshot, params] = this.handleOptionAndParams(params, 'watchBalance', 'fetchBalanceSnapshot', true);
@@ -969,7 +1141,7 @@ export default class bingx extends bingxRest {
969
1141
  }
970
1142
  return await this.watch(url, messageHash, request, subscriptionHash);
971
1143
  }
972
- setBalanceCache(client, type, subscriptionHash, params) {
1144
+ setBalanceCache(client, type, subType, subscriptionHash, params) {
973
1145
  if (subscriptionHash in client.subscriptions) {
974
1146
  return;
975
1147
  }
@@ -978,15 +1150,15 @@ export default class bingx extends bingxRest {
978
1150
  const messageHash = type + ':fetchBalanceSnapshot';
979
1151
  if (!(messageHash in client.futures)) {
980
1152
  client.future(messageHash);
981
- this.spawn(this.loadBalanceSnapshot, client, messageHash, type);
1153
+ this.spawn(this.loadBalanceSnapshot, client, messageHash, type, subType);
982
1154
  }
983
1155
  }
984
1156
  else {
985
1157
  this.balance[type] = {};
986
1158
  }
987
1159
  }
988
- async loadBalanceSnapshot(client, messageHash, type) {
989
- const response = await this.fetchBalance({ 'type': type });
1160
+ async loadBalanceSnapshot(client, messageHash, type, subType) {
1161
+ const response = await this.fetchBalance({ 'type': type, 'subType': subType });
990
1162
  this.balance[type] = this.extend(response, this.safeValue(this.balance, type, {}));
991
1163
  // don't remove the future from the .futures cache
992
1164
  const future = client.futures[messageHash];
@@ -1025,7 +1197,7 @@ export default class bingx extends bingxRest {
1025
1197
  await this.userAuthPrivatePutUserDataStream({ 'listenKey': listenKey }); // extend the expiry
1026
1198
  }
1027
1199
  catch (error) {
1028
- const types = ['spot', 'swap'];
1200
+ const types = ['spot', 'linear', 'inverse'];
1029
1201
  for (let i = 0; i < types.length; i++) {
1030
1202
  const type = types[i];
1031
1203
  const url = this.urls['api']['ws'][type] + '?listenKey=' + listenKey;