ccxt 4.2.89 → 4.2.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 (90) hide show
  1. package/CHANGELOG.md +44 -16
  2. package/README.md +3 -3
  3. package/build.sh +1 -1
  4. package/dist/ccxt.browser.js +1167 -274
  5. package/dist/ccxt.browser.min.js +6 -4
  6. package/dist/cjs/ccxt.js +1 -1
  7. package/dist/cjs/src/ascendex.js +1 -0
  8. package/dist/cjs/src/base/Exchange.js +39 -9
  9. package/dist/cjs/src/base/functions/crypto.js +37 -0
  10. package/dist/cjs/src/base/functions/rsa.js +19 -4
  11. package/dist/cjs/src/binance.js +90 -9
  12. package/dist/cjs/src/bingx.js +101 -1
  13. package/dist/cjs/src/bitfinex2.js +1 -0
  14. package/dist/cjs/src/bitget.js +2 -0
  15. package/dist/cjs/src/bitmex.js +1 -0
  16. package/dist/cjs/src/bitrue.js +1 -0
  17. package/dist/cjs/src/bybit.js +61 -0
  18. package/dist/cjs/src/coinbase.js +51 -25
  19. package/dist/cjs/src/coinbaseinternational.js +1 -0
  20. package/dist/cjs/src/coinex.js +102 -8
  21. package/dist/cjs/src/cryptocom.js +1 -0
  22. package/dist/cjs/src/delta.js +1 -0
  23. package/dist/cjs/src/digifinex.js +1 -0
  24. package/dist/cjs/src/exmo.js +1 -0
  25. package/dist/cjs/src/gate.js +2 -0
  26. package/dist/cjs/src/gemini.js +12 -10
  27. package/dist/cjs/src/hitbtc.js +1 -0
  28. package/dist/cjs/src/htx.js +1 -0
  29. package/dist/cjs/src/hyperliquid.js +1 -0
  30. package/dist/cjs/src/kraken.js +11 -9
  31. package/dist/cjs/src/kucoin.js +1 -0
  32. package/dist/cjs/src/kucoinfutures.js +34 -3
  33. package/dist/cjs/src/mexc.js +1 -0
  34. package/dist/cjs/src/okx.js +187 -38
  35. package/dist/cjs/src/phemex.js +1 -0
  36. package/dist/cjs/src/pro/bitmex.js +39 -18
  37. package/dist/cjs/src/pro/kucoin.js +91 -0
  38. package/dist/cjs/src/pro/kucoinfutures.js +151 -82
  39. package/dist/cjs/src/static_dependencies/noble-curves/p256.js +48 -0
  40. package/dist/cjs/src/woo.js +1 -0
  41. package/js/ccxt.d.ts +1 -1
  42. package/js/ccxt.js +1 -1
  43. package/js/src/abstract/bingx.d.ts +2 -0
  44. package/js/src/abstract/bybit.d.ts +2 -0
  45. package/js/src/ascendex.js +1 -0
  46. package/js/src/base/Exchange.d.ts +5 -0
  47. package/js/src/base/Exchange.js +39 -9
  48. package/js/src/base/functions/crypto.js +37 -0
  49. package/js/src/base/functions/rsa.d.ts +1 -1
  50. package/js/src/base/functions/rsa.js +21 -5
  51. package/js/src/base/types.d.ts +1 -0
  52. package/js/src/binance.d.ts +1 -0
  53. package/js/src/binance.js +90 -9
  54. package/js/src/bingx.d.ts +1 -0
  55. package/js/src/bingx.js +101 -1
  56. package/js/src/bitfinex2.js +1 -0
  57. package/js/src/bitget.js +2 -0
  58. package/js/src/bitmex.js +1 -0
  59. package/js/src/bitrue.js +1 -0
  60. package/js/src/bybit.d.ts +2 -0
  61. package/js/src/bybit.js +61 -0
  62. package/js/src/coinbase.js +51 -25
  63. package/js/src/coinbaseinternational.js +1 -0
  64. package/js/src/coinex.d.ts +2 -0
  65. package/js/src/coinex.js +102 -8
  66. package/js/src/cryptocom.js +1 -0
  67. package/js/src/delta.js +1 -0
  68. package/js/src/digifinex.js +1 -0
  69. package/js/src/exmo.js +1 -0
  70. package/js/src/gate.js +2 -0
  71. package/js/src/gemini.js +12 -10
  72. package/js/src/hitbtc.js +1 -0
  73. package/js/src/htx.js +1 -0
  74. package/js/src/hyperliquid.js +1 -0
  75. package/js/src/kraken.js +11 -9
  76. package/js/src/kucoin.js +1 -0
  77. package/js/src/kucoinfutures.d.ts +2 -9
  78. package/js/src/kucoinfutures.js +34 -3
  79. package/js/src/mexc.js +1 -0
  80. package/js/src/okx.d.ts +1 -0
  81. package/js/src/okx.js +187 -38
  82. package/js/src/phemex.js +1 -0
  83. package/js/src/pro/bitmex.d.ts +1 -0
  84. package/js/src/pro/bitmex.js +39 -18
  85. package/js/src/pro/kucoin.d.ts +4 -0
  86. package/js/src/pro/kucoin.js +91 -0
  87. package/js/src/pro/kucoinfutures.d.ts +9 -5
  88. package/js/src/pro/kucoinfutures.js +151 -82
  89. package/js/src/woo.js +1 -0
  90. package/package.json +1 -1
@@ -84,6 +84,7 @@ class okx extends okx$1 {
84
84
  'fetchLedgerEntry': undefined,
85
85
  'fetchLeverage': true,
86
86
  'fetchLeverageTiers': false,
87
+ 'fetchMarginAdjustmentHistory': true,
87
88
  'fetchMarketLeverageTiers': true,
88
89
  'fetchMarkets': true,
89
90
  'fetchMarkOHLCV': true,
@@ -1218,7 +1219,7 @@ class okx extends okx$1 {
1218
1219
  // ]
1219
1220
  // }
1220
1221
  //
1221
- const data = this.safeValue(response, 'data', []);
1222
+ const data = this.safeList(response, 'data', []);
1222
1223
  const dataLength = data.length;
1223
1224
  const update = {
1224
1225
  'updated': undefined,
@@ -1266,8 +1267,8 @@ class okx extends okx$1 {
1266
1267
  // "msg": ""
1267
1268
  // }
1268
1269
  //
1269
- const data = this.safeValue(response, 'data', []);
1270
- const first = this.safeValue(data, 0, {});
1270
+ const data = this.safeList(response, 'data', []);
1271
+ const first = this.safeDict(data, 0, {});
1271
1272
  return this.safeInteger(first, 'ts');
1272
1273
  }
1273
1274
  async fetchAccounts(params = {}) {
@@ -1299,7 +1300,7 @@ class okx extends okx$1 {
1299
1300
  // "msg": ""
1300
1301
  // }
1301
1302
  //
1302
- const data = this.safeValue(response, 'data', []);
1303
+ const data = this.safeList(response, 'data', []);
1303
1304
  const result = [];
1304
1305
  for (let i = 0; i < data.length; i++) {
1305
1306
  const account = data[i];
@@ -1324,7 +1325,7 @@ class okx extends okx$1 {
1324
1325
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1325
1326
  * @returns {object[]} an array of objects representing market data
1326
1327
  */
1327
- const types = this.safeValue(this.options, 'fetchMarkets');
1328
+ const types = this.safeList(this.options, 'fetchMarkets', []);
1328
1329
  let promises = [];
1329
1330
  let result = [];
1330
1331
  for (let i = 0; i < types.length; i++) {
@@ -1428,7 +1429,7 @@ class okx extends okx$1 {
1428
1429
  }
1429
1430
  }
1430
1431
  const tickSize = this.safeString(market, 'tickSz');
1431
- const fees = this.safeValue2(this.fees, type, 'trading', {});
1432
+ const fees = this.safeDict2(this.fees, type, 'trading', {});
1432
1433
  let maxLeverage = this.safeString(market, 'lever', '1');
1433
1434
  maxLeverage = Precise["default"].stringMax(maxLeverage, '1');
1434
1435
  const maxSpotCost = this.safeNumber(market, 'maxMktSz');
@@ -1487,7 +1488,7 @@ class okx extends okx$1 {
1487
1488
  'instType': this.convertToInstrumentType(type),
1488
1489
  };
1489
1490
  if (type === 'option') {
1490
- const optionsUnderlying = this.safeValue(this.options, 'defaultUnderlying', ['BTC-USD', 'ETH-USD']);
1491
+ const optionsUnderlying = this.safeList(this.options, 'defaultUnderlying', ['BTC-USD', 'ETH-USD']);
1491
1492
  const promises = [];
1492
1493
  for (let i = 0; i < optionsUnderlying.length; i++) {
1493
1494
  const underlying = optionsUnderlying[i];
@@ -1497,8 +1498,8 @@ class okx extends okx$1 {
1497
1498
  const promisesResult = await Promise.all(promises);
1498
1499
  let markets = [];
1499
1500
  for (let i = 0; i < promisesResult.length; i++) {
1500
- const res = this.safeValue(promisesResult, i, {});
1501
- const options = this.safeValue(res, 'data', []);
1501
+ const res = this.safeDict(promisesResult, i, {});
1502
+ const options = this.safeList(res, 'data', []);
1502
1503
  markets = this.arrayConcat(markets, options);
1503
1504
  }
1504
1505
  return this.parseMarkets(markets);
@@ -1537,7 +1538,7 @@ class okx extends okx$1 {
1537
1538
  // "msg": ""
1538
1539
  // }
1539
1540
  //
1540
- const dataResponse = this.safeValue(response, 'data', []);
1541
+ const dataResponse = this.safeList(response, 'data', []);
1541
1542
  return this.parseMarkets(dataResponse);
1542
1543
  }
1543
1544
  safeNetwork(networkId) {
@@ -1614,7 +1615,7 @@ class okx extends okx$1 {
1614
1615
  // "msg": ""
1615
1616
  // }
1616
1617
  //
1617
- const data = this.safeValue(response, 'data', []);
1618
+ const data = this.safeList(response, 'data', []);
1618
1619
  const result = {};
1619
1620
  const dataByCurrencyId = this.groupBy(data, 'ccy');
1620
1621
  const currencyIds = Object.keys(dataByCurrencyId);
@@ -1630,11 +1631,11 @@ class okx extends okx$1 {
1630
1631
  let maxPrecision = undefined;
1631
1632
  for (let j = 0; j < chains.length; j++) {
1632
1633
  const chain = chains[j];
1633
- const canDeposit = this.safeValue(chain, 'canDep');
1634
+ const canDeposit = this.safeBool(chain, 'canDep');
1634
1635
  depositEnabled = (canDeposit) ? canDeposit : depositEnabled;
1635
- const canWithdraw = this.safeValue(chain, 'canWd');
1636
+ const canWithdraw = this.safeBool(chain, 'canWd');
1636
1637
  withdrawEnabled = (canWithdraw) ? canWithdraw : withdrawEnabled;
1637
- const canInternal = this.safeValue(chain, 'canInternal');
1638
+ const canInternal = this.safeBool(chain, 'canInternal');
1638
1639
  const active = (canDeposit && canWithdraw && canInternal) ? true : false;
1639
1640
  currencyActive = (active) ? active : currencyActive;
1640
1641
  const networkId = this.safeString(chain, 'chain');
@@ -1667,7 +1668,7 @@ class okx extends okx$1 {
1667
1668
  };
1668
1669
  }
1669
1670
  }
1670
- const firstChain = this.safeValue(chains, 0);
1671
+ const firstChain = this.safeDict(chains, 0, {});
1671
1672
  result[code] = {
1672
1673
  'info': undefined,
1673
1674
  'code': code,
@@ -1743,8 +1744,8 @@ class okx extends okx$1 {
1743
1744
  // ]
1744
1745
  // }
1745
1746
  //
1746
- const data = this.safeValue(response, 'data', []);
1747
- const first = this.safeValue(data, 0, {});
1747
+ const data = this.safeList(response, 'data', []);
1748
+ const first = this.safeDict(data, 0, {});
1748
1749
  const timestamp = this.safeInteger(first, 'ts');
1749
1750
  return this.parseOrderBook(first, symbol, timestamp);
1750
1751
  }
@@ -1845,7 +1846,7 @@ class okx extends okx$1 {
1845
1846
  // ]
1846
1847
  // }
1847
1848
  //
1848
- const data = this.safeValue(response, 'data', []);
1849
+ const data = this.safeList(response, 'data', []);
1849
1850
  const first = this.safeDict(data, 0, {});
1850
1851
  return this.parseTicker(first, market);
1851
1852
  }
@@ -1868,7 +1869,7 @@ class okx extends okx$1 {
1868
1869
  'instType': this.convertToInstrumentType(marketType),
1869
1870
  };
1870
1871
  if (marketType === 'option') {
1871
- const defaultUnderlying = this.safeValue(this.options, 'defaultUnderlying', 'BTC-USD');
1872
+ const defaultUnderlying = this.safeString(this.options, 'defaultUnderlying', 'BTC-USD');
1872
1873
  const currencyId = this.safeString2(params, 'uly', 'marketId', defaultUnderlying);
1873
1874
  if (currencyId === undefined) {
1874
1875
  throw new errors.ArgumentsRequired(this.id + ' fetchTickers() requires an underlying uly or marketId parameter for options markets');
@@ -2134,7 +2135,7 @@ class okx extends okx$1 {
2134
2135
  }
2135
2136
  const price = this.safeString(params, 'price');
2136
2137
  params = this.omit(params, 'price');
2137
- const options = this.safeValue(this.options, 'fetchOHLCV', {});
2138
+ const options = this.safeDict(this.options, 'fetchOHLCV', {});
2138
2139
  const timezone = this.safeString(options, 'timezone', 'UTC');
2139
2140
  if (limit === undefined) {
2140
2141
  limit = 100; // default 100, max 100
@@ -2267,7 +2268,7 @@ class okx extends okx$1 {
2267
2268
  // }
2268
2269
  //
2269
2270
  const rates = [];
2270
- const data = this.safeValue(response, 'data', []);
2271
+ const data = this.safeList(response, 'data', []);
2271
2272
  for (let i = 0; i < data.length; i++) {
2272
2273
  const rate = data[i];
2273
2274
  const timestamp = this.safeInteger(rate, 'fundingTime');
@@ -2292,10 +2293,10 @@ class okx extends okx$1 {
2292
2293
  }
2293
2294
  parseTradingBalance(response) {
2294
2295
  const result = { 'info': response };
2295
- const data = this.safeValue(response, 'data', []);
2296
- const first = this.safeValue(data, 0, {});
2296
+ const data = this.safeList(response, 'data', []);
2297
+ const first = this.safeDict(data, 0, {});
2297
2298
  const timestamp = this.safeInteger(first, 'uTime');
2298
- const details = this.safeValue(first, 'details', []);
2299
+ const details = this.safeList(first, 'details', []);
2299
2300
  for (let i = 0; i < details.length; i++) {
2300
2301
  const balance = details[i];
2301
2302
  const currencyId = this.safeString(balance, 'ccy');
@@ -2320,7 +2321,7 @@ class okx extends okx$1 {
2320
2321
  }
2321
2322
  parseFundingBalance(response) {
2322
2323
  const result = { 'info': response };
2323
- const data = this.safeValue(response, 'data', []);
2324
+ const data = this.safeList(response, 'data', []);
2324
2325
  for (let i = 0; i < data.length; i++) {
2325
2326
  const balance = data[i];
2326
2327
  const currencyId = this.safeString(balance, 'ccy');
@@ -2404,8 +2405,8 @@ class okx extends okx$1 {
2404
2405
  // "msg": ""
2405
2406
  // }
2406
2407
  //
2407
- const data = this.safeValue(response, 'data', []);
2408
- const first = this.safeValue(data, 0, {});
2408
+ const data = this.safeList(response, 'data', []);
2409
+ const first = this.safeDict(data, 0, {});
2409
2410
  return this.parseTradingFee(first, market);
2410
2411
  }
2411
2412
  async fetchBalance(params = {}) {
@@ -2893,8 +2894,8 @@ class okx extends okx$1 {
2893
2894
  else {
2894
2895
  response = await this.privatePostTradeBatchOrders(request);
2895
2896
  }
2896
- const data = this.safeValue(response, 'data', []);
2897
- const first = this.safeValue(data, 0);
2897
+ const data = this.safeList(response, 'data', []);
2898
+ const first = this.safeDict(data, 0, {});
2898
2899
  const order = this.parseOrder(first, market);
2899
2900
  order['type'] = type;
2900
2901
  order['side'] = side;
@@ -4405,7 +4406,7 @@ class okx extends okx$1 {
4405
4406
  // ]
4406
4407
  // }
4407
4408
  //
4408
- const data = this.safeValue(response, 'data', []);
4409
+ const data = this.safeList(response, 'data', []);
4409
4410
  return this.parseLedger(data, currency, since, limit);
4410
4411
  }
4411
4412
  parseLedgerEntryType(type) {
@@ -6463,9 +6464,9 @@ class okx extends okx$1 {
6463
6464
  // }
6464
6465
  //
6465
6466
  const data = this.safeList(response, 'data', []);
6467
+ const entry = this.safeDict(data, 0, {});
6466
6468
  const errorCode = this.safeString(response, 'code');
6467
- const item = this.safeDict(data, 0, {});
6468
- return this.extend(this.parseMarginModification(item, market), {
6469
+ return this.extend(this.parseMarginModification(entry, market), {
6469
6470
  'status': (errorCode === '0') ? 'ok' : 'failed',
6470
6471
  });
6471
6472
  }
@@ -6480,22 +6481,68 @@ class okx extends okx$1 {
6480
6481
  // "type": "reduce"
6481
6482
  // }
6482
6483
  //
6483
- const amountRaw = this.safeNumber(data, 'amt');
6484
+ // fetchMarginAdjustmentHistory
6485
+ //
6486
+ // {
6487
+ // bal: '67621.4325135010619812',
6488
+ // balChg: '-10.0000000000000000',
6489
+ // billId: '691293628710342659',
6490
+ // ccy: 'USDT',
6491
+ // clOrdId: '',
6492
+ // execType: '',
6493
+ // fee: '0',
6494
+ // fillFwdPx: '',
6495
+ // fillIdxPx: '',
6496
+ // fillMarkPx: '',
6497
+ // fillMarkVol: '',
6498
+ // fillPxUsd: '',
6499
+ // fillPxVol: '',
6500
+ // fillTime: '1711089244850',
6501
+ // from: '',
6502
+ // instId: 'XRP-USDT-SWAP',
6503
+ // instType: 'SWAP',
6504
+ // interest: '0',
6505
+ // mgnMode: 'isolated',
6506
+ // notes: '',
6507
+ // ordId: '',
6508
+ // pnl: '0',
6509
+ // posBal: '73.12',
6510
+ // posBalChg: '10.00',
6511
+ // px: '',
6512
+ // subType: '160',
6513
+ // sz: '10',
6514
+ // tag: '',
6515
+ // to: '',
6516
+ // tradeId: '0',
6517
+ // ts: '1711089244699',
6518
+ // type: '6'
6519
+ // }
6520
+ //
6521
+ const amountRaw = this.safeString2(data, 'amt', 'posBalChg');
6484
6522
  const typeRaw = this.safeString(data, 'type');
6485
- const type = (typeRaw === 'reduce') ? 'reduce' : 'add';
6523
+ let type = undefined;
6524
+ if (typeRaw === '6') {
6525
+ type = Precise["default"].stringGt(amountRaw, '0') ? 'add' : 'reduce';
6526
+ }
6527
+ else {
6528
+ type = typeRaw;
6529
+ }
6530
+ const amount = Precise["default"].stringAbs(amountRaw);
6486
6531
  const marketId = this.safeString(data, 'instId');
6487
6532
  const responseMarket = this.safeMarket(marketId, market);
6488
6533
  const code = responseMarket['inverse'] ? responseMarket['base'] : responseMarket['quote'];
6534
+ const timestamp = this.safeInteger(data, 'ts');
6489
6535
  return {
6490
6536
  'info': data,
6491
6537
  'symbol': responseMarket['symbol'],
6492
6538
  'type': type,
6493
- 'amount': amountRaw,
6494
- 'total': undefined,
6539
+ 'marginMode': 'isolated',
6540
+ 'amount': this.parseNumber(amount),
6495
6541
  'code': code,
6542
+ 'total': undefined,
6496
6543
  'status': undefined,
6497
- 'timestamp': undefined,
6498
- 'datetime': undefined,
6544
+ 'timestamp': timestamp,
6545
+ 'datetime': this.iso8601(timestamp),
6499
6546
  };
6500
6547
  }
6501
6548
  async reduceMargin(symbol, amount, params = {}) {
@@ -7597,6 +7644,108 @@ class okx extends okx$1 {
7597
7644
  }
7598
7645
  return undefined;
7599
7646
  }
7647
+ async fetchMarginAdjustmentHistory(symbol = undefined, type = undefined, since = undefined, limit = undefined, params = {}) {
7648
+ /**
7649
+ * @method
7650
+ * @name okx#fetchMarginAdjustmentHistory
7651
+ * @description fetches the history of margin added or reduced from contract isolated positions
7652
+ * @see https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-bills-details-last-7-days
7653
+ * @see https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-bills-details-last-3-months
7654
+ * @param {string} [symbol] not used by okx fetchMarginAdjustmentHistory
7655
+ * @param {string} [type] "add" or "reduce"
7656
+ * @param {object} params extra parameters specific to the exchange api endpoint
7657
+ * @param {boolean} [params.auto] true if fetching auto margin increases
7658
+ * @returns {object[]} a list of [margin structures]{@link https://docs.ccxt.com/#/?id=margin-loan-structure}
7659
+ */
7660
+ await this.loadMarkets();
7661
+ const auto = this.safeBool(params, 'auto');
7662
+ if (type === undefined) {
7663
+ throw new errors.ArgumentsRequired(this.id + ' fetchMarginAdjustmentHistory () requires a type argument');
7664
+ }
7665
+ const isAdd = type === 'add';
7666
+ let subType = isAdd ? '160' : '161';
7667
+ if (auto) {
7668
+ if (isAdd) {
7669
+ subType = '162';
7670
+ }
7671
+ else {
7672
+ throw new errors.BadRequest(this.id + ' cannot fetch margin adjustments for type ' + type);
7673
+ }
7674
+ }
7675
+ const request = {
7676
+ 'subType': subType,
7677
+ 'mgnMode': 'isolated',
7678
+ };
7679
+ const until = this.safeInteger(params, 'until');
7680
+ params = this.omit(params, 'until');
7681
+ if (since !== undefined) {
7682
+ request['startTime'] = since;
7683
+ }
7684
+ if (limit !== undefined) {
7685
+ request['limit'] = limit;
7686
+ }
7687
+ if (until !== undefined) {
7688
+ request['endTime'] = until;
7689
+ }
7690
+ let response = undefined;
7691
+ const now = this.milliseconds();
7692
+ const oneWeekAgo = now - 604800000;
7693
+ const threeMonthsAgo = now - 7776000000;
7694
+ if ((since === undefined) || (since > oneWeekAgo)) {
7695
+ response = await this.privateGetAccountBills(this.extend(request, params));
7696
+ }
7697
+ else if (since > threeMonthsAgo) {
7698
+ response = await this.privateGetAccountBillsArchive(this.extend(request, params));
7699
+ }
7700
+ else {
7701
+ throw new errors.BadRequest(this.id + ' fetchMarginAdjustmentHistory () cannot fetch margin adjustments older than 3 months');
7702
+ }
7703
+ //
7704
+ // {
7705
+ // code: '0',
7706
+ // data: [
7707
+ // {
7708
+ // bal: '67621.4325135010619812',
7709
+ // balChg: '-10.0000000000000000',
7710
+ // billId: '691293628710342659',
7711
+ // ccy: 'USDT',
7712
+ // clOrdId: '',
7713
+ // execType: '',
7714
+ // fee: '0',
7715
+ // fillFwdPx: '',
7716
+ // fillIdxPx: '',
7717
+ // fillMarkPx: '',
7718
+ // fillMarkVol: '',
7719
+ // fillPxUsd: '',
7720
+ // fillPxVol: '',
7721
+ // fillTime: '1711089244850',
7722
+ // from: '',
7723
+ // instId: 'XRP-USDT-SWAP',
7724
+ // instType: 'SWAP',
7725
+ // interest: '0',
7726
+ // mgnMode: 'isolated',
7727
+ // notes: '',
7728
+ // ordId: '',
7729
+ // pnl: '0',
7730
+ // posBal: '73.12',
7731
+ // posBalChg: '10.00',
7732
+ // px: '',
7733
+ // subType: '160',
7734
+ // sz: '10',
7735
+ // tag: '',
7736
+ // to: '',
7737
+ // tradeId: '0',
7738
+ // ts: '1711089244699',
7739
+ // type: '6'
7740
+ // }
7741
+ // ],
7742
+ // msg: ''
7743
+ // }
7744
+ //
7745
+ const data = this.safeList(response, 'data');
7746
+ const modifications = this.parseMarginModifications(data);
7747
+ return this.filterBySymbolSinceLimit(modifications, symbol, since, limit);
7748
+ }
7600
7749
  }
7601
7750
 
7602
7751
  module.exports = okx;
@@ -4062,6 +4062,7 @@ class phemex extends phemex$1 {
4062
4062
  'info': data,
4063
4063
  'symbol': this.safeSymbol(undefined, market),
4064
4064
  'type': 'set',
4065
+ 'marginMode': 'isolated',
4065
4066
  'amount': undefined,
4066
4067
  'total': undefined,
4067
4068
  'code': market[codeCurrency],
@@ -541,8 +541,8 @@ class bitmex extends bitmex$1 {
541
541
  for (let i = 0; i < marketIds.length; i++) {
542
542
  const marketId = marketIds[i];
543
543
  const market = this.safeMarket(marketId);
544
- const messageHash = table + ':' + marketId;
545
544
  const symbol = market['symbol'];
545
+ const messageHash = table + ':' + symbol;
546
546
  const trades = this.parseTrades(dataByMarketIds[marketId], market);
547
547
  let stored = this.safeValue(this.trades, symbol);
548
548
  if (stored === undefined) {
@@ -567,23 +567,7 @@ class bitmex extends bitmex$1 {
567
567
  * @param {object} [params] extra parameters specific to the exchange API endpoint
568
568
  * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
569
569
  */
570
- await this.loadMarkets();
571
- const market = this.market(symbol);
572
- symbol = market['symbol'];
573
- const table = 'trade';
574
- const messageHash = table + ':' + market['id'];
575
- const url = this.urls['api']['ws'];
576
- const request = {
577
- 'op': 'subscribe',
578
- 'args': [
579
- messageHash,
580
- ],
581
- };
582
- const trades = await this.watch(url, messageHash, this.extend(request, params), messageHash);
583
- if (this.newUpdates) {
584
- limit = trades.getLimit(symbol, limit);
585
- }
586
- return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
570
+ return await this.watchTradesForSymbols([symbol], since, limit, params);
587
571
  }
588
572
  async authenticate(params = {}) {
589
573
  const url = this.urls['api']['ws'];
@@ -1216,6 +1200,43 @@ class bitmex extends bitmex$1 {
1216
1200
  const orderbook = await this.watchMultiple(url, messageHashes, this.deepExtend(request, params), topics);
1217
1201
  return orderbook.limit();
1218
1202
  }
1203
+ async watchTradesForSymbols(symbols, since = undefined, limit = undefined, params = {}) {
1204
+ /**
1205
+ * @method
1206
+ * @name bitmex#watchTradesForSymbols
1207
+ * @description get the list of most recent trades for a list of symbols
1208
+ * @param {string[]} symbols unified symbol of the market to fetch trades for
1209
+ * @param {int} [since] timestamp in ms of the earliest trade to fetch
1210
+ * @param {int} [limit] the maximum amount of trades to fetch
1211
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1212
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades}
1213
+ */
1214
+ await this.loadMarkets();
1215
+ symbols = this.marketSymbols(symbols, undefined, false);
1216
+ const table = 'trade';
1217
+ const topics = [];
1218
+ const messageHashes = [];
1219
+ for (let i = 0; i < symbols.length; i++) {
1220
+ const symbol = symbols[i];
1221
+ const market = this.market(symbol);
1222
+ const topic = table + ':' + market['id'];
1223
+ topics.push(topic);
1224
+ const messageHash = table + ':' + symbol;
1225
+ messageHashes.push(messageHash);
1226
+ }
1227
+ const url = this.urls['api']['ws'];
1228
+ const request = {
1229
+ 'op': 'subscribe',
1230
+ 'args': topics,
1231
+ };
1232
+ const trades = await this.watchMultiple(url, messageHashes, this.deepExtend(request, params), topics);
1233
+ if (this.newUpdates) {
1234
+ const first = this.safeValue(trades, 0);
1235
+ const tradeSymbol = this.safeString(first, 'symbol');
1236
+ limit = trades.getLimit(tradeSymbol, limit);
1237
+ }
1238
+ return this.filterBySinceLimit(trades, since, limit, 'timestamp', true);
1239
+ }
1219
1240
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1220
1241
  /**
1221
1242
  * @method
@@ -18,6 +18,7 @@ class kucoin extends kucoin$1 {
18
18
  'cancelOrderWs': false,
19
19
  'cancelOrdersWs': false,
20
20
  'cancelAllOrdersWs': false,
21
+ 'watchBidsAsks': true,
21
22
  'watchOrderBook': true,
22
23
  'watchOrders': true,
23
24
  'watchMyTrades': true,
@@ -285,6 +286,92 @@ class kucoin extends kucoin$1 {
285
286
  }
286
287
  }
287
288
  }
289
+ async watchBidsAsks(symbols = undefined, params = {}) {
290
+ /**
291
+ * @method
292
+ * @name kucoin#watchBidsAsks
293
+ * @see https://www.kucoin.com/docs/websocket/spot-trading/public-channels/level1-bbo-market-data
294
+ * @description watches best bid & ask for symbols
295
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
296
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
297
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
298
+ */
299
+ const ticker = await this.watchMultiHelper('watchBidsAsks', '/spotMarket/level1:', symbols, params);
300
+ if (this.newUpdates) {
301
+ const tickers = {};
302
+ tickers[ticker['symbol']] = ticker;
303
+ return tickers;
304
+ }
305
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
306
+ }
307
+ async watchMultiHelper(methodName, channelName, symbols = undefined, params = {}) {
308
+ await this.loadMarkets();
309
+ symbols = this.marketSymbols(symbols, undefined, false, true, false);
310
+ const length = symbols.length;
311
+ if (length > 100) {
312
+ throw new errors.ArgumentsRequired(this.id + ' ' + methodName + '() accepts a maximum of 100 symbols');
313
+ }
314
+ const messageHashes = [];
315
+ for (let i = 0; i < symbols.length; i++) {
316
+ const symbol = symbols[i];
317
+ const market = this.market(symbol);
318
+ messageHashes.push('bidask@' + market['symbol']);
319
+ }
320
+ const url = await this.negotiate(false);
321
+ const marketIds = this.marketIds(symbols);
322
+ const joined = marketIds.join(',');
323
+ const requestId = this.requestId().toString();
324
+ const request = {
325
+ 'id': requestId,
326
+ 'type': 'subscribe',
327
+ 'topic': channelName + joined,
328
+ 'response': true,
329
+ };
330
+ const message = this.extend(request, params);
331
+ return await this.watchMultiple(url, messageHashes, message, messageHashes);
332
+ }
333
+ handleBidAsk(client, message) {
334
+ //
335
+ // arrives one symbol dict
336
+ //
337
+ // {
338
+ // topic: '/spotMarket/level1:ETH-USDT',
339
+ // type: 'message',
340
+ // data: {
341
+ // asks: [ '3347.42', '2.0778387' ],
342
+ // bids: [ '3347.41', '6.0411697' ],
343
+ // timestamp: 1712231142085
344
+ // },
345
+ // subject: 'level1'
346
+ // }
347
+ //
348
+ const parsedTicker = this.parseWsBidAsk(message);
349
+ const symbol = parsedTicker['symbol'];
350
+ this.bidsasks[symbol] = parsedTicker;
351
+ const messageHash = 'bidask@' + symbol;
352
+ client.resolve(parsedTicker, messageHash);
353
+ }
354
+ parseWsBidAsk(ticker, market = undefined) {
355
+ const topic = this.safeString(ticker, 'topic');
356
+ const parts = topic.split(':');
357
+ const marketId = parts[1];
358
+ market = this.safeMarket(marketId, market);
359
+ const symbol = this.safeString(market, 'symbol');
360
+ const data = this.safeDict(ticker, 'data', {});
361
+ const ask = this.safeList(data, 'asks', []);
362
+ const bid = this.safeList(data, 'bids', []);
363
+ const timestamp = this.safeInteger(data, 'timestamp');
364
+ return this.safeTicker({
365
+ 'symbol': symbol,
366
+ 'timestamp': timestamp,
367
+ 'datetime': this.iso8601(timestamp),
368
+ 'ask': this.safeNumber(ask, 0),
369
+ 'askVolume': this.safeNumber(ask, 1),
370
+ 'bid': this.safeNumber(bid, 0),
371
+ 'bidVolume': this.safeNumber(bid, 1),
372
+ 'info': ticker,
373
+ }, market);
374
+ }
288
375
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
289
376
  /**
290
377
  * @method
@@ -676,6 +763,9 @@ class kucoin extends kucoin$1 {
676
763
  // }
677
764
  //
678
765
  const id = this.safeString(message, 'id');
766
+ if (!(id in client.subscriptions)) {
767
+ return;
768
+ }
679
769
  const subscriptionHash = this.safeString(client.subscriptions, id);
680
770
  const subscription = this.safeValue(client.subscriptions, subscriptionHash);
681
771
  delete client.subscriptions[id];
@@ -1049,6 +1139,7 @@ class kucoin extends kucoin$1 {
1049
1139
  }
1050
1140
  const subject = this.safeString(message, 'subject');
1051
1141
  const methods = {
1142
+ 'level1': this.handleBidAsk,
1052
1143
  'level2': this.handleOrderBook,
1053
1144
  'trade.l2update': this.handleOrderBook,
1054
1145
  'trade.ticker': this.handleTicker,