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
@@ -507,6 +507,7 @@ class okx extends okx$1["default"] {
507
507
  'account/fixed-loan/repay-borrowing-order': 5,
508
508
  'account/bills-history-archive': 72000,
509
509
  'account/move-positions': 10,
510
+ 'account/set-settle-currency': 1,
510
511
  // subaccount
511
512
  'users/subaccount/modify-apikey': 10,
512
513
  'asset/subaccount/transfer': 10,
@@ -689,6 +690,7 @@ class okx extends okx$1["default"] {
689
690
  '51031': errors.InvalidOrder,
690
691
  '51046': errors.InvalidOrder,
691
692
  '51047': errors.InvalidOrder,
693
+ '51051': errors.InvalidOrder,
692
694
  '51072': errors.InvalidOrder,
693
695
  '51073': errors.InvalidOrder,
694
696
  '51074': errors.InvalidOrder,
@@ -828,6 +830,9 @@ class okx extends okx$1["default"] {
828
830
  '54008': errors.InvalidOrder,
829
831
  '54009': errors.InvalidOrder,
830
832
  '54011': errors.InvalidOrder,
833
+ '54072': errors.ExchangeError,
834
+ '54073': errors.BadRequest,
835
+ '54074': errors.ExchangeError,
831
836
  // Trading bot Error Code from 55100 to 55999
832
837
  '55100': errors.InvalidOrder,
833
838
  '55101': errors.InvalidOrder,
@@ -933,6 +938,9 @@ class okx extends okx$1["default"] {
933
938
  '59519': errors.ExchangeError,
934
939
  '59642': errors.BadRequest,
935
940
  '59643': errors.ExchangeError,
941
+ '59683': errors.ExchangeError,
942
+ '59684': errors.BadRequest,
943
+ '59686': errors.BadRequest,
936
944
  // WebSocket error Codes from 60000-63999
937
945
  '60001': errors.AuthenticationError,
938
946
  '60002': errors.AuthenticationError,
@@ -1299,6 +1307,9 @@ class okx extends okx$1["default"] {
1299
1307
  },
1300
1308
  'spot': {
1301
1309
  'extends': 'default',
1310
+ 'fetchCurrencies': {
1311
+ 'private': true,
1312
+ },
1302
1313
  },
1303
1314
  'swap': {
1304
1315
  'linear': {
@@ -1506,14 +1517,33 @@ class okx extends okx$1["default"] {
1506
1517
  // "data": [
1507
1518
  // {
1508
1519
  // "acctLv": "2",
1520
+ // "acctStpMode": "cancel_maker",
1509
1521
  // "autoLoan": false,
1510
1522
  // "ctIsoMode": "automatic",
1523
+ // "enableSpotBorrow": false,
1511
1524
  // "greeksType": "PA",
1525
+ // "feeType": "0",
1526
+ // "ip": "",
1527
+ // "type": "0",
1528
+ // "kycLv": "3",
1529
+ // "label": "v5 test",
1512
1530
  // "level": "Lv1",
1513
1531
  // "levelTmp": "",
1532
+ // "liquidationGear": "-1",
1533
+ // "mainUid": "44705892343619584",
1514
1534
  // "mgnIsoMode": "automatic",
1535
+ // "opAuth": "1",
1536
+ // "perm": "read_only,withdraw,trade",
1515
1537
  // "posMode": "long_short_mode",
1516
- // "uid": "88018754289672195"
1538
+ // "roleType": "0",
1539
+ // "spotBorrowAutoRepay": false,
1540
+ // "spotOffsetType": "",
1541
+ // "spotRoleType": "0",
1542
+ // "spotTraderInsts": [],
1543
+ // "traderInsts": [],
1544
+ // "uid": "44705892343619584",
1545
+ // "settleCcy": "USDT",
1546
+ // "settleCcyList": ["USD", "USDC", "USDG"],
1517
1547
  // }
1518
1548
  // ],
1519
1549
  // "msg": ""
@@ -1795,7 +1825,7 @@ class okx extends okx$1["default"] {
1795
1825
  // and fallback to generating the currencies from the markets
1796
1826
  const isSandboxMode = this.safeBool(this.options, 'sandboxMode', false);
1797
1827
  if (!this.checkRequiredCredentials(false) || isSandboxMode) {
1798
- return undefined;
1828
+ return {};
1799
1829
  }
1800
1830
  //
1801
1831
  // has['fetchCurrencies'] is currently set to true, but an unauthorized request returns
@@ -3159,7 +3189,8 @@ class okx extends okx$1["default"] {
3159
3189
  request['attachAlgoOrds'] = [attachAlgoOrd];
3160
3190
  }
3161
3191
  }
3162
- else if (trigger) {
3192
+ // algo order details
3193
+ if (trigger) {
3163
3194
  request['ordType'] = 'trigger';
3164
3195
  request['triggerPx'] = this.priceToPrecision(symbol, triggerPrice);
3165
3196
  request['orderPx'] = isMarketOrder ? '-1' : this.priceToPrecision(symbol, price);
@@ -4072,7 +4072,7 @@ class phemex extends phemex$1["default"] {
4072
4072
  const isCross = this.safeValue(position, 'crossMargin');
4073
4073
  return this.safePosition({
4074
4074
  'info': position,
4075
- 'id': undefined,
4075
+ 'id': this.safeString(position, 'execSeq'),
4076
4076
  'symbol': symbol,
4077
4077
  'contracts': this.parseNumber(contracts),
4078
4078
  'contractSize': contractSize,
@@ -964,6 +964,7 @@ class apex extends apex$1["default"] {
964
964
  }
965
965
  ping(client) {
966
966
  const timeStamp = this.milliseconds().toString();
967
+ client.lastPong = timeStamp; // server won't send a pong, so we set it here
967
968
  return {
968
969
  'args': [timeStamp],
969
970
  'op': 'ping',
@@ -802,7 +802,7 @@ class backpack extends backpack$1["default"] {
802
802
  }
803
803
  /**
804
804
  * @method
805
- * @name kucoin#unWatchOrderBookForSymbols
805
+ * @name backpack#unWatchOrderBookForSymbols
806
806
  * @description unWatches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
807
807
  * @param {string[]} symbols unified array of symbols
808
808
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -78,6 +78,19 @@ class binance extends binance$1["default"] {
78
78
  },
79
79
  },
80
80
  },
81
+ 'demo': {
82
+ 'ws': {
83
+ 'spot': 'wss://demo-stream.binance.com/ws',
84
+ 'margin': 'wss://demo-stream.binance.com/ws',
85
+ 'future': 'wss://fstream.binancefuture.com/ws',
86
+ 'delivery': 'wss://dstream.binancefuture.com/ws',
87
+ 'ws-api': {
88
+ 'spot': 'wss://demo-ws-api.binance.com/ws-api/v3',
89
+ 'future': 'wss://testnet.binancefuture.com/ws-fapi/v1',
90
+ 'delivery': 'wss://testnet.binancefuture.com/ws-dapi/v1',
91
+ },
92
+ },
93
+ },
81
94
  'api': {
82
95
  'ws': {
83
96
  'spot': 'wss://stream.binance.com:9443/ws',
@@ -175,6 +188,9 @@ class binance extends binance$1["default"] {
175
188
  this.options['requestId'][url] = newValue;
176
189
  return newValue;
177
190
  }
191
+ isSpotUrl(client) {
192
+ return (client.url.indexOf('/stream') > -1) || (client.url.indexOf('demo-stream') > -1);
193
+ }
178
194
  stream(type, subscriptionHash, numSubscriptions = 1) {
179
195
  const streamBySubscriptionsHash = this.safeDict(this.options, 'streamBySubscriptionsHash', this.createSafeDictionary());
180
196
  let stream = this.safeString(streamBySubscriptionsHash, subscriptionHash);
@@ -904,7 +920,7 @@ class binance extends binance$1["default"] {
904
920
  // ]
905
921
  // }
906
922
  //
907
- const isSpot = (client.url.indexOf('/stream') > -1);
923
+ const isSpot = this.isSpotUrl(client);
908
924
  const marketType = (isSpot) ? 'spot' : 'contract';
909
925
  const marketId = this.safeString(message, 's');
910
926
  const market = this.safeMarket(marketId, undefined, undefined, marketType);
@@ -1364,7 +1380,7 @@ class binance extends binance$1["default"] {
1364
1380
  handleTrade(client, message) {
1365
1381
  // the trade streams push raw trade information in real-time
1366
1382
  // each trade has a unique buyer and seller
1367
- const isSpot = (client.url.indexOf('/stream') > -1);
1383
+ const isSpot = this.isSpotUrl(client);
1368
1384
  const marketType = (isSpot) ? 'spot' : 'contract';
1369
1385
  const marketId = this.safeString(message, 's');
1370
1386
  const market = this.safeMarket(marketId, undefined, undefined, marketType);
@@ -1606,7 +1622,7 @@ class binance extends binance$1["default"] {
1606
1622
  this.safeFloat(kline, 'c'),
1607
1623
  this.safeFloat(kline, 'v'),
1608
1624
  ];
1609
- const isSpot = (client.url.indexOf('/stream') > -1);
1625
+ const isSpot = this.isSpotUrl(client);
1610
1626
  const marketType = (isSpot) ? 'spot' : 'contract';
1611
1627
  const symbol = this.safeSymbol(marketId, undefined, undefined, marketType);
1612
1628
  const messageHash = 'ohlcv::' + symbol + '::' + unifiedTimeframe;
@@ -2248,7 +2264,7 @@ class binance extends binance$1["default"] {
2248
2264
  this.handleTickersAndBidsAsks(client, message, 'tickers');
2249
2265
  }
2250
2266
  handleTickersAndBidsAsks(client, message, methodType) {
2251
- const isSpot = (client.url.indexOf('/stream') > -1);
2267
+ const isSpot = this.isSpotUrl(client);
2252
2268
  const marketType = (isSpot) ? 'spot' : 'contract';
2253
2269
  const isBidAsk = (methodType === 'bidasks');
2254
2270
  let channelName = undefined;
@@ -2331,6 +2347,58 @@ class binance extends binance$1["default"] {
2331
2347
  extendedParams['signature'] = signature;
2332
2348
  return extendedParams;
2333
2349
  }
2350
+ /**
2351
+ * Ensures a User Data Stream WebSocket subscription is active for the specified scope
2352
+ * @param marketType {string} only support on 'spot'
2353
+ * @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}
2354
+ * @returns Promise<number> The subscription ID for the user data stream
2355
+ */
2356
+ async ensureUserDataStreamWsSubscribeSignature(marketType = 'spot') {
2357
+ const url = this.urls['api']['ws']['ws-api'][marketType];
2358
+ const client = this.client(url);
2359
+ const subscriptions = client.subscriptions;
2360
+ const subscriptionsKeys = Object.keys(subscriptions);
2361
+ const accountType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
2362
+ if (accountType === marketType) {
2363
+ return;
2364
+ }
2365
+ client.subscriptions[marketType] = true;
2366
+ const requestId = this.requestId(url);
2367
+ const messageHash = requestId.toString();
2368
+ const message = {
2369
+ 'id': messageHash,
2370
+ 'method': 'userDataStream.subscribe.signature',
2371
+ 'params': this.signParams({}),
2372
+ };
2373
+ const subscription = {
2374
+ 'id': messageHash,
2375
+ 'method': this.handleUserDataStreamSubscribe,
2376
+ 'subscription': marketType,
2377
+ };
2378
+ await this.watch(url, messageHash, message, messageHash, subscription);
2379
+ }
2380
+ handleUserDataStreamSubscribe(client, message) {
2381
+ //
2382
+ // {
2383
+ // "id": 1,
2384
+ // "status": 200,
2385
+ // "result": {
2386
+ // "subscriptionId": 0
2387
+ // }
2388
+ // }
2389
+ //
2390
+ const messageHash = this.safeString(message, 'id');
2391
+ const subscriptions = client.subscriptions;
2392
+ const subscriptionsKeys = Object.keys(subscriptions);
2393
+ const accountType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
2394
+ const result = this.safeDict(message, 'result', {});
2395
+ const subscriptionId = this.safeInteger(result, 'subscriptionId');
2396
+ if (subscriptionId === undefined) {
2397
+ delete client.subscriptions[accountType];
2398
+ client.reject(message, accountType);
2399
+ }
2400
+ client.resolve(message, messageHash);
2401
+ }
2334
2402
  async authenticate(params = {}) {
2335
2403
  const time = this.milliseconds();
2336
2404
  let type = undefined;
@@ -2345,6 +2413,11 @@ class binance extends binance$1["default"] {
2345
2413
  else if (this.isInverse(type, subType)) {
2346
2414
  type = 'delivery';
2347
2415
  }
2416
+ // For spot use WebSocket API signature subscription
2417
+ if (type === 'spot') {
2418
+ await this.ensureUserDataStreamWsSubscribeSignature('spot');
2419
+ return;
2420
+ }
2348
2421
  let marginMode = undefined;
2349
2422
  [marginMode, params] = this.handleMarginModeAndParams('authenticate', params);
2350
2423
  const isIsolatedMargin = (marginMode === 'isolated');
@@ -2472,7 +2545,7 @@ class binance extends binance$1["default"] {
2472
2545
  }
2473
2546
  }
2474
2547
  setBalanceCache(client, type, isPortfolioMargin = false) {
2475
- if (type in client.subscriptions) {
2548
+ if ((type in client.subscriptions) && (type in this.balance)) {
2476
2549
  return;
2477
2550
  }
2478
2551
  const options = this.safeValue(this.options, 'watchBalance');
@@ -2736,11 +2809,18 @@ class binance extends binance$1["default"] {
2736
2809
  else if (this.isInverse(type, subType)) {
2737
2810
  type = 'delivery';
2738
2811
  }
2812
+ let url = '';
2739
2813
  let urlType = type;
2740
- if (isPortfolioMargin) {
2741
- urlType = 'papi';
2814
+ if (type === 'spot') {
2815
+ // route to WebSocket API connection where the user data stream is subscribed
2816
+ url = this.urls['api']['ws']['ws-api'][type];
2817
+ }
2818
+ else {
2819
+ if (isPortfolioMargin) {
2820
+ urlType = 'papi';
2821
+ }
2822
+ url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
2742
2823
  }
2743
- const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
2744
2824
  const client = this.client(url);
2745
2825
  this.setBalanceCache(client, type, isPortfolioMargin);
2746
2826
  this.setPositionsCache(client, type, undefined, isPortfolioMargin);
@@ -2822,9 +2902,9 @@ class binance extends binance$1["default"] {
2822
2902
  //
2823
2903
  const wallet = this.safeString(this.options, 'wallet', 'wb'); // cw for cross wallet
2824
2904
  // each account is connected to a different endpoint
2825
- // and has exactly one subscriptionhash which is the account type
2826
- const subscriptions = Object.keys(client.subscriptions);
2827
- const accountType = subscriptions[0];
2905
+ const subscriptions = client.subscriptions;
2906
+ const subscriptionsKeys = Object.keys(subscriptions);
2907
+ const accountType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
2828
2908
  const messageHash = accountType + ':balance';
2829
2909
  if (this.balance[accountType] === undefined) {
2830
2910
  this.balance[accountType] = {};
@@ -2868,6 +2948,17 @@ class binance extends binance$1["default"] {
2868
2948
  this.balance[accountType] = this.safeBalance(this.balance[accountType]);
2869
2949
  client.resolve(this.balance[accountType], messageHash);
2870
2950
  }
2951
+ getAccountTypeFromSubscriptions(subscriptions) {
2952
+ let accountType = '';
2953
+ for (let i = 0; i < subscriptions.length; i++) {
2954
+ const subscription = subscriptions[i];
2955
+ if ((subscription === 'spot') || (subscription === 'margin') || (subscription === 'future') || (subscription === 'delivery')) {
2956
+ accountType = subscription;
2957
+ break;
2958
+ }
2959
+ }
2960
+ return accountType;
2961
+ }
2871
2962
  getMarketType(method, market, params = {}) {
2872
2963
  let type = undefined;
2873
2964
  [type, params] = this.handleMarketTypeAndParams(method, market, params);
@@ -3469,10 +3560,17 @@ class binance extends binance$1["default"] {
3469
3560
  }
3470
3561
  let isPortfolioMargin = undefined;
3471
3562
  [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'watchOrders', 'papi', 'portfolioMargin', false);
3472
- if (isPortfolioMargin) {
3473
- urlType = 'papi';
3563
+ let url = '';
3564
+ if (type === 'spot') {
3565
+ // route orders to ws-api user data stream
3566
+ url = this.urls['api']['ws']['ws-api'][type];
3567
+ }
3568
+ else {
3569
+ if (isPortfolioMargin) {
3570
+ urlType = 'papi';
3571
+ }
3572
+ url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
3474
3573
  }
3475
- const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
3476
3574
  const client = this.client(url);
3477
3575
  this.setBalanceCache(client, type, isPortfolioMargin);
3478
3576
  this.setPositionsCache(client, type, undefined, isPortfolioMargin);
@@ -3859,8 +3957,9 @@ class binance extends binance$1["default"] {
3859
3957
  //
3860
3958
  // each account is connected to a different endpoint
3861
3959
  // and has exactly one subscriptionhash which is the account type
3862
- const subscriptions = Object.keys(client.subscriptions);
3863
- const accountType = subscriptions[0];
3960
+ const subscriptions = client.subscriptions;
3961
+ const subscriptionsKeys = Object.keys(subscriptions);
3962
+ const accountType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
3864
3963
  if (this.positions === undefined) {
3865
3964
  this.positions = {};
3866
3965
  }
@@ -4137,10 +4236,16 @@ class binance extends binance$1["default"] {
4137
4236
  }
4138
4237
  let isPortfolioMargin = undefined;
4139
4238
  [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'watchMyTrades', 'papi', 'portfolioMargin', false);
4140
- if (isPortfolioMargin) {
4141
- urlType = 'papi';
4239
+ let url = '';
4240
+ if (type === 'spot') {
4241
+ url = this.urls['api']['ws']['ws-api'][type];
4242
+ }
4243
+ else {
4244
+ if (isPortfolioMargin) {
4245
+ urlType = 'papi';
4246
+ }
4247
+ url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
4142
4248
  }
4143
- const url = this.urls['api']['ws'][urlType] + '/' + this.options[type]['listenKey'];
4144
4249
  const client = this.client(url);
4145
4250
  this.setBalanceCache(client, type, isPortfolioMargin);
4146
4251
  this.setPositionsCache(client, type, undefined, isPortfolioMargin);
@@ -4286,8 +4391,12 @@ class binance extends binance$1["default"] {
4286
4391
  for (let i = 0; i < subscriptionKeys.length; i++) {
4287
4392
  const subscriptionHash = subscriptionKeys[i];
4288
4393
  const subscriptionId = this.safeString(client.subscriptions[subscriptionHash], 'id');
4394
+ const subscription = this.safeString(client.subscriptions[subscriptionHash], 'subscription');
4289
4395
  if (id === subscriptionId) {
4290
4396
  client.reject(e, subscriptionHash);
4397
+ if (subscription !== undefined) {
4398
+ delete client.subscriptions[subscription];
4399
+ }
4291
4400
  }
4292
4401
  }
4293
4402
  }
@@ -4300,14 +4409,35 @@ class binance extends binance$1["default"] {
4300
4409
  client.reset(message);
4301
4410
  }
4302
4411
  }
4412
+ handleEventStreamTerminated(client, message) {
4413
+ //
4414
+ // {
4415
+ // e: 'eventStreamTerminated',
4416
+ // E: 1757896885229
4417
+ // }
4418
+ //
4419
+ const event = this.safeString(message, 'e');
4420
+ const subscriptions = client.subscriptions;
4421
+ const subscriptionsKeys = Object.keys(subscriptions);
4422
+ const accountType = this.getAccountTypeFromSubscriptions(subscriptionsKeys);
4423
+ if (event === 'eventStreamTerminated') {
4424
+ delete client.subscriptions[accountType];
4425
+ client.reject(message, accountType);
4426
+ }
4427
+ }
4303
4428
  handleMessage(client, message) {
4304
4429
  // handle WebSocketAPI
4430
+ const eventMsg = this.safeDict(message, 'event');
4431
+ if (eventMsg !== undefined) {
4432
+ message = eventMsg;
4433
+ }
4305
4434
  const status = this.safeString(message, 'status');
4306
4435
  const error = this.safeValue(message, 'error');
4307
4436
  if ((error !== undefined) || (status !== undefined && status !== '200')) {
4308
4437
  this.handleWsError(client, message);
4309
4438
  return;
4310
4439
  }
4440
+ // user subscription wraps message in subscriptionId and event
4311
4441
  const id = this.safeString(message, 'id');
4312
4442
  const subscriptions = this.safeValue(client.subscriptions, id);
4313
4443
  let method = this.safeValue(subscriptions, 'method');
@@ -4342,6 +4472,7 @@ class binance extends binance$1["default"] {
4342
4472
  'executionReport': this.handleOrderUpdate,
4343
4473
  'ORDER_TRADE_UPDATE': this.handleOrderUpdate,
4344
4474
  'forceOrder': this.handleLiquidation,
4475
+ 'eventStreamTerminated': this.handleEventStreamTerminated,
4345
4476
  'externalLockUpdate': this.handleBalance,
4346
4477
  };
4347
4478
  let event = this.safeString(message, 'e');