ccxt 4.2.9 → 4.2.11

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 (56) hide show
  1. package/README.md +3 -3
  2. package/build.sh +2 -2
  3. package/dist/ccxt.browser.js +322 -164
  4. package/dist/ccxt.browser.min.js +7 -7
  5. package/dist/cjs/ccxt.js +1 -1
  6. package/dist/cjs/src/base/Exchange.js +48 -8
  7. package/dist/cjs/src/binance.js +6 -1
  8. package/dist/cjs/src/bingx.js +0 -10
  9. package/dist/cjs/src/bitget.js +14 -5
  10. package/dist/cjs/src/bl3p.js +1 -1
  11. package/dist/cjs/src/btcalpha.js +1 -1
  12. package/dist/cjs/src/bybit.js +1 -1
  13. package/dist/cjs/src/cryptocom.js +3 -1
  14. package/dist/cjs/src/deribit.js +39 -22
  15. package/dist/cjs/src/kraken.js +1 -1
  16. package/dist/cjs/src/kucoin.js +30 -6
  17. package/dist/cjs/src/lykke.js +1 -1
  18. package/dist/cjs/src/ndax.js +1 -1
  19. package/dist/cjs/src/pro/bitmart.js +49 -27
  20. package/dist/cjs/src/pro/blockchaincom.js +2 -28
  21. package/dist/cjs/src/pro/coinbasepro.js +9 -16
  22. package/dist/cjs/src/pro/cryptocom.js +110 -28
  23. package/dist/cjs/src/pro/luno.js +5 -5
  24. package/js/ccxt.d.ts +1 -1
  25. package/js/ccxt.js +1 -1
  26. package/js/src/base/Exchange.d.ts +5 -3
  27. package/js/src/base/Exchange.js +48 -8
  28. package/js/src/binance.js +6 -1
  29. package/js/src/bingx.d.ts +0 -1
  30. package/js/src/bingx.js +0 -10
  31. package/js/src/bitget.js +14 -5
  32. package/js/src/bl3p.d.ts +2 -2
  33. package/js/src/bl3p.js +1 -1
  34. package/js/src/btcalpha.d.ts +2 -2
  35. package/js/src/btcalpha.js +1 -1
  36. package/js/src/bybit.js +1 -1
  37. package/js/src/cryptocom.js +3 -1
  38. package/js/src/deribit.js +39 -22
  39. package/js/src/kraken.d.ts +2 -2
  40. package/js/src/kraken.js +1 -1
  41. package/js/src/kucoin.js +30 -6
  42. package/js/src/lykke.d.ts +2 -2
  43. package/js/src/lykke.js +1 -1
  44. package/js/src/ndax.d.ts +2 -2
  45. package/js/src/ndax.js +1 -1
  46. package/js/src/pro/bitmart.d.ts +1 -0
  47. package/js/src/pro/bitmart.js +49 -27
  48. package/js/src/pro/blockchaincom.d.ts +1 -11
  49. package/js/src/pro/blockchaincom.js +2 -28
  50. package/js/src/pro/coinbasepro.js +9 -16
  51. package/js/src/pro/cryptocom.d.ts +3 -1
  52. package/js/src/pro/cryptocom.js +111 -29
  53. package/js/src/pro/luno.d.ts +4 -4
  54. package/js/src/pro/luno.js +5 -5
  55. package/package.json +11 -11
  56. package/tests-manager.sh +2 -2
package/dist/cjs/ccxt.js CHANGED
@@ -169,7 +169,7 @@ var woo$1 = require('./src/pro/woo.js');
169
169
 
170
170
  //-----------------------------------------------------------------------------
171
171
  // this is updated by vss.js when building
172
- const version = '4.2.9';
172
+ const version = '4.2.11';
173
173
  Exchange["default"].ccxtVersion = version;
174
174
  const exchanges = {
175
175
  'ace': ace,
@@ -1295,6 +1295,17 @@ class Exchange {
1295
1295
  axolotl(payload, hexKey, ed25519) {
1296
1296
  return crypto.axolotl(payload, hexKey, ed25519);
1297
1297
  }
1298
+ fixStringifiedJsonMembers(content) {
1299
+ // used for instance in bingx
1300
+ // when stringified json has members with their values also stringified, like:
1301
+ // '{"code":0, "data":{"order":{"orderId":1742968678528512345,"symbol":"BTC-USDT", "takeProfit":"{\"type\":\"TAKE_PROFIT\",\"stopPrice\":43320.1}","reduceOnly":false}}}'
1302
+ // we can fix with below manipulations
1303
+ // @ts-ignore
1304
+ let modifiedContent = content.replaceAll('\\', '');
1305
+ modifiedContent = modifiedContent.replaceAll('"{', '{');
1306
+ modifiedContent = modifiedContent.replaceAll('}"', '}');
1307
+ return modifiedContent;
1308
+ }
1298
1309
  /* eslint-enable */
1299
1310
  // ------------------------------------------------------------------------
1300
1311
  // ########################################################################
@@ -2862,11 +2873,11 @@ class Exchange {
2862
2873
  }
2863
2874
  return result;
2864
2875
  }
2865
- parseBidsAsks(bidasks, priceKey = 0, amountKey = 1) {
2876
+ parseBidsAsks(bidasks, priceKey = 0, amountKey = 1, countOrIdKey = 2) {
2866
2877
  bidasks = this.toArray(bidasks);
2867
2878
  const result = [];
2868
2879
  for (let i = 0; i < bidasks.length; i++) {
2869
- result.push(this.parseBidAsk(bidasks[i], priceKey, amountKey));
2880
+ result.push(this.parseBidAsk(bidasks[i], priceKey, amountKey, countOrIdKey));
2870
2881
  }
2871
2882
  return result;
2872
2883
  }
@@ -3035,9 +3046,9 @@ class Exchange {
3035
3046
  const value = this.safeString2(dictionary, key1, key2);
3036
3047
  return this.parseNumber(value, d);
3037
3048
  }
3038
- parseOrderBook(orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 0, amountKey = 1) {
3039
- const bids = this.parseBidsAsks(this.safeValue(orderbook, bidsKey, []), priceKey, amountKey);
3040
- const asks = this.parseBidsAsks(this.safeValue(orderbook, asksKey, []), priceKey, amountKey);
3049
+ parseOrderBook(orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 0, amountKey = 1, countOrIdKey = 2) {
3050
+ const bids = this.parseBidsAsks(this.safeValue(orderbook, bidsKey, []), priceKey, amountKey, countOrIdKey);
3051
+ const asks = this.parseBidsAsks(this.safeValue(orderbook, asksKey, []), priceKey, amountKey, countOrIdKey);
3041
3052
  return {
3042
3053
  'symbol': symbol,
3043
3054
  'bids': this.sortBy(bids, 0, true),
@@ -3352,10 +3363,15 @@ class Exchange {
3352
3363
  async fetchBidsAsks(symbols = undefined, params = {}) {
3353
3364
  throw new errors.NotSupported(this.id + ' fetchBidsAsks() is not supported yet');
3354
3365
  }
3355
- parseBidAsk(bidask, priceKey = 0, amountKey = 1) {
3366
+ parseBidAsk(bidask, priceKey = 0, amountKey = 1, countOrIdKey = 2) {
3356
3367
  const price = this.safeNumber(bidask, priceKey);
3357
3368
  const amount = this.safeNumber(bidask, amountKey);
3358
- return [price, amount];
3369
+ const countOrId = this.safeInteger(bidask, countOrIdKey);
3370
+ const bidAsk = [price, amount];
3371
+ if (countOrId !== undefined) {
3372
+ bidAsk.push(countOrId);
3373
+ }
3374
+ return bidAsk;
3359
3375
  }
3360
3376
  safeCurrency(currencyId, currency = undefined) {
3361
3377
  if ((currencyId === undefined) && (currency !== undefined)) {
@@ -3403,7 +3419,7 @@ class Exchange {
3403
3419
  }
3404
3420
  }
3405
3421
  }
3406
- else if (delimiter !== undefined) {
3422
+ else if (delimiter !== undefined && delimiter !== '') {
3407
3423
  const parts = marketId.split(delimiter);
3408
3424
  const partsLength = parts.length;
3409
3425
  if (partsLength === 2) {
@@ -3564,6 +3580,30 @@ class Exchange {
3564
3580
  }
3565
3581
  return [value, params];
3566
3582
  }
3583
+ handleOptionAndParams2(params, methodName, methodName2, optionName, defaultValue = undefined) {
3584
+ // This method can be used to obtain method specific properties, i.e: this.handleOptionAndParams (params, 'fetchPosition', 'marginMode', 'isolated')
3585
+ const defaultOptionName = 'default' + this.capitalize(optionName); // we also need to check the 'defaultXyzWhatever'
3586
+ // check if params contain the key
3587
+ let value = this.safeValue2(params, optionName, defaultOptionName);
3588
+ if (value !== undefined) {
3589
+ params = this.omit(params, [optionName, defaultOptionName]);
3590
+ }
3591
+ else {
3592
+ // check if exchange has properties for this method
3593
+ const exchangeWideMethodOptions = this.safeValue2(this.options, methodName, methodName2);
3594
+ if (exchangeWideMethodOptions !== undefined) {
3595
+ // check if the option is defined inside this method's props
3596
+ value = this.safeValue2(exchangeWideMethodOptions, optionName, defaultOptionName);
3597
+ }
3598
+ if (value === undefined) {
3599
+ // if it's still undefined, check if global exchange-wide option exists
3600
+ value = this.safeValue2(this.options, optionName, defaultOptionName);
3601
+ }
3602
+ // if it's still undefined, use the default value
3603
+ value = (value !== undefined) ? value : defaultValue;
3604
+ }
3605
+ return [value, params];
3606
+ }
3567
3607
  handleOption(methodName, optionName, defaultValue = undefined) {
3568
3608
  // eslint-disable-next-line no-unused-vars
3569
3609
  const [result, empty] = this.handleOptionAndParams({}, methodName, optionName, defaultValue);
@@ -3145,7 +3145,12 @@ class binance extends binance$1 {
3145
3145
  response = await this.dapiPublicGetTickerBookTicker(params);
3146
3146
  }
3147
3147
  else {
3148
- response = await this.publicGetTickerBookTicker(params);
3148
+ const request = {};
3149
+ if (symbols !== undefined) {
3150
+ const marketIds = this.marketIds(symbols);
3151
+ request['symbols'] = this.json(marketIds);
3152
+ }
3153
+ response = await this.publicGetTickerBookTicker(this.extend(request, params));
3149
3154
  }
3150
3155
  return this.parseTickers(response, symbols);
3151
3156
  }
@@ -1906,16 +1906,6 @@ class bingx extends bingx$1 {
1906
1906
  const order = this.safeValue(data, 'order', data);
1907
1907
  return this.parseOrder(order, market);
1908
1908
  }
1909
- fixStringifiedJsonMembers(content) {
1910
- // when stringified json has members with their values also stringified, like:
1911
- // '{"code":0, "data":{"order":{"orderId":1742968678528512345,"symbol":"BTC-USDT", "takeProfit":"{\"type\":\"TAKE_PROFIT\",\"stopPrice\":43320.1}","reduceOnly":false}}}'
1912
- // we can fix with below manipulations
1913
- // @ts-ignore
1914
- let modifiedContent = content.replaceAll('\\', '');
1915
- modifiedContent = modifiedContent.replaceAll('"{', '{');
1916
- modifiedContent = modifiedContent.replaceAll('}"', '}');
1917
- return modifiedContent;
1918
- }
1919
1909
  async createOrders(orders, params = {}) {
1920
1910
  /**
1921
1911
  * @method
@@ -4008,6 +4008,7 @@ class bitget extends bitget$1 {
4008
4008
  * @param {string} [params.trailingPercent] *swap and future only* the percent to trail away from the current market price, rate can not be greater than 10
4009
4009
  * @param {string} [params.trailingTriggerPrice] *swap and future only* the price to trigger a trailing stop order, default uses the price argument
4010
4010
  * @param {string} [params.triggerType] *swap and future only* 'fill_price', 'mark_price' or 'index_price'
4011
+ * @param {boolean} [params.oneWayMode] *swap and future only* required to set this to true in one_way_mode and you can leave this as undefined in hedge_mode, can adjust the mode using the setPositionMode() method
4011
4012
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
4012
4013
  */
4013
4014
  await this.loadMarkets();
@@ -4201,15 +4202,23 @@ class bitget extends bitget$1 {
4201
4202
  }
4202
4203
  const marginModeRequest = (marginMode === 'cross') ? 'crossed' : 'isolated';
4203
4204
  request['marginMode'] = marginModeRequest;
4205
+ const oneWayMode = this.safeValue(params, 'oneWayMode', false);
4206
+ params = this.omit(params, 'oneWayMode');
4204
4207
  let requestSide = side;
4205
4208
  if (reduceOnly) {
4206
- request['reduceOnly'] = 'YES';
4207
- request['tradeSide'] = 'Close';
4208
- // on bitget if the position is long the side is always buy, and if the position is short the side is always sell
4209
- requestSide = (side === 'buy') ? 'sell' : 'buy';
4209
+ if (oneWayMode) {
4210
+ request['reduceOnly'] = 'YES';
4211
+ }
4212
+ else {
4213
+ // on bitget hedge mode if the position is long the side is always buy, and if the position is short the side is always sell
4214
+ requestSide = (side === 'buy') ? 'sell' : 'buy';
4215
+ request['tradeSide'] = 'Close';
4216
+ }
4210
4217
  }
4211
4218
  else {
4212
- request['tradeSide'] = 'Open';
4219
+ if (!oneWayMode) {
4220
+ request['tradeSide'] = 'Open';
4221
+ }
4213
4222
  }
4214
4223
  request['side'] = requestSide;
4215
4224
  }
@@ -146,7 +146,7 @@ class bl3p extends bl3p$1 {
146
146
  const response = await this.privatePostGENMKTMoneyInfo(params);
147
147
  return this.parseBalance(response);
148
148
  }
149
- parseBidAsk(bidask, priceKey = 0, amountKey = 1) {
149
+ parseBidAsk(bidask, priceKey = 0, amountKey = 1, countOrIdKey = 2) {
150
150
  const price = this.safeString(bidask, priceKey);
151
151
  const size = this.safeString(bidask, amountKey);
152
152
  return [
@@ -359,7 +359,7 @@ class btcalpha extends btcalpha$1 {
359
359
  const response = await this.publicGetOrderbookPairName(this.extend(request, params));
360
360
  return this.parseOrderBook(response, market['symbol'], undefined, 'buy', 'sell', 'price', 'amount');
361
361
  }
362
- parseBidsAsks(bidasks, priceKey = 0, amountKey = 1) {
362
+ parseBidsAsks(bidasks, priceKey = 0, amountKey = 1, countOrIdKey = 2) {
363
363
  const result = [];
364
364
  for (let i = 0; i < bidasks.length; i++) {
365
365
  const bidask = bidasks[i];
@@ -316,7 +316,7 @@ class bybit extends bybit$1 {
316
316
  'v5/asset/deposit/query-internal-record': 5,
317
317
  'v5/asset/deposit/query-address': 10,
318
318
  'v5/asset/deposit/query-sub-member-address': 10,
319
- 'v5/asset/coin/query-info': 25,
319
+ 'v5/asset/coin/query-info': 28,
320
320
  'v5/asset/withdraw/query-record': 10,
321
321
  'v5/asset/withdraw/withdrawable-amount': 5,
322
322
  // user
@@ -770,6 +770,7 @@ class cryptocom extends cryptocom$1 {
770
770
  // "p": "26386.00",
771
771
  // "q": "0.00453",
772
772
  // "t": 1686944282062,
773
+ // "tn" : 1704476468851524373,
773
774
  // "d": "4611686018455979970",
774
775
  // "i": "BTC_USD"
775
776
  // },
@@ -1940,7 +1941,8 @@ class cryptocom extends cryptocom$1 {
1940
1941
  // "s": "sell",
1941
1942
  // "p": "26386.00",
1942
1943
  // "q": "0.00453",
1943
- // "t": 1686944282062,
1944
+ // "tn": 1686944282062,
1945
+ // "tn": 1704476468851524373,
1944
1946
  // "d": "4611686018455979970",
1945
1947
  // "i": "BTC_USD"
1946
1948
  // }
@@ -1723,27 +1723,18 @@ class deribit extends deribit$1 {
1723
1723
  * @param {string} symbol unified symbol of the market to create an order in
1724
1724
  * @param {string} type 'market' or 'limit'
1725
1725
  * @param {string} side 'buy' or 'sell'
1726
- * @param {float} amount how much of currency you want to trade. For perpetual and futures the amount is in USD. For options it is in corresponding cryptocurrency contracts currency.
1726
+ * @param {float} amount how much you want to trade in units of the base currency. For inverse perpetual and futures the amount is in the quote currency USD. For options it is in the underlying assets base currency.
1727
1727
  * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1728
1728
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1729
+ * @param {string} [params.trigger] the trigger type 'index_price', 'mark_price', or 'last_price', default is 'last_price'
1730
+ * @param {float} [params.trailingAmount] the quote amount to trail away from the current market price
1729
1731
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1730
1732
  */
1731
1733
  await this.loadMarkets();
1732
1734
  const market = this.market(symbol);
1733
- if (market['inverse']) {
1734
- amount = this.amountToPrecision(symbol, amount);
1735
- }
1736
- else if (market['settle'] === 'USDC') {
1737
- amount = this.amountToPrecision(symbol, amount);
1738
- }
1739
- else {
1740
- amount = this.currencyToPrecision(symbol, amount);
1741
- }
1742
1735
  const request = {
1743
1736
  'instrument_name': market['id'],
1744
- // for perpetual and futures the amount is in USD
1745
- // for options it is in corresponding cryptocurrency contracts, e.g., BTC or ETH
1746
- 'amount': amount,
1737
+ 'amount': this.amountToPrecision(symbol, amount),
1747
1738
  'type': type, // limit, stop_limit, market, stop_market, default is limit
1748
1739
  // 'label': 'string', // user-defined label for the order (maximum 64 characters)
1749
1740
  // 'price': this.priceToPrecision (symbol, 123.45), // only for limit and stop_limit orders
@@ -1756,12 +1747,15 @@ class deribit extends deribit$1 {
1756
1747
  // 'trigger': 'index_price', // mark_price, last_price, required for stop_limit orders
1757
1748
  // 'advanced': 'usd', // 'implv', advanced option order type, options only
1758
1749
  };
1750
+ const trigger = this.safeString(params, 'trigger', 'last_price');
1759
1751
  const timeInForce = this.safeStringUpper(params, 'timeInForce');
1760
1752
  const reduceOnly = this.safeValue2(params, 'reduceOnly', 'reduce_only');
1761
1753
  // only stop loss sell orders are allowed when price crossed from above
1762
1754
  const stopLossPrice = this.safeValue(params, 'stopLossPrice');
1763
1755
  // only take profit buy orders are allowed when price crossed from below
1764
1756
  const takeProfitPrice = this.safeValue(params, 'takeProfitPrice');
1757
+ const trailingAmount = this.safeString2(params, 'trailingAmount', 'trigger_offset');
1758
+ const isTrailingAmountOrder = trailingAmount !== undefined;
1765
1759
  const isStopLimit = type === 'stop_limit';
1766
1760
  const isStopMarket = type === 'stop_market';
1767
1761
  const isTakeLimit = type === 'take_limit';
@@ -1783,10 +1777,15 @@ class deribit extends deribit$1 {
1783
1777
  else {
1784
1778
  request['type'] = 'market';
1785
1779
  }
1786
- if (isStopOrder) {
1780
+ if (isTrailingAmountOrder) {
1781
+ request['trigger'] = trigger;
1782
+ request['type'] = 'trailing_stop';
1783
+ request['trigger_offset'] = this.parseToNumeric(trailingAmount);
1784
+ }
1785
+ else if (isStopOrder) {
1787
1786
  const triggerPrice = (stopLossPrice !== undefined) ? stopLossPrice : takeProfitPrice;
1788
1787
  request['trigger_price'] = this.priceToPrecision(symbol, triggerPrice);
1789
- request['trigger'] = 'last_price'; // required
1788
+ request['trigger'] = trigger;
1790
1789
  if (isStopLossOrder) {
1791
1790
  if (isMarketOrder) {
1792
1791
  // stop_market (sell only)
@@ -1826,7 +1825,7 @@ class deribit extends deribit$1 {
1826
1825
  request['time_in_force'] = 'fill_or_kill';
1827
1826
  }
1828
1827
  }
1829
- params = this.omit(params, ['timeInForce', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'reduceOnly']);
1828
+ params = this.omit(params, ['timeInForce', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'reduceOnly', 'trailingAmount']);
1830
1829
  let response = undefined;
1831
1830
  if (this.capitalize(side) === 'Buy') {
1832
1831
  response = await this.privateGetBuy(this.extend(request, params));
@@ -1893,25 +1892,43 @@ class deribit extends deribit$1 {
1893
1892
  return this.parseOrder(order, market);
1894
1893
  }
1895
1894
  async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
1895
+ /**
1896
+ * @method
1897
+ * @name deribit#editOrder
1898
+ * @description edit a trade order
1899
+ * @see https://docs.deribit.com/#private-edit
1900
+ * @param {string} id edit order id
1901
+ * @param {string} [symbol] unified symbol of the market to edit an order in
1902
+ * @param {string} [type] 'market' or 'limit'
1903
+ * @param {string} [side] 'buy' or 'sell'
1904
+ * @param {float} amount how much you want to trade in units of the base currency, inverse swap and future use the quote currency
1905
+ * @param {float} [price] the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
1906
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1907
+ * @param {float} [params.trailingAmount] the quote amount to trail away from the current market price
1908
+ * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
1909
+ */
1896
1910
  if (amount === undefined) {
1897
1911
  throw new errors.ArgumentsRequired(this.id + ' editOrder() requires an amount argument');
1898
1912
  }
1899
- if (price === undefined) {
1900
- throw new errors.ArgumentsRequired(this.id + ' editOrder() requires a price argument');
1901
- }
1902
1913
  await this.loadMarkets();
1903
1914
  const request = {
1904
1915
  'order_id': id,
1905
- // for perpetual and futures the amount is in USD
1906
- // for options it is in corresponding cryptocurrency contracts, e.g., BTC or ETH
1907
1916
  'amount': this.amountToPrecision(symbol, amount),
1908
- 'price': this.priceToPrecision(symbol, price), // required
1909
1917
  // 'post_only': false, // if the new price would cause the order to be filled immediately (as taker), the price will be changed to be just below the spread.
1910
1918
  // 'reject_post_only': false, // if true the order is put to order book unmodified or request is rejected
1911
1919
  // 'reduce_only': false, // if true, the order is intended to only reduce a current position
1912
1920
  // 'stop_price': false, // stop price, required for stop_limit orders
1913
1921
  // 'advanced': 'usd', // 'implv', advanced option order type, options only
1914
1922
  };
1923
+ if (price !== undefined) {
1924
+ request['price'] = this.priceToPrecision(symbol, price);
1925
+ }
1926
+ const trailingAmount = this.safeString2(params, 'trailingAmount', 'trigger_offset');
1927
+ const isTrailingAmountOrder = trailingAmount !== undefined;
1928
+ if (isTrailingAmountOrder) {
1929
+ request['trigger_offset'] = this.parseToNumeric(trailingAmount);
1930
+ params = this.omit(params, 'trigger_offset');
1931
+ }
1915
1932
  const response = await this.privateGetEdit(this.extend(request, params));
1916
1933
  const result = this.safeValue(response, 'result', {});
1917
1934
  const order = this.safeValue(result, 'order');
@@ -751,7 +751,7 @@ class kraken extends kraken$1 {
751
751
  'tierBased': true,
752
752
  };
753
753
  }
754
- parseBidAsk(bidask, priceKey = 0, amountKey = 1) {
754
+ parseBidAsk(bidask, priceKey = 0, amountKey = 1, countOrIdKey = 2) {
755
755
  const price = this.safeNumber(bidask, priceKey);
756
756
  const amount = this.safeNumber(bidask, amountKey);
757
757
  const timestamp = this.safeInteger(bidask, 2);
@@ -2419,7 +2419,7 @@ class kucoin extends kucoin$1 {
2419
2419
  // }
2420
2420
  // }
2421
2421
  const responseData = this.safeValue(response, 'data', {});
2422
- const orders = this.safeValue(responseData, 'items', []);
2422
+ const orders = this.safeValue(responseData, 'items', responseData);
2423
2423
  return this.parseOrders(orders, market, since, limit);
2424
2424
  }
2425
2425
  async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
@@ -3445,10 +3445,12 @@ class kucoin extends kucoin$1 {
3445
3445
  * @name kucoin#fetchBalance
3446
3446
  * @description query for balance and get the amount of funds available for trading or funds locked in orders
3447
3447
  * @see https://docs.kucoin.com/#list-accounts
3448
+ * @see https://www.kucoin.com/docs/rest/account/basic-info/get-account-list-spot-margin-trade_hf
3448
3449
  * @see https://docs.kucoin.com/#query-isolated-margin-account-info
3449
3450
  * @param {object} [params] extra parameters specific to the exchange API endpoint
3450
3451
  * @param {object} [params.marginMode] 'cross' or 'isolated', margin type for fetching margin balance
3451
3452
  * @param {object} [params.type] extra parameters specific to the exchange API endpoint
3453
+ * @param {object} [params.hf] *default if false* if true, the result includes the balance of the high frequency account
3452
3454
  * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
3453
3455
  */
3454
3456
  await this.loadMarkets();
@@ -3460,8 +3462,13 @@ class kucoin extends kucoin$1 {
3460
3462
  const defaultType = this.safeString2(this.options, 'fetchBalance', 'defaultType', 'spot');
3461
3463
  const requestedType = this.safeString(params, 'type', defaultType);
3462
3464
  const accountsByType = this.safeValue(this.options, 'accountsByType');
3463
- const type = this.safeString(accountsByType, requestedType, requestedType);
3465
+ let type = this.safeString(accountsByType, requestedType, requestedType);
3464
3466
  params = this.omit(params, 'type');
3467
+ const isHf = this.safeValue(params, 'hf', false);
3468
+ if (isHf) {
3469
+ type = 'trade_hf';
3470
+ }
3471
+ params = this.omit(params, 'hf');
3465
3472
  const [marginMode, query] = this.handleMarginModeAndParams('fetchBalance', params);
3466
3473
  let response = undefined;
3467
3474
  const request = {};
@@ -3543,7 +3550,7 @@ class kucoin extends kucoin$1 {
3543
3550
  'datetime': undefined,
3544
3551
  };
3545
3552
  if (isolated) {
3546
- const assets = this.safeValue(data, 'assets', []);
3553
+ const assets = this.safeValue(data, 'assets', data);
3547
3554
  for (let i = 0; i < assets.length; i++) {
3548
3555
  const entry = assets[i];
3549
3556
  const marketId = this.safeString(entry, 'symbol');
@@ -3874,12 +3881,14 @@ class kucoin extends kucoin$1 {
3874
3881
  * @method
3875
3882
  * @name kucoin#fetchLedger
3876
3883
  * @see https://docs.kucoin.com/#get-account-ledgers
3884
+ * @see https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-trade_hf
3885
+ * @see https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-margin_hf
3877
3886
  * @description fetch the history of changes, actions done by the user or operations that altered balance of the user
3878
- * @see https://docs.kucoin.com/#get-account-ledgers
3879
3887
  * @param {string} code unified currency code, default is undefined
3880
3888
  * @param {int} [since] timestamp in ms of the earliest ledger entry, default is undefined
3881
3889
  * @param {int} [limit] max number of ledger entrys to return, default is undefined
3882
3890
  * @param {object} [params] extra parameters specific to the exchange API endpoint
3891
+ * @param {boolean} [params.hf] default false, when true will fetch ledger entries for the high frequency trading account
3883
3892
  * @param {int} [params.until] the latest time in ms to fetch entries for
3884
3893
  * @param {boolean} [params.paginate] default false, when true will automatically paginate by calling this endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
3885
3894
  * @returns {object} a [ledger structure]{@link https://docs.ccxt.com/#/?id=ledger-structure}
@@ -3888,6 +3897,8 @@ class kucoin extends kucoin$1 {
3888
3897
  await this.loadAccounts();
3889
3898
  let paginate = false;
3890
3899
  [paginate, params] = this.handleOptionAndParams(params, 'fetchLedger', 'paginate');
3900
+ const isHf = this.safeValue(params, 'hf');
3901
+ params = this.omit(params, 'hf');
3891
3902
  if (paginate) {
3892
3903
  return await this.fetchPaginatedCallDynamic('fetchLedger', code, since, limit, params);
3893
3904
  }
@@ -3908,7 +3919,20 @@ class kucoin extends kucoin$1 {
3908
3919
  request['currency'] = currency['id'];
3909
3920
  }
3910
3921
  [request, params] = this.handleUntilOption('endAt', request, params);
3911
- const response = await this.privateGetAccountsLedgers(this.extend(request, params));
3922
+ let marginMode = undefined;
3923
+ [marginMode, params] = this.handleMarginModeAndParams('fetchLedger', params);
3924
+ let response = undefined;
3925
+ if (isHf) {
3926
+ if (marginMode !== undefined) {
3927
+ response = await this.privateGetHfMarginAccountLedgers(this.extend(request, params));
3928
+ }
3929
+ else {
3930
+ response = await this.privateGetHfAccountsLedgers(this.extend(request, params));
3931
+ }
3932
+ }
3933
+ else {
3934
+ response = await this.privateGetAccountsLedgers(this.extend(request, params));
3935
+ }
3912
3936
  //
3913
3937
  // {
3914
3938
  // "code":"200000",
@@ -3947,7 +3971,7 @@ class kucoin extends kucoin$1 {
3947
3971
  // }
3948
3972
  //
3949
3973
  const data = this.safeValue(response, 'data');
3950
- const items = this.safeValue(data, 'items');
3974
+ const items = this.safeValue(data, 'items', data);
3951
3975
  return this.parseLedger(items, currency, since, limit);
3952
3976
  }
3953
3977
  calculateRateLimiterCost(api, method, path, params, config = {}) {
@@ -1078,7 +1078,7 @@ class lykke extends lykke$1 {
1078
1078
  //
1079
1079
  return this.parseTrades(payload, market, since, limit);
1080
1080
  }
1081
- parseBidAsk(bidask, priceKey = 0, amountKey = 1) {
1081
+ parseBidAsk(bidask, priceKey = 0, amountKey = 1, countOrIdKey = 2) {
1082
1082
  const price = this.safeString(bidask, priceKey);
1083
1083
  const amount = Precise["default"].stringAbs(this.safeString(bidask, amountKey));
1084
1084
  return [this.parseNumber(price), this.parseNumber(amount)];
@@ -518,7 +518,7 @@ class ndax extends ndax$1 {
518
518
  'info': market,
519
519
  };
520
520
  }
521
- parseOrderBook(orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 6, amountKey = 8) {
521
+ parseOrderBook(orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 6, amountKey = 8, countOrIdKey = 2) {
522
522
  let nonce = undefined;
523
523
  const result = {
524
524
  'symbol': symbol,
@@ -290,25 +290,39 @@ class bitmart extends bitmart$1 {
290
290
  const market = this.getMarketFromSymbols(symbols);
291
291
  let type = 'spot';
292
292
  [type, params] = this.handleMarketTypeAndParams('watchTickers', market, params);
293
- symbols = this.marketSymbols(symbols);
294
- if (type === 'spot') {
295
- throw new errors.NotSupported(this.id + ' watchTickers() does not support ' + type + ' markets. Use watchTicker() instead');
296
- }
297
293
  const url = this.implodeHostname(this.urls['api']['ws'][type]['public']);
298
- if (type === 'swap') {
299
- type = 'futures';
300
- }
301
- let messageHash = 'tickers';
294
+ symbols = this.marketSymbols(symbols);
295
+ let messageHash = 'tickers::' + type;
302
296
  if (symbols !== undefined) {
303
297
  messageHash += '::' + symbols.join(',');
304
298
  }
305
- const request = {
306
- 'action': 'subscribe',
307
- 'args': ['futures/ticker'],
308
- };
309
- const newTickers = await this.watch(url, messageHash, this.deepExtend(request, params), messageHash);
299
+ let request = undefined;
300
+ let tickers = undefined;
301
+ const isSpot = (type === 'spot');
302
+ if (isSpot) {
303
+ if (symbols === undefined) {
304
+ throw new errors.ArgumentsRequired(this.id + ' watchTickers() for ' + type + ' market type requires symbols argument to be provided');
305
+ }
306
+ const marketIds = this.marketIds(symbols);
307
+ const finalArray = [];
308
+ for (let i = 0; i < marketIds.length; i++) {
309
+ finalArray.push('spot/ticker:' + marketIds[i]);
310
+ }
311
+ request = {
312
+ 'op': 'subscribe',
313
+ 'args': finalArray,
314
+ };
315
+ tickers = await this.watch(url, messageHash, this.deepExtend(request, params), messageHash);
316
+ }
317
+ else {
318
+ request = {
319
+ 'action': 'subscribe',
320
+ 'args': ['futures/ticker'],
321
+ };
322
+ tickers = await this.watch(url, messageHash, this.deepExtend(request, params), messageHash);
323
+ }
310
324
  if (this.newUpdates) {
311
- return newTickers;
325
+ return tickers;
312
326
  }
313
327
  return this.filterByArray(this.tickers, 'symbol', symbols);
314
328
  }
@@ -893,28 +907,36 @@ class bitmart extends bitmart$1 {
893
907
  const messageHash = table + ':' + marketId;
894
908
  this.tickers[symbol] = ticker;
895
909
  client.resolve(ticker, messageHash);
910
+ this.resolveMessageHashesForSymbol(client, symbol, ticker, 'tickers::');
896
911
  }
897
912
  }
898
913
  else {
914
+ // on each update for contract markets, single ticker is provided
899
915
  const ticker = this.parseWsSwapTicker(data);
900
916
  const symbol = this.safeString(ticker, 'symbol');
901
917
  this.tickers[symbol] = ticker;
902
- client.resolve(ticker, 'tickers');
903
- const messageHashes = this.findMessageHashes(client, 'tickers::');
904
- for (let i = 0; i < messageHashes.length; i++) {
905
- const messageHash = messageHashes[i];
906
- const parts = messageHash.split('::');
907
- const symbolsString = parts[1];
908
- const symbols = symbolsString.split(',');
909
- if (this.inArray(symbol, symbols)) {
910
- const response = {};
911
- response[symbol] = ticker;
912
- client.resolve(response, messageHash);
913
- }
914
- }
918
+ client.resolve(ticker, 'tickers::swap');
919
+ this.resolveMessageHashesForSymbol(client, symbol, ticker, 'tickers::');
915
920
  }
916
921
  return message;
917
922
  }
923
+ resolveMessageHashesForSymbol(client, symbol, result, prexif) {
924
+ const prefixSeparator = '::';
925
+ const symbolsSeparator = ',';
926
+ const messageHashes = this.findMessageHashes(client, prexif);
927
+ for (let i = 0; i < messageHashes.length; i++) {
928
+ const messageHash = messageHashes[i];
929
+ const parts = messageHash.split(prefixSeparator);
930
+ const length = parts.length;
931
+ const symbolsString = parts[length - 1];
932
+ const symbols = symbolsString.split(symbolsSeparator);
933
+ if (this.inArray(symbol, symbols)) {
934
+ const response = {};
935
+ response[symbol] = result;
936
+ client.resolve(response, messageHash);
937
+ }
938
+ }
939
+ }
918
940
  parseWsSwapTicker(ticker, market = undefined) {
919
941
  //
920
942
  // {
@@ -695,7 +695,7 @@ class blockchaincom extends blockchaincom$1 {
695
695
  return message;
696
696
  }
697
697
  else if (event === 'snapshot') {
698
- const snapshot = this.parseCountedOrderBook(message, symbol, timestamp, 'bids', 'asks', 'px', 'qty', 'num');
698
+ const snapshot = this.parseOrderBook(message, symbol, timestamp, 'bids', 'asks', 'px', 'qty', 'num');
699
699
  storedOrderBook.reset(snapshot);
700
700
  }
701
701
  else if (event === 'updated') {
@@ -711,34 +711,8 @@ class blockchaincom extends blockchaincom$1 {
711
711
  }
712
712
  client.resolve(storedOrderBook, messageHash);
713
713
  }
714
- parseCountedBidAsk(bidAsk, priceKey = 0, amountKey = 1, countKey = 2) {
715
- const price = this.safeNumber(bidAsk, priceKey);
716
- const amount = this.safeNumber(bidAsk, amountKey);
717
- const count = this.safeNumber(bidAsk, countKey);
718
- return [price, amount, count];
719
- }
720
- parseCountedBidsAsks(bidasks, priceKey = 0, amountKey = 1, countKey = 2) {
721
- bidasks = this.toArray(bidasks);
722
- const result = [];
723
- for (let i = 0; i < bidasks.length; i++) {
724
- result.push(this.parseCountedBidAsk(bidasks[i], priceKey, amountKey, countKey));
725
- }
726
- return result;
727
- }
728
- parseCountedOrderBook(orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 0, amountKey = 1, countKey = 2) {
729
- const bids = this.parseCountedBidsAsks(this.safeValue(orderbook, bidsKey, []), priceKey, amountKey, countKey);
730
- const asks = this.parseCountedBidsAsks(this.safeValue(orderbook, asksKey, []), priceKey, amountKey, countKey);
731
- return {
732
- 'symbol': symbol,
733
- 'bids': this.sortBy(bids, 0, true),
734
- 'asks': this.sortBy(asks, 0),
735
- 'timestamp': timestamp,
736
- 'datetime': this.iso8601(timestamp),
737
- 'nonce': undefined,
738
- };
739
- }
740
714
  handleDelta(bookside, delta) {
741
- const bookArray = this.parseCountedBidAsk(delta, 'px', 'qty', 'num');
715
+ const bookArray = this.parseBidAsk(delta, 'px', 'qty', 'num');
742
716
  bookside.storeArray(bookArray);
743
717
  }
744
718
  handleDeltas(bookside, deltas) {