ccxt 4.5.5 → 4.5.6

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 (90) hide show
  1. package/README.md +4 -4
  2. package/dist/ccxt.browser.min.js +15 -15
  3. package/dist/cjs/ccxt.js +6 -6
  4. package/dist/cjs/src/abstract/toobit.js +11 -0
  5. package/dist/cjs/src/abstract/tradeogre.js +1 -1
  6. package/dist/cjs/src/backpack.js +1 -1
  7. package/dist/cjs/src/base/Exchange.js +129 -2
  8. package/dist/cjs/src/bigone.js +4 -4
  9. package/dist/cjs/src/binance.js +79 -20
  10. package/dist/cjs/src/bingx.js +5 -2
  11. package/dist/cjs/src/bitget.js +16 -9
  12. package/dist/cjs/src/bybit.js +186 -127
  13. package/dist/cjs/src/coinsph.js +4 -1
  14. package/dist/cjs/src/cryptocom.js +6 -3
  15. package/dist/cjs/src/gate.js +1 -1
  16. package/dist/cjs/src/gemini.js +2 -2
  17. package/dist/cjs/src/hyperliquid.js +3 -0
  18. package/dist/cjs/src/kraken.js +6 -2
  19. package/dist/cjs/src/kucoin.js +1 -2
  20. package/dist/cjs/src/luno.js +4 -1
  21. package/dist/cjs/src/mexc.js +4 -1
  22. package/dist/cjs/src/okcoin.js +4 -1
  23. package/dist/cjs/src/okx.js +34 -3
  24. package/dist/cjs/src/phemex.js +1 -1
  25. package/dist/cjs/src/pro/apex.js +1 -0
  26. package/dist/cjs/src/pro/backpack.js +1 -1
  27. package/dist/cjs/src/pro/binance.js +150 -19
  28. package/dist/cjs/src/pro/bitget.js +332 -76
  29. package/dist/cjs/src/pro/cex.js +1 -0
  30. package/dist/cjs/src/pro/independentreserve.js +1 -0
  31. package/dist/cjs/src/pro/mexc.js +23 -23
  32. package/dist/cjs/src/pro/okx.js +46 -10
  33. package/dist/cjs/src/pro/toobit.js +1163 -0
  34. package/dist/cjs/src/pro/tradeogre.js +1 -1
  35. package/dist/cjs/src/toobit.js +2999 -0
  36. package/dist/cjs/src/tradeogre.js +1 -1
  37. package/js/ccxt.d.ts +8 -8
  38. package/js/ccxt.js +6 -6
  39. package/js/src/abstract/myokx.d.ts +1 -0
  40. package/js/src/abstract/okx.d.ts +1 -0
  41. package/js/src/abstract/okxus.d.ts +1 -0
  42. package/js/src/abstract/toobit.d.ts +66 -0
  43. package/js/src/backpack.js +1 -1
  44. package/js/src/base/Exchange.d.ts +9 -0
  45. package/js/src/base/Exchange.js +129 -2
  46. package/js/src/bigone.js +4 -4
  47. package/js/src/binance.d.ts +9 -0
  48. package/js/src/binance.js +79 -20
  49. package/js/src/bingx.js +5 -2
  50. package/js/src/bitget.js +16 -9
  51. package/js/src/bybit.d.ts +8 -0
  52. package/js/src/bybit.js +186 -127
  53. package/js/src/coinsph.js +4 -1
  54. package/js/src/cryptocom.js +6 -3
  55. package/js/src/gate.js +1 -1
  56. package/js/src/gemini.js +2 -2
  57. package/js/src/hyperliquid.js +3 -0
  58. package/js/src/kraken.d.ts +1 -1
  59. package/js/src/kraken.js +6 -2
  60. package/js/src/kucoin.js +1 -2
  61. package/js/src/luno.js +4 -1
  62. package/js/src/mexc.js +4 -1
  63. package/js/src/okcoin.js +4 -1
  64. package/js/src/okx.js +34 -3
  65. package/js/src/phemex.js +1 -1
  66. package/js/src/pro/apex.js +1 -0
  67. package/js/src/pro/backpack.d.ts +1 -1
  68. package/js/src/pro/backpack.js +1 -1
  69. package/js/src/pro/binance.d.ts +24 -0
  70. package/js/src/pro/binance.js +150 -19
  71. package/js/src/pro/bitget.d.ts +6 -0
  72. package/js/src/pro/bitget.js +332 -76
  73. package/js/src/pro/cex.js +1 -0
  74. package/js/src/pro/independentreserve.js +1 -0
  75. package/js/src/pro/mexc.js +23 -23
  76. package/js/src/pro/okx.d.ts +7 -1
  77. package/js/src/pro/okx.js +46 -10
  78. package/js/src/pro/toobit.d.ts +174 -0
  79. package/js/src/pro/toobit.js +1162 -0
  80. package/js/src/toobit.d.ts +456 -0
  81. package/js/src/toobit.js +2992 -0
  82. package/package.json +1 -1
  83. package/dist/373.ccxt.browser.js +0 -7630
  84. package/dist/373.ccxt.browser.min.js +0 -1
  85. package/js/src/abstract/tradeogre.d.ts +0 -21
  86. package/js/src/pro/tradeogre.d.ts +0 -49
  87. package/js/src/pro/tradeogre.js +0 -278
  88. package/js/src/tradeogre.d.ts +0 -149
  89. package/js/src/tradeogre.js +0 -872
  90. /package/js/src/abstract/{tradeogre.js → toobit.js} +0 -0
package/js/src/okcoin.js CHANGED
@@ -205,6 +205,9 @@ export default class okcoin extends Exchange {
205
205
  'features': {
206
206
  'spot': {
207
207
  'sandbox': false,
208
+ 'fetchCurrencies': {
209
+ 'private': true,
210
+ },
208
211
  'createOrder': {
209
212
  'marginMode': true,
210
213
  'triggerPrice': true,
@@ -819,7 +822,7 @@ export default class okcoin extends Exchange {
819
822
  if (this.options['warnOnFetchCurrenciesWithoutAuthorization']) {
820
823
  throw new ExchangeError(this.id + ' fetchCurrencies() is a private API endpoint that requires authentication with API keys. Set the API keys on the exchange instance or exchange.options["warnOnFetchCurrenciesWithoutAuthorization"] = false to suppress this warning message.');
821
824
  }
822
- return undefined;
825
+ return {};
823
826
  }
824
827
  else {
825
828
  const response = await this.privateGetAssetCurrencies(params);
package/js/src/okx.js CHANGED
@@ -502,6 +502,7 @@ export default class okx extends Exchange {
502
502
  'account/fixed-loan/repay-borrowing-order': 5,
503
503
  'account/bills-history-archive': 72000,
504
504
  'account/move-positions': 10,
505
+ 'account/set-settle-currency': 1,
505
506
  // subaccount
506
507
  'users/subaccount/modify-apikey': 10,
507
508
  'asset/subaccount/transfer': 10,
@@ -684,6 +685,7 @@ export default class okx extends Exchange {
684
685
  '51031': InvalidOrder,
685
686
  '51046': InvalidOrder,
686
687
  '51047': InvalidOrder,
688
+ '51051': InvalidOrder,
687
689
  '51072': InvalidOrder,
688
690
  '51073': InvalidOrder,
689
691
  '51074': InvalidOrder,
@@ -823,6 +825,9 @@ export default class okx extends Exchange {
823
825
  '54008': InvalidOrder,
824
826
  '54009': InvalidOrder,
825
827
  '54011': InvalidOrder,
828
+ '54072': ExchangeError,
829
+ '54073': BadRequest,
830
+ '54074': ExchangeError,
826
831
  // Trading bot Error Code from 55100 to 55999
827
832
  '55100': InvalidOrder,
828
833
  '55101': InvalidOrder,
@@ -928,6 +933,9 @@ export default class okx extends Exchange {
928
933
  '59519': ExchangeError,
929
934
  '59642': BadRequest,
930
935
  '59643': ExchangeError,
936
+ '59683': ExchangeError,
937
+ '59684': BadRequest,
938
+ '59686': BadRequest,
931
939
  // WebSocket error Codes from 60000-63999
932
940
  '60001': AuthenticationError,
933
941
  '60002': AuthenticationError,
@@ -1294,6 +1302,9 @@ export default class okx extends Exchange {
1294
1302
  },
1295
1303
  'spot': {
1296
1304
  'extends': 'default',
1305
+ 'fetchCurrencies': {
1306
+ 'private': true,
1307
+ },
1297
1308
  },
1298
1309
  'swap': {
1299
1310
  'linear': {
@@ -1501,14 +1512,33 @@ export default class okx extends Exchange {
1501
1512
  // "data": [
1502
1513
  // {
1503
1514
  // "acctLv": "2",
1515
+ // "acctStpMode": "cancel_maker",
1504
1516
  // "autoLoan": false,
1505
1517
  // "ctIsoMode": "automatic",
1518
+ // "enableSpotBorrow": false,
1506
1519
  // "greeksType": "PA",
1520
+ // "feeType": "0",
1521
+ // "ip": "",
1522
+ // "type": "0",
1523
+ // "kycLv": "3",
1524
+ // "label": "v5 test",
1507
1525
  // "level": "Lv1",
1508
1526
  // "levelTmp": "",
1527
+ // "liquidationGear": "-1",
1528
+ // "mainUid": "44705892343619584",
1509
1529
  // "mgnIsoMode": "automatic",
1530
+ // "opAuth": "1",
1531
+ // "perm": "read_only,withdraw,trade",
1510
1532
  // "posMode": "long_short_mode",
1511
- // "uid": "88018754289672195"
1533
+ // "roleType": "0",
1534
+ // "spotBorrowAutoRepay": false,
1535
+ // "spotOffsetType": "",
1536
+ // "spotRoleType": "0",
1537
+ // "spotTraderInsts": [],
1538
+ // "traderInsts": [],
1539
+ // "uid": "44705892343619584",
1540
+ // "settleCcy": "USDT",
1541
+ // "settleCcyList": ["USD", "USDC", "USDG"],
1512
1542
  // }
1513
1543
  // ],
1514
1544
  // "msg": ""
@@ -1790,7 +1820,7 @@ export default class okx extends Exchange {
1790
1820
  // and fallback to generating the currencies from the markets
1791
1821
  const isSandboxMode = this.safeBool(this.options, 'sandboxMode', false);
1792
1822
  if (!this.checkRequiredCredentials(false) || isSandboxMode) {
1793
- return undefined;
1823
+ return {};
1794
1824
  }
1795
1825
  //
1796
1826
  // has['fetchCurrencies'] is currently set to true, but an unauthorized request returns
@@ -3154,7 +3184,8 @@ export default class okx extends Exchange {
3154
3184
  request['attachAlgoOrds'] = [attachAlgoOrd];
3155
3185
  }
3156
3186
  }
3157
- else if (trigger) {
3187
+ // algo order details
3188
+ if (trigger) {
3158
3189
  request['ordType'] = 'trigger';
3159
3190
  request['triggerPx'] = this.priceToPrecision(symbol, triggerPrice);
3160
3191
  request['orderPx'] = isMarketOrder ? '-1' : this.priceToPrecision(symbol, price);
package/js/src/phemex.js CHANGED
@@ -4067,7 +4067,7 @@ export default class phemex extends Exchange {
4067
4067
  const isCross = this.safeValue(position, 'crossMargin');
4068
4068
  return this.safePosition({
4069
4069
  'info': position,
4070
- 'id': undefined,
4070
+ 'id': this.safeString(position, 'execSeq'),
4071
4071
  'symbol': symbol,
4072
4072
  'contracts': this.parseNumber(contracts),
4073
4073
  'contractSize': contractSize,
@@ -959,6 +959,7 @@ export default class apex extends apexRest {
959
959
  }
960
960
  ping(client) {
961
961
  const timeStamp = this.milliseconds().toString();
962
+ client.lastPong = timeStamp; // server won't send a pong, so we set it here
962
963
  return {
963
964
  'args': [timeStamp],
964
965
  'op': 'ping',
@@ -197,7 +197,7 @@ export default class backpack extends backpackRest {
197
197
  unWatchOrderBook(symbol: string, params?: {}): Promise<any>;
198
198
  /**
199
199
  * @method
200
- * @name kucoin#unWatchOrderBookForSymbols
200
+ * @name backpack#unWatchOrderBookForSymbols
201
201
  * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
202
202
  * @param {string[]} symbols unified array of symbols
203
203
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -797,7 +797,7 @@ export default class backpack extends backpackRest {
797
797
  }
798
798
  /**
799
799
  * @method
800
- * @name kucoin#unWatchOrderBookForSymbols
800
+ * @name backpack#unWatchOrderBookForSymbols
801
801
  * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
802
802
  * @param {string[]} symbols unified array of symbols
803
803
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -62,6 +62,19 @@ export default class binance extends binanceRest {
62
62
  };
63
63
  };
64
64
  };
65
+ demo: {
66
+ ws: {
67
+ spot: string;
68
+ margin: string;
69
+ future: string;
70
+ delivery: string;
71
+ 'ws-api': {
72
+ spot: string;
73
+ future: string;
74
+ delivery: string;
75
+ };
76
+ };
77
+ };
65
78
  api: {
66
79
  ws: {
67
80
  spot: string;
@@ -149,6 +162,7 @@ export default class binance extends binanceRest {
149
162
  };
150
163
  };
151
164
  requestId(url: any): any;
165
+ isSpotUrl(client: Client): boolean;
152
166
  stream(type: Str, subscriptionHash: Str, numSubscriptions?: number): string;
153
167
  /**
154
168
  * @method
@@ -541,6 +555,14 @@ export default class binance extends binanceRest {
541
555
  handleTickersAndBidsAsks(client: Client, message: any, methodType: any): void;
542
556
  getMessageHash(channelName: string, symbol: Str, isBidAsk: boolean): string;
543
557
  signParams(params?: {}): any;
558
+ /**
559
+ * Ensures a User Data Stream WebSocket subscription is active for the specified scope
560
+ * @param marketType {string} only support on 'spot'
561
+ * @see {@link https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/user-data-stream-requests#subscribe-to-user-data-stream-through-signature-subscription-user_data Binance User Data Stream Documentation}
562
+ * @returns Promise<number> The subscription ID for the user data stream
563
+ */
564
+ ensureUserDataStreamWsSubscribeSignature(marketType?: string): Promise<void>;
565
+ handleUserDataStreamSubscribe(client: Client, message: any): void;
544
566
  authenticate(params?: {}): Promise<void>;
545
567
  keepAliveListenKey(params?: {}): Promise<void>;
546
568
  setBalanceCache(client: Client, type: any, isPortfolioMargin?: boolean): void;
@@ -596,6 +618,7 @@ export default class binance extends binanceRest {
596
618
  */
597
619
  watchBalance(params?: {}): Promise<Balances>;
598
620
  handleBalance(client: Client, message: any): void;
621
+ getAccountTypeFromSubscriptions(subscriptions: string[]): string;
599
622
  getMarketType(method: any, market: any, params?: {}): any;
600
623
  /**
601
624
  * @method
@@ -792,5 +815,6 @@ export default class binance extends binanceRest {
792
815
  handleOrder(client: Client, message: any): void;
793
816
  handleAcountUpdate(client: any, message: any): void;
794
817
  handleWsError(client: Client, message: any): void;
818
+ handleEventStreamTerminated(client: Client, message: any): void;
795
819
  handleMessage(client: Client, message: any): void;
796
820
  }
@@ -73,6 +73,19 @@ export default class binance extends binanceRest {
73
73
  },
74
74
  },
75
75
  },
76
+ 'demo': {
77
+ 'ws': {
78
+ 'spot': 'wss://demo-stream.binance.com/ws',
79
+ 'margin': 'wss://demo-stream.binance.com/ws',
80
+ 'future': 'wss://fstream.binancefuture.com/ws',
81
+ 'delivery': 'wss://dstream.binancefuture.com/ws',
82
+ 'ws-api': {
83
+ 'spot': 'wss://demo-ws-api.binance.com/ws-api/v3',
84
+ 'future': 'wss://testnet.binancefuture.com/ws-fapi/v1',
85
+ 'delivery': 'wss://testnet.binancefuture.com/ws-dapi/v1',
86
+ },
87
+ },
88
+ },
76
89
  'api': {
77
90
  'ws': {
78
91
  'spot': 'wss://stream.binance.com:9443/ws',
@@ -170,6 +183,9 @@ export default class binance extends binanceRest {
170
183
  this.options['requestId'][url] = newValue;
171
184
  return newValue;
172
185
  }
186
+ isSpotUrl(client) {
187
+ return (client.url.indexOf('/stream') > -1) || (client.url.indexOf('demo-stream') > -1);
188
+ }
173
189
  stream(type, subscriptionHash, numSubscriptions = 1) {
174
190
  const streamBySubscriptionsHash = this.safeDict(this.options, 'streamBySubscriptionsHash', this.createSafeDictionary());
175
191
  let stream = this.safeString(streamBySubscriptionsHash, subscriptionHash);
@@ -899,7 +915,7 @@ export default class binance extends binanceRest {
899
915
  // ]
900
916
  // }
901
917
  //
902
- const isSpot = (client.url.indexOf('/stream') > -1);
918
+ const isSpot = this.isSpotUrl(client);
903
919
  const marketType = (isSpot) ? 'spot' : 'contract';
904
920
  const marketId = this.safeString(message, 's');
905
921
  const market = this.safeMarket(marketId, undefined, undefined, marketType);
@@ -1359,7 +1375,7 @@ export default class binance extends binanceRest {
1359
1375
  handleTrade(client, message) {
1360
1376
  // the trade streams push raw trade information in real-time
1361
1377
  // each trade has a unique buyer and seller
1362
- const isSpot = (client.url.indexOf('/stream') > -1);
1378
+ const isSpot = this.isSpotUrl(client);
1363
1379
  const marketType = (isSpot) ? 'spot' : 'contract';
1364
1380
  const marketId = this.safeString(message, 's');
1365
1381
  const market = this.safeMarket(marketId, undefined, undefined, marketType);
@@ -1601,7 +1617,7 @@ export default class binance extends binanceRest {
1601
1617
  this.safeFloat(kline, 'c'),
1602
1618
  this.safeFloat(kline, 'v'),
1603
1619
  ];
1604
- const isSpot = (client.url.indexOf('/stream') > -1);
1620
+ const isSpot = this.isSpotUrl(client);
1605
1621
  const marketType = (isSpot) ? 'spot' : 'contract';
1606
1622
  const symbol = this.safeSymbol(marketId, undefined, undefined, marketType);
1607
1623
  const messageHash = 'ohlcv::' + symbol + '::' + unifiedTimeframe;
@@ -2246,7 +2262,7 @@ export default class binance extends binanceRest {
2246
2262
  this.handleTickersAndBidsAsks(client, message, 'tickers');
2247
2263
  }
2248
2264
  handleTickersAndBidsAsks(client, message, methodType) {
2249
- const isSpot = (client.url.indexOf('/stream') > -1);
2265
+ const isSpot = this.isSpotUrl(client);
2250
2266
  const marketType = (isSpot) ? 'spot' : 'contract';
2251
2267
  const isBidAsk = (methodType === 'bidasks');
2252
2268
  let channelName = undefined;
@@ -2329,6 +2345,58 @@ export default class binance extends binanceRest {
2329
2345
  extendedParams['signature'] = signature;
2330
2346
  return extendedParams;
2331
2347
  }
2348
+ /**
2349
+ * Ensures a User Data Stream WebSocket subscription is active for the specified scope
2350
+ * @param marketType {string} only support on 'spot'
2351
+ * @see {@link https://developers.binance.com/docs/binance-spot-api-docs/websocket-api/user-data-stream-requests#subscribe-to-user-data-stream-through-signature-subscription-user_data Binance User Data Stream Documentation}
2352
+ * @returns Promise<number> The subscription ID for the user data stream
2353
+ */
2354
+ async ensureUserDataStreamWsSubscribeSignature(marketType = 'spot') {
2355
+ const url = this.urls['api']['ws']['ws-api'][marketType];
2356
+ const client = this.client(url);
2357
+ const subscriptions = client.subscriptions;
2358
+ const subscriptionsKeys = Object.keys(subscriptions);
2359
+ const accountType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
2360
+ if (accountType === marketType) {
2361
+ return;
2362
+ }
2363
+ client.subscriptions[marketType] = true;
2364
+ const requestId = this.requestId(url);
2365
+ const messageHash = requestId.toString();
2366
+ const message = {
2367
+ 'id': messageHash,
2368
+ 'method': 'userDataStream.subscribe.signature',
2369
+ 'params': this.signParams({}),
2370
+ };
2371
+ const subscription = {
2372
+ 'id': messageHash,
2373
+ 'method': this.handleUserDataStreamSubscribe,
2374
+ 'subscription': marketType,
2375
+ };
2376
+ await this.watch(url, messageHash, message, messageHash, subscription);
2377
+ }
2378
+ handleUserDataStreamSubscribe(client, message) {
2379
+ //
2380
+ // {
2381
+ // "id": 1,
2382
+ // "status": 200,
2383
+ // "result": {
2384
+ // "subscriptionId": 0
2385
+ // }
2386
+ // }
2387
+ //
2388
+ const messageHash = this.safeString(message, 'id');
2389
+ const subscriptions = client.subscriptions;
2390
+ const subscriptionsKeys = Object.keys(subscriptions);
2391
+ const accountType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
2392
+ const result = this.safeDict(message, 'result', {});
2393
+ const subscriptionId = this.safeInteger(result, 'subscriptionId');
2394
+ if (subscriptionId === undefined) {
2395
+ delete client.subscriptions[accountType];
2396
+ client.reject(message, accountType);
2397
+ }
2398
+ client.resolve(message, messageHash);
2399
+ }
2332
2400
  async authenticate(params = {}) {
2333
2401
  const time = this.milliseconds();
2334
2402
  let type = undefined;
@@ -2343,6 +2411,11 @@ export default class binance extends binanceRest {
2343
2411
  else if (this.isInverse(type, subType)) {
2344
2412
  type = 'delivery';
2345
2413
  }
2414
+ // For spot use WebSocket API signature subscription
2415
+ if (type === 'spot') {
2416
+ await this.ensureUserDataStreamWsSubscribeSignature('spot');
2417
+ return;
2418
+ }
2346
2419
  let marginMode = undefined;
2347
2420
  [marginMode, params] = this.handleMarginModeAndParams('authenticate', params);
2348
2421
  const isIsolatedMargin = (marginMode === 'isolated');
@@ -2470,7 +2543,7 @@ export default class binance extends binanceRest {
2470
2543
  }
2471
2544
  }
2472
2545
  setBalanceCache(client, type, isPortfolioMargin = false) {
2473
- if (type in client.subscriptions) {
2546
+ if ((type in client.subscriptions) && (type in this.balance)) {
2474
2547
  return;
2475
2548
  }
2476
2549
  const options = this.safeValue(this.options, 'watchBalance');
@@ -2734,11 +2807,18 @@ export default class binance extends binanceRest {
2734
2807
  else if (this.isInverse(type, subType)) {
2735
2808
  type = 'delivery';
2736
2809
  }
2810
+ let url = '';
2737
2811
  let urlType = type;
2738
- if (isPortfolioMargin) {
2739
- urlType = 'papi';
2812
+ if (type === 'spot') {
2813
+ // route to WebSocket API connection where the user data stream is subscribed
2814
+ url = this.urls['api']['ws']['ws-api'][type];
2815
+ }
2816
+ else {
2817
+ if (isPortfolioMargin) {
2818
+ urlType = 'papi';
2819
+ }
2820
+ url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
2740
2821
  }
2741
- const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
2742
2822
  const client = this.client(url);
2743
2823
  this.setBalanceCache(client, type, isPortfolioMargin);
2744
2824
  this.setPositionsCache(client, type, undefined, isPortfolioMargin);
@@ -2820,9 +2900,9 @@ export default class binance extends binanceRest {
2820
2900
  //
2821
2901
  const wallet = this.safeString(this.options, 'wallet', 'wb'); // cw for cross wallet
2822
2902
  // each account is connected to a different endpoint
2823
- // and has exactly one subscriptionhash which is the account type
2824
- const subscriptions = Object.keys(client.subscriptions);
2825
- const accountType = subscriptions[0];
2903
+ const subscriptions = client.subscriptions;
2904
+ const subscriptionsKeys = Object.keys(subscriptions);
2905
+ const accountType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
2826
2906
  const messageHash = accountType + ':balance';
2827
2907
  if (this.balance[accountType] === undefined) {
2828
2908
  this.balance[accountType] = {};
@@ -2866,6 +2946,17 @@ export default class binance extends binanceRest {
2866
2946
  this.balance[accountType] = this.safeBalance(this.balance[accountType]);
2867
2947
  client.resolve(this.balance[accountType], messageHash);
2868
2948
  }
2949
+ getAccountTypeFromSubscriptions(subscriptions) {
2950
+ let accountType = '';
2951
+ for (let i = 0; i < subscriptions.length; i++) {
2952
+ const subscription = subscriptions[i];
2953
+ if ((subscription === 'spot') || (subscription === 'margin') || (subscription === 'future') || (subscription === 'delivery')) {
2954
+ accountType = subscription;
2955
+ break;
2956
+ }
2957
+ }
2958
+ return accountType;
2959
+ }
2869
2960
  getMarketType(method, market, params = {}) {
2870
2961
  let type = undefined;
2871
2962
  [type, params] = this.handleMarketTypeAndParams(method, market, params);
@@ -3467,10 +3558,17 @@ export default class binance extends binanceRest {
3467
3558
  }
3468
3559
  let isPortfolioMargin = undefined;
3469
3560
  [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'watchOrders', 'papi', 'portfolioMargin', false);
3470
- if (isPortfolioMargin) {
3471
- urlType = 'papi';
3561
+ let url = '';
3562
+ if (type === 'spot') {
3563
+ // route orders to ws-api user data stream
3564
+ url = this.urls['api']['ws']['ws-api'][type];
3565
+ }
3566
+ else {
3567
+ if (isPortfolioMargin) {
3568
+ urlType = 'papi';
3569
+ }
3570
+ url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
3472
3571
  }
3473
- const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
3474
3572
  const client = this.client(url);
3475
3573
  this.setBalanceCache(client, type, isPortfolioMargin);
3476
3574
  this.setPositionsCache(client, type, undefined, isPortfolioMargin);
@@ -3857,8 +3955,9 @@ export default class binance extends binanceRest {
3857
3955
  //
3858
3956
  // each account is connected to a different endpoint
3859
3957
  // and has exactly one subscriptionhash which is the account type
3860
- const subscriptions = Object.keys(client.subscriptions);
3861
- const accountType = subscriptions[0];
3958
+ const subscriptions = client.subscriptions;
3959
+ const subscriptionsKeys = Object.keys(subscriptions);
3960
+ const accountType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
3862
3961
  if (this.positions === undefined) {
3863
3962
  this.positions = {};
3864
3963
  }
@@ -4135,10 +4234,16 @@ export default class binance extends binanceRest {
4135
4234
  }
4136
4235
  let isPortfolioMargin = undefined;
4137
4236
  [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'watchMyTrades', 'papi', 'portfolioMargin', false);
4138
- if (isPortfolioMargin) {
4139
- urlType = 'papi';
4237
+ let url = '';
4238
+ if (type === 'spot') {
4239
+ url = this.urls['api']['ws']['ws-api'][type];
4240
+ }
4241
+ else {
4242
+ if (isPortfolioMargin) {
4243
+ urlType = 'papi';
4244
+ }
4245
+ url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
4140
4246
  }
4141
- const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
4142
4247
  const client = this.client(url);
4143
4248
  this.setBalanceCache(client, type, isPortfolioMargin);
4144
4249
  this.setPositionsCache(client, type, undefined, isPortfolioMargin);
@@ -4284,8 +4389,12 @@ export default class binance extends binanceRest {
4284
4389
  for (let i = 0; i < subscriptionKeys.length; i++) {
4285
4390
  const subscriptionHash = subscriptionKeys[i];
4286
4391
  const subscriptionId = this.safeString(client.subscriptions[subscriptionHash], 'id');
4392
+ const subscription = this.safeString(client.subscriptions[subscriptionHash], 'subscription');
4287
4393
  if (id === subscriptionId) {
4288
4394
  client.reject(e, subscriptionHash);
4395
+ if (subscription !== undefined) {
4396
+ delete client.subscriptions[subscription];
4397
+ }
4289
4398
  }
4290
4399
  }
4291
4400
  }
@@ -4298,14 +4407,35 @@ export default class binance extends binanceRest {
4298
4407
  client.reset(message);
4299
4408
  }
4300
4409
  }
4410
+ handleEventStreamTerminated(client, message) {
4411
+ //
4412
+ // {
4413
+ // e: 'eventStreamTerminated',
4414
+ // E: 1757896885229
4415
+ // }
4416
+ //
4417
+ const event = this.safeString(message, 'e');
4418
+ const subscriptions = client.subscriptions;
4419
+ const subscriptionsKeys = Object.keys(subscriptions);
4420
+ const accountType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
4421
+ if (event === 'eventStreamTerminated') {
4422
+ delete client.subscriptions[accountType];
4423
+ client.reject(message, accountType);
4424
+ }
4425
+ }
4301
4426
  handleMessage(client, message) {
4302
4427
  // handle WebSocketAPI
4428
+ const eventMsg = this.safeDict(message, 'event');
4429
+ if (eventMsg !== undefined) {
4430
+ message = eventMsg;
4431
+ }
4303
4432
  const status = this.safeString(message, 'status');
4304
4433
  const error = this.safeValue(message, 'error');
4305
4434
  if ((error !== undefined) || (status !== undefined && status !== '200')) {
4306
4435
  this.handleWsError(client, message);
4307
4436
  return;
4308
4437
  }
4438
+ // user subscription wraps message in subscriptionId and event
4309
4439
  const id = this.safeString(message, 'id');
4310
4440
  const subscriptions = this.safeValue(client.subscriptions, id);
4311
4441
  let method = this.safeValue(subscriptions, 'method');
@@ -4340,6 +4470,7 @@ export default class binance extends binanceRest {
4340
4470
  'executionReport': this.handleOrderUpdate,
4341
4471
  'ORDER_TRADE_UPDATE': this.handleOrderUpdate,
4342
4472
  'forceOrder': this.handleLiquidation,
4473
+ 'eventStreamTerminated': this.handleEventStreamTerminated,
4343
4474
  'externalLockUpdate': this.handleBalance,
4344
4475
  };
4345
4476
  let event = this.safeString(message, 'e');
@@ -192,11 +192,13 @@ export default class bitget extends bitgetRest {
192
192
  * @name bitget#watchPositions
193
193
  * @description watch all open positions
194
194
  * @see https://www.bitget.com/api-doc/contract/websocket/private/Positions-Channel
195
+ * @see https://www.bitget.com/api-doc/uta/websocket/private/Positions-Channel
195
196
  * @param {string[]|undefined} symbols list of unified market symbols
196
197
  * @param {int} [since] the earliest time in ms to fetch positions for
197
198
  * @param {int} [limit] the maximum number of positions to retrieve
198
199
  * @param {object} params extra parameters specific to the exchange API endpoint
199
200
  * @param {string} [params.instType] one of 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES', default is 'USDT-FUTURES'
201
+ * @param {boolean} [params.uta] set to true for the unified trading account (uta), defaults to false
200
202
  * @returns {object[]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
201
203
  */
202
204
  watchPositions(symbols?: Strings, since?: Int, limit?: Int, params?: {}): Promise<Position[]>;
@@ -211,6 +213,7 @@ export default class bitget extends bitgetRest {
211
213
  * @see https://www.bitget.com/api-doc/contract/websocket/private/Plan-Order-Channel
212
214
  * @see https://www.bitget.com/api-doc/margin/cross/websocket/private/Cross-Orders
213
215
  * @see https://www.bitget.com/api-doc/margin/isolated/websocket/private/Isolate-Orders
216
+ * @see https://www.bitget.com/api-doc/uta/websocket/private/Order-Channel
214
217
  * @param {string} symbol unified market symbol of the market orders were made in
215
218
  * @param {int} [since] the earliest time in ms to fetch orders for
216
219
  * @param {int} [limit] the maximum number of order structures to retrieve
@@ -219,6 +222,7 @@ export default class bitget extends bitgetRest {
219
222
  * @param {string} [params.marginMode] 'isolated' or 'cross' for watching spot margin orders]
220
223
  * @param {string} [params.type] 'spot', 'swap'
221
224
  * @param {string} [params.subType] 'linear', 'inverse'
225
+ * @param {boolean} [params.uta] set to true for the unified trading account (uta), defaults to false
222
226
  * @returns {object[]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
223
227
  */
224
228
  watchOrders(symbol?: Str, since?: Int, limit?: Int, params?: {}): Promise<Order[]>;
@@ -248,10 +252,12 @@ export default class bitget extends bitgetRest {
248
252
  * @see https://www.bitget.com/api-doc/contract/websocket/private/Account-Channel
249
253
  * @see https://www.bitget.com/api-doc/margin/cross/websocket/private/Margin-Cross-Account-Assets
250
254
  * @see https://www.bitget.com/api-doc/margin/isolated/websocket/private/Margin-isolated-account-assets
255
+ * @see https://www.bitget.com/api-doc/uta/websocket/private/Account-Channel
251
256
  * @param {object} [params] extra parameters specific to the exchange API endpoint
252
257
  * @param {str} [params.type] spot or contract if not provided this.options['defaultType'] is used
253
258
  * @param {string} [params.instType] one of 'SPOT', 'MARGIN', 'USDT-FUTURES', 'USDC-FUTURES', 'COIN-FUTURES', 'SUSDT-FUTURES', 'SUSDC-FUTURES' or 'SCOIN-FUTURES'
254
259
  * @param {string} [params.marginMode] 'isolated' or 'cross' for watching spot margin balances
260
+ * @param {boolean} [params.uta] set to true for the unified trading account (uta), defaults to false
255
261
  * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
256
262
  */
257
263
  watchBalance(params?: {}): Promise<Balances>;