ccxt 4.3.16 → 4.3.18

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.
package/README.md CHANGED
@@ -213,13 +213,13 @@ console.log(version, Object.keys(exchanges));
213
213
 
214
214
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
215
215
 
216
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.16/dist/ccxt.browser.js
217
- * unpkg: https://unpkg.com/ccxt@4.3.16/dist/ccxt.browser.js
216
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.3.18/dist/ccxt.browser.js
217
+ * unpkg: https://unpkg.com/ccxt@4.3.18/dist/ccxt.browser.js
218
218
 
219
219
  CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers.
220
220
 
221
221
  ```HTML
222
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.16/dist/ccxt.browser.js"></script>
222
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.3.18/dist/ccxt.browser.js"></script>
223
223
  ```
224
224
 
225
225
  Creates a global `ccxt` object:
package/dist/cjs/ccxt.js CHANGED
@@ -182,7 +182,7 @@ var woo$1 = require('./src/pro/woo.js');
182
182
 
183
183
  //-----------------------------------------------------------------------------
184
184
  // this is updated by vss.js when building
185
- const version = '4.3.16';
185
+ const version = '4.3.18';
186
186
  Exchange["default"].ccxtVersion = version;
187
187
  const exchanges = {
188
188
  'ace': ace,
@@ -3383,7 +3383,7 @@ class Exchange {
3383
3383
  }
3384
3384
  return networkId;
3385
3385
  }
3386
- networkIdToCode(networkId, currencyCode = undefined) {
3386
+ networkIdToCode(networkId = undefined, currencyCode = undefined) {
3387
3387
  /**
3388
3388
  * @ignore
3389
3389
  * @method
@@ -12,8 +12,9 @@ class Precise {
12
12
  let modifier = 0;
13
13
  number = number.toLowerCase();
14
14
  if (number.indexOf('e') > -1) {
15
- [number, modifier] = number.split('e');
16
- modifier = parseInt(modifier.toString());
15
+ let modifierString = '0';
16
+ [number, modifierString] = number.split('e');
17
+ modifier = parseInt(modifierString);
17
18
  }
18
19
  const decimalIndex = number.indexOf('.');
19
20
  this.decimals = (decimalIndex > -1) ? number.length - decimalIndex - 1 : 0;
@@ -2619,7 +2619,7 @@ class binance extends binance$1 {
2619
2619
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2620
2620
  * @returns {object} an associative dictionary of currencies
2621
2621
  */
2622
- const fetchCurrenciesEnabled = this.safeValue(this.options, 'fetchCurrencies');
2622
+ const fetchCurrenciesEnabled = this.safeBool(this.options, 'fetchCurrencies');
2623
2623
  if (!fetchCurrenciesEnabled) {
2624
2624
  return undefined;
2625
2625
  }
@@ -4543,7 +4543,7 @@ class binance extends binance$1 {
4543
4543
  market = this.safeMarket(marketId, market, undefined, marketType);
4544
4544
  const symbol = market['symbol'];
4545
4545
  let side = undefined;
4546
- const buyerMaker = this.safeValue2(trade, 'm', 'isBuyerMaker');
4546
+ const buyerMaker = this.safeBool2(trade, 'm', 'isBuyerMaker');
4547
4547
  let takerOrMaker = undefined;
4548
4548
  if (buyerMaker !== undefined) {
4549
4549
  side = buyerMaker ? 'sell' : 'buy'; // this is reversed intentionally
@@ -4851,7 +4851,7 @@ class binance extends binance$1 {
4851
4851
  uppercaseType = 'STOP_LOSS_LIMIT';
4852
4852
  }
4853
4853
  }
4854
- const validOrderTypes = this.safeValue(market['info'], 'orderTypes');
4854
+ const validOrderTypes = this.safeList(market['info'], 'orderTypes');
4855
4855
  if (!this.inArray(uppercaseType, validOrderTypes)) {
4856
4856
  if (initialUppercaseType !== uppercaseType) {
4857
4857
  throw new errors.InvalidOrder(this.id + ' stopPrice parameter is not allowed for ' + symbol + ' ' + type + ' orders');
@@ -4861,7 +4861,7 @@ class binance extends binance$1 {
4861
4861
  }
4862
4862
  }
4863
4863
  if (clientOrderId === undefined) {
4864
- const broker = this.safeValue(this.options, 'broker');
4864
+ const broker = this.safeDict(this.options, 'broker');
4865
4865
  if (broker !== undefined) {
4866
4866
  const brokerId = this.safeString(broker, 'spot');
4867
4867
  if (brokerId !== undefined) {
@@ -5747,6 +5747,7 @@ class binance extends binance$1 {
5747
5747
  * @param {float} [params.stopLossPrice] the price that a stop loss order is triggered at
5748
5748
  * @param {float} [params.takeProfitPrice] the price that a take profit order is triggered at
5749
5749
  * @param {boolean} [params.portfolioMargin] set to true if you would like to create an order in a portfolio margin account
5750
+ * @param {string} [params.stopLossOrTakeProfit] 'stopLoss' or 'takeProfit', required for spot trailing orders
5750
5751
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
5751
5752
  */
5752
5753
  await this.loadMarkets();
@@ -5872,8 +5873,8 @@ class binance extends binance$1 {
5872
5873
  const stopLossPrice = this.safeString(params, 'stopLossPrice', triggerPrice); // fallback to stopLoss
5873
5874
  const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
5874
5875
  const trailingDelta = this.safeString(params, 'trailingDelta');
5875
- const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activationPrice', this.numberToString(price));
5876
- const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRate');
5876
+ const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activationPrice');
5877
+ const trailingPercent = this.safeStringN(params, ['trailingPercent', 'callbackRate', 'trailingDelta']);
5877
5878
  const priceMatch = this.safeString(params, 'priceMatch');
5878
5879
  const isTrailingPercentOrder = trailingPercent !== undefined;
5879
5880
  const isStopLoss = stopLossPrice !== undefined || trailingDelta !== undefined;
@@ -5885,10 +5886,33 @@ class binance extends binance$1 {
5885
5886
  let uppercaseType = type.toUpperCase();
5886
5887
  let stopPrice = undefined;
5887
5888
  if (isTrailingPercentOrder) {
5888
- uppercaseType = 'TRAILING_STOP_MARKET';
5889
- request['callbackRate'] = trailingPercent;
5890
- if (trailingTriggerPrice !== undefined) {
5891
- request['activationPrice'] = this.priceToPrecision(symbol, trailingTriggerPrice);
5889
+ if (market['swap']) {
5890
+ uppercaseType = 'TRAILING_STOP_MARKET';
5891
+ request['callbackRate'] = trailingPercent;
5892
+ if (trailingTriggerPrice !== undefined) {
5893
+ request['activationPrice'] = this.priceToPrecision(symbol, trailingTriggerPrice);
5894
+ }
5895
+ }
5896
+ else {
5897
+ if (isMarketOrder) {
5898
+ throw new errors.InvalidOrder(this.id + ' trailingPercent orders are not supported for ' + symbol + ' ' + type + ' orders');
5899
+ }
5900
+ const stopLossOrTakeProfit = this.safeString(params, 'stopLossOrTakeProfit');
5901
+ params = this.omit(params, 'stopLossOrTakeProfit');
5902
+ if (stopLossOrTakeProfit !== 'stopLoss' && stopLossOrTakeProfit !== 'takeProfit') {
5903
+ throw new errors.InvalidOrder(this.id + symbol + ' trailingPercent orders require a stopLossOrTakeProfit parameter of either stopLoss or takeProfit');
5904
+ }
5905
+ if (stopLossOrTakeProfit === 'stopLoss') {
5906
+ uppercaseType = 'STOP_LOSS_LIMIT';
5907
+ }
5908
+ else if (stopLossOrTakeProfit === 'takeProfit') {
5909
+ uppercaseType = 'TAKE_PROFIT_LIMIT';
5910
+ }
5911
+ if (trailingTriggerPrice !== undefined) {
5912
+ stopPrice = this.priceToPrecision(symbol, trailingTriggerPrice);
5913
+ }
5914
+ const trailingPercentConverted = Precise["default"].stringMul(trailingPercent, '100');
5915
+ request['trailingDelta'] = trailingPercentConverted;
5892
5916
  }
5893
5917
  }
5894
5918
  else if (isStopLoss) {
@@ -6075,8 +6099,8 @@ class binance extends binance$1 {
6075
6099
  }
6076
6100
  else {
6077
6101
  // check for delta price as well
6078
- if (trailingDelta === undefined && stopPrice === undefined) {
6079
- throw new errors.InvalidOrder(this.id + ' createOrder() requires a stopPrice or trailingDelta param for a ' + type + ' order');
6102
+ if (trailingDelta === undefined && stopPrice === undefined && trailingPercent === undefined) {
6103
+ throw new errors.InvalidOrder(this.id + ' createOrder() requires a stopPrice, trailingDelta or trailingPercent param for a ' + type + ' order');
6080
6104
  }
6081
6105
  }
6082
6106
  if (stopPrice !== undefined) {
@@ -7660,7 +7684,7 @@ class binance extends binance$1 {
7660
7684
  request['endTime'] = until;
7661
7685
  }
7662
7686
  const raw = await this.sapiGetFiatOrders(this.extend(request, params));
7663
- response = this.safeValue(raw, 'data');
7687
+ response = this.safeList(raw, 'data', []);
7664
7688
  // {
7665
7689
  // "code": "000000",
7666
7690
  // "message": "success",
@@ -7775,7 +7799,7 @@ class binance extends binance$1 {
7775
7799
  request['beginTime'] = since;
7776
7800
  }
7777
7801
  const raw = await this.sapiGetFiatOrders(this.extend(request, params));
7778
- response = this.safeValue(raw, 'data');
7802
+ response = this.safeList(raw, 'data', []);
7779
7803
  // {
7780
7804
  // "code": "000000",
7781
7805
  // "message": "success",
@@ -7993,7 +8017,7 @@ class binance extends binance$1 {
7993
8017
  if (txType !== undefined) {
7994
8018
  type = (txType === '0') ? 'deposit' : 'withdrawal';
7995
8019
  }
7996
- const legalMoneyCurrenciesById = this.safeValue(this.options, 'legalMoneyCurrenciesById');
8020
+ const legalMoneyCurrenciesById = this.safeDict(this.options, 'legalMoneyCurrenciesById');
7997
8021
  code = this.safeString(legalMoneyCurrenciesById, code, code);
7998
8022
  }
7999
8023
  const status = this.parseTransactionStatusByType(this.safeString(transaction, 'status'), type);
@@ -8347,7 +8371,7 @@ class binance extends binance$1 {
8347
8371
  }
8348
8372
  }
8349
8373
  impliedNetwork = this.safeString(reverseNetworks, topLevel);
8350
- const impliedNetworks = this.safeValue(this.options, 'impliedNetworks', {
8374
+ const impliedNetworks = this.safeDict(this.options, 'impliedNetworks', {
8351
8375
  'ETH': { 'ERC20': 'ETH' },
8352
8376
  'TRX': { 'TRC20': 'TRX' },
8353
8377
  });
@@ -9656,7 +9680,7 @@ class binance extends binance$1 {
9656
9680
  await this.loadMarkets();
9657
9681
  // by default cache the leverage bracket
9658
9682
  // it contains useful stuff like the maintenance margin and initial margin for positions
9659
- const leverageBrackets = this.safeValue(this.options, 'leverageBrackets');
9683
+ const leverageBrackets = this.safeDict(this.options, 'leverageBrackets', {});
9660
9684
  if ((leverageBrackets === undefined) || (reload)) {
9661
9685
  const defaultType = this.safeString(this.options, 'defaultType', 'future');
9662
9686
  const type = this.safeString(params, 'type', defaultType);
@@ -1491,6 +1491,7 @@ class bybit extends bybit$1 {
1491
1491
  // "quoteCoin": "USDT",
1492
1492
  // "innovation": "0",
1493
1493
  // "status": "Trading",
1494
+ // "marginTrading": "both",
1494
1495
  // "lotSizeFilter": {
1495
1496
  // "basePrecision": "0.000001",
1496
1497
  // "quotePrecision": "0.00000001",
@@ -1527,7 +1528,9 @@ class bybit extends bybit$1 {
1527
1528
  const lotSizeFilter = this.safeDict(market, 'lotSizeFilter');
1528
1529
  const priceFilter = this.safeDict(market, 'priceFilter');
1529
1530
  const quotePrecision = this.safeNumber(lotSizeFilter, 'quotePrecision');
1530
- result.push({
1531
+ const marginTrading = this.safeString(market, 'marginTrading', 'none');
1532
+ const allowsMargin = marginTrading !== 'none';
1533
+ result.push(this.safeMarketStructure({
1531
1534
  'id': id,
1532
1535
  'symbol': symbol,
1533
1536
  'base': base,
@@ -1538,7 +1541,7 @@ class bybit extends bybit$1 {
1538
1541
  'settleId': undefined,
1539
1542
  'type': 'spot',
1540
1543
  'spot': true,
1541
- 'margin': undefined,
1544
+ 'margin': allowsMargin,
1542
1545
  'swap': false,
1543
1546
  'future': false,
1544
1547
  'option': false,
@@ -1577,7 +1580,7 @@ class bybit extends bybit$1 {
1577
1580
  },
1578
1581
  'created': undefined,
1579
1582
  'info': market,
1580
- });
1583
+ }));
1581
1584
  }
1582
1585
  return result;
1583
1586
  }
@@ -1702,7 +1705,7 @@ class bybit extends bybit$1 {
1702
1705
  symbol = symbol + '-' + this.yymmdd(expiry);
1703
1706
  }
1704
1707
  const contractSize = inverse ? this.safeNumber2(lotSizeFilter, 'minTradingQty', 'minOrderQty') : this.parseNumber('1');
1705
- result.push({
1708
+ result.push(this.safeMarketStructure({
1706
1709
  'id': id,
1707
1710
  'symbol': symbol,
1708
1711
  'base': base,
@@ -1752,7 +1755,7 @@ class bybit extends bybit$1 {
1752
1755
  },
1753
1756
  'created': this.safeInteger(market, 'launchTime'),
1754
1757
  'info': market,
1755
- });
1758
+ }));
1756
1759
  }
1757
1760
  return result;
1758
1761
  }
@@ -1835,7 +1838,7 @@ class bybit extends bybit$1 {
1835
1838
  const optionLetter = this.safeString(splitId, 3);
1836
1839
  const isActive = (status === 'Trading');
1837
1840
  if (isActive || (this.options['loadAllOptions']) || (this.options['loadExpiredOptions'])) {
1838
- result.push({
1841
+ result.push(this.safeMarketStructure({
1839
1842
  'id': id,
1840
1843
  'symbol': base + '/' + quote + ':' + settle + '-' + this.yymmdd(expiry) + '-' + strike + '-' + optionLetter,
1841
1844
  'base': base,
@@ -1885,7 +1888,7 @@ class bybit extends bybit$1 {
1885
1888
  },
1886
1889
  'created': this.safeInteger(market, 'launchTime'),
1887
1890
  'info': market,
1888
- });
1891
+ }));
1889
1892
  }
1890
1893
  }
1891
1894
  return result;
@@ -3303,7 +3303,7 @@ class htx extends htx$1 {
3303
3303
  }
3304
3304
  return result;
3305
3305
  }
3306
- networkIdToCode(networkId, currencyCode = undefined) {
3306
+ networkIdToCode(networkId = undefined, currencyCode = undefined) {
3307
3307
  // here network-id is provided as a pair of currency & chain (i.e. trc20usdt)
3308
3308
  const keys = Object.keys(this.options['networkNamesByChainIds']);
3309
3309
  const keysLength = keys.length;
@@ -889,7 +889,24 @@ class okx extends okx$1 {
889
889
  '60017': errors.BadRequest,
890
890
  '60018': errors.BadRequest,
891
891
  '60019': errors.BadRequest,
892
+ '60020': errors.ExchangeError,
893
+ '60021': errors.AccountNotEnabled,
894
+ '60022': errors.AuthenticationError,
895
+ '60023': errors.DDoSProtection,
896
+ '60024': errors.AuthenticationError,
897
+ '60025': errors.ExchangeError,
898
+ '60026': errors.AuthenticationError,
899
+ '60027': errors.ArgumentsRequired,
900
+ '60028': errors.NotSupported,
901
+ '60029': errors.AccountNotEnabled,
902
+ '60030': errors.AccountNotEnabled,
903
+ '60031': errors.AuthenticationError,
904
+ '60032': errors.AuthenticationError,
892
905
  '63999': errors.ExchangeError,
906
+ '64000': errors.BadRequest,
907
+ '64001': errors.BadRequest,
908
+ '64002': errors.BadRequest,
909
+ '64003': errors.AccountNotEnabled,
893
910
  '70010': errors.BadRequest,
894
911
  '70013': errors.BadRequest,
895
912
  '70016': errors.BadRequest, // Please specify your instrument settings for at least one instType.
@@ -682,6 +682,8 @@ class bitfinex2 extends bitfinex2$1 {
682
682
  const responseChecksum = this.safeInteger(message, 2);
683
683
  if (responseChecksum !== localChecksum) {
684
684
  const error = new errors.InvalidNonce(this.id + ' invalid checksum');
685
+ delete client.subscriptions[messageHash];
686
+ delete this.orderbooks[symbol];
685
687
  client.reject(error, messageHash);
686
688
  }
687
689
  }
@@ -560,7 +560,10 @@ class bitget extends bitget$1 {
560
560
  const responseChecksum = this.safeInteger(rawOrderBook, 'checksum');
561
561
  if (calculatedChecksum !== responseChecksum) {
562
562
  const error = new errors.InvalidNonce(this.id + ' invalid checksum');
563
+ delete client.subscriptions[messageHash];
564
+ delete this.orderbooks[symbol];
563
565
  client.reject(error, messageHash);
566
+ return;
564
567
  }
565
568
  }
566
569
  }
@@ -12,11 +12,11 @@ class bybit extends bybit$1 {
12
12
  return this.deepExtend(super.describe(), {
13
13
  'has': {
14
14
  'ws': true,
15
- 'createOrderWs': false,
16
- 'editOrderWs': false,
15
+ 'createOrderWs': true,
16
+ 'editOrderWs': true,
17
17
  'fetchOpenOrdersWs': false,
18
18
  'fetchOrderWs': false,
19
- 'cancelOrderWs': false,
19
+ 'cancelOrderWs': true,
20
20
  'cancelOrdersWs': false,
21
21
  'cancelAllOrdersWs': false,
22
22
  'fetchTradesWs': false,
@@ -50,7 +50,7 @@ class bybit extends bybit$1 {
50
50
  },
51
51
  'contract': 'wss://stream.{hostname}/v5/private',
52
52
  'usdc': 'wss://stream.{hostname}/trade/option/usdc/private/v1',
53
- 'trade': 'wss://stream-testnet.bybit.com/v5/trade',
53
+ 'trade': 'wss://stream.bybit.com/v5/trade',
54
54
  },
55
55
  },
56
56
  },
@@ -284,7 +284,9 @@ class bybit extends bybit$1 {
284
284
  const url = this.urls['api']['ws']['private']['trade'];
285
285
  await this.authenticate(url);
286
286
  const requestId = this.requestId().toString();
287
- delete orderRequest['orderFilter'];
287
+ if ('orderFilter' in orderRequest) {
288
+ delete orderRequest['orderFilter'];
289
+ }
288
290
  const request = {
289
291
  'op': 'order.cancel',
290
292
  'reqId': requestId,
@@ -432,6 +432,8 @@ class htx extends htx$1 {
432
432
  }
433
433
  }
434
434
  catch (e) {
435
+ delete client.subscriptions[messageHash];
436
+ delete this.orderbooks[symbol];
435
437
  client.reject(e, messageHash);
436
438
  }
437
439
  }
@@ -217,6 +217,8 @@ class independentreserve extends independentreserve$1 {
217
217
  const responseChecksum = this.safeInteger(orderBook, 'Crc32');
218
218
  if (calculatedChecksum !== responseChecksum) {
219
219
  const error = new errors.InvalidNonce(this.id + ' invalid checksum');
220
+ delete client.subscriptions[messageHash];
221
+ delete this.orderbooks[symbol];
220
222
  client.reject(error, messageHash);
221
223
  }
222
224
  }
@@ -767,6 +767,8 @@ class kraken extends kraken$1 {
767
767
  const localChecksum = this.crc32(payload, false);
768
768
  if (localChecksum !== c) {
769
769
  const error = new errors.InvalidNonce(this.id + ' invalid checksum');
770
+ delete client.subscriptions[messageHash];
771
+ delete this.orderbooks[symbol];
770
772
  client.reject(error, messageHash);
771
773
  return;
772
774
  }
@@ -450,10 +450,12 @@ class okx extends okx$1 {
450
450
  /**
451
451
  * @method
452
452
  * @name okx#watchOrderBook
453
+ * @see https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-order-book-channel
453
454
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
454
455
  * @param {string} symbol unified symbol of the market to fetch the order book for
455
456
  * @param {int} [limit] the maximum amount of order book entries to return
456
457
  * @param {object} [params] extra parameters specific to the exchange API endpoint
458
+ * @param {string} [params.depth] okx order book depth, can be books, books5, books-l2-tbt, books50-l2-tbt, bbo-tbt
457
459
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
458
460
  */
459
461
  //
@@ -485,16 +487,18 @@ class okx extends okx$1 {
485
487
  /**
486
488
  * @method
487
489
  * @name okx#watchOrderBookForSymbols
490
+ * @see https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-order-book-channel
488
491
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
489
492
  * @param {string[]} symbols unified array of symbols
490
493
  * @param {int} [limit] 1,5, 400, 50 (l2-tbt, vip4+) or 40000 (vip5+) the maximum amount of order book entries to return
491
494
  * @param {object} [params] extra parameters specific to the exchange API endpoint
495
+ * @param {string} [params.depth] okx order book depth, can be books, books5, books-l2-tbt, books50-l2-tbt, bbo-tbt
492
496
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
493
497
  */
494
498
  await this.loadMarkets();
495
499
  symbols = this.marketSymbols(symbols);
496
- const options = this.safeValue(this.options, 'watchOrderBook', {});
497
- let depth = this.safeString(options, 'depth', 'books');
500
+ let depth = undefined;
501
+ [depth, params] = this.handleOptionAndParams(params, 'watchOrderBook', 'depth', 'books');
498
502
  if (limit !== undefined) {
499
503
  if (limit === 1) {
500
504
  depth = 'bbo-tbt';
@@ -502,17 +506,17 @@ class okx extends okx$1 {
502
506
  else if (limit > 1 && limit <= 5) {
503
507
  depth = 'books5';
504
508
  }
505
- else if (limit === 400) {
506
- depth = 'books';
507
- }
508
509
  else if (limit === 50) {
509
510
  depth = 'books50-l2-tbt'; // Make sure you have VIP4 and above
510
511
  }
511
- else if (limit === 4000) {
512
- depth = 'books-l2-tbt'; // Make sure you have VIP5 and above
512
+ else if (limit === 400) {
513
+ depth = 'books';
513
514
  }
514
515
  }
515
516
  if ((depth === 'books-l2-tbt') || (depth === 'books50-l2-tbt')) {
517
+ if (!this.checkRequiredCredentials(false)) {
518
+ throw new errors.AuthenticationError(this.id + ' watchOrderBook/watchOrderBookForSymbols requires authentication for this depth. Add credentials or change the depth option to books or books5');
519
+ }
516
520
  await this.authenticate({ 'access': 'public' });
517
521
  }
518
522
  const topics = [];
@@ -576,6 +580,8 @@ class okx extends okx$1 {
576
580
  const storedBids = orderbook['bids'];
577
581
  this.handleDeltas(storedAsks, asks);
578
582
  this.handleDeltas(storedBids, bids);
583
+ const marketId = this.safeString(message, 'instId');
584
+ const symbol = this.safeSymbol(marketId);
579
585
  const checksum = this.safeBool(this.options, 'checksum', true);
580
586
  if (checksum) {
581
587
  const asksLength = storedAsks.length;
@@ -596,6 +602,8 @@ class okx extends okx$1 {
596
602
  const localChecksum = this.crc32(payload, true);
597
603
  if (responseChecksum !== localChecksum) {
598
604
  const error = new errors.InvalidNonce(this.id + ' invalid checksum');
605
+ delete client.subscriptions[messageHash];
606
+ delete this.orderbooks[symbol];
599
607
  client.reject(error, messageHash);
600
608
  }
601
609
  }
@@ -690,10 +698,10 @@ class okx extends okx$1 {
690
698
  // ]
691
699
  // }
692
700
  //
693
- const arg = this.safeValue(message, 'arg', {});
701
+ const arg = this.safeDict(message, 'arg', {});
694
702
  const channel = this.safeString(arg, 'channel');
695
703
  const action = this.safeString(message, 'action');
696
- const data = this.safeValue(message, 'data', []);
704
+ const data = this.safeList(message, 'data', []);
697
705
  const marketId = this.safeString(arg, 'instId');
698
706
  const market = this.safeMarket(marketId);
699
707
  const symbol = market['symbol'];
@@ -1523,29 +1531,21 @@ class okx extends okx$1 {
1523
1531
  // { event: 'error', msg: "Illegal request: {"op":"subscribe","args":["spot/ticker:BTC-USDT"]}", code: "60012" }
1524
1532
  // { event: 'error", msg: "channel:ticker,instId:BTC-USDT doesn"t exist", code: "60018" }
1525
1533
  //
1526
- const errorCode = this.safeInteger(message, 'code');
1534
+ const errorCode = this.safeString(message, 'code');
1527
1535
  try {
1528
- if (errorCode) {
1536
+ if (errorCode && errorCode !== '0') {
1529
1537
  const feedback = this.id + ' ' + this.json(message);
1530
1538
  this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
1531
1539
  const messageString = this.safeValue(message, 'msg');
1532
1540
  if (messageString !== undefined) {
1533
1541
  this.throwBroadlyMatchedException(this.exceptions['broad'], messageString, feedback);
1534
1542
  }
1543
+ throw new errors.ExchangeError(feedback);
1535
1544
  }
1536
1545
  }
1537
1546
  catch (e) {
1538
- if (e instanceof errors.AuthenticationError) {
1539
- const messageHash = 'authenticated';
1540
- client.reject(e, messageHash);
1541
- if (messageHash in client.subscriptions) {
1542
- delete client.subscriptions[messageHash];
1543
- }
1544
- return false;
1545
- }
1546
- else {
1547
- client.reject(e);
1548
- }
1547
+ client.reject(e);
1548
+ return false;
1549
1549
  }
1550
1550
  return message;
1551
1551
  }
package/js/ccxt.d.ts CHANGED
@@ -4,7 +4,7 @@ import * as functions from './src/base/functions.js';
4
4
  import * as errors from './src/base/errors.js';
5
5
  import type { Market, Trade, Fee, Ticker, OrderBook, Order, Transaction, Tickers, Currency, Balance, DepositAddress, WithdrawalResponse, DepositAddressResponse, OHLCV, Balances, PartialBalances, Dictionary, MinMax, Position, FundingRateHistory, Liquidation, FundingHistory, MarginMode, Greeks, Leverage, Leverages, Option, OptionChain, Conversion } from './src/base/types.js';
6
6
  import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, ProxyError, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout } from './src/base/errors.js';
7
- declare const version = "4.3.15";
7
+ declare const version = "4.3.17";
8
8
  import ace from './src/ace.js';
9
9
  import alpaca from './src/alpaca.js';
10
10
  import ascendex from './src/ascendex.js';
package/js/ccxt.js CHANGED
@@ -38,7 +38,7 @@ import * as errors from './src/base/errors.js';
38
38
  import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, ProxyError, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout } from './src/base/errors.js';
39
39
  //-----------------------------------------------------------------------------
40
40
  // this is updated by vss.js when building
41
- const version = '4.3.16';
41
+ const version = '4.3.18';
42
42
  Exchange.ccxtVersion = version;
43
43
  //-----------------------------------------------------------------------------
44
44
  import ace from './src/ace.js';
@@ -816,7 +816,7 @@ export default class Exchange {
816
816
  filterBySymbol(objects: any, symbol?: Str): any;
817
817
  parseOHLCV(ohlcv: any, market?: Market): OHLCV;
818
818
  networkCodeToId(networkCode: string, currencyCode?: Str): string;
819
- networkIdToCode(networkId: string, currencyCode?: Str): string;
819
+ networkIdToCode(networkId?: Str, currencyCode?: Str): string;
820
820
  handleNetworkCodeAndParams(params: any): any[];
821
821
  defaultNetworkCode(currencyCode: string): any;
822
822
  selectNetworkCodeFromUnifiedNetworks(currencyCode: any, networkCode: any, indexedNetworkEntries: any): any;
@@ -3370,7 +3370,7 @@ export default class Exchange {
3370
3370
  }
3371
3371
  return networkId;
3372
3372
  }
3373
- networkIdToCode(networkId, currencyCode = undefined) {
3373
+ networkIdToCode(networkId = undefined, currencyCode = undefined) {
3374
3374
  /**
3375
3375
  * @ignore
3376
3376
  * @method
@@ -3,38 +3,38 @@ declare class Precise {
3
3
  decimals: number;
4
4
  integer: bigint;
5
5
  base: any;
6
- constructor(number: any, decimals?: Int);
7
- mul(other: any): Precise;
8
- div(other: any, precision?: number): Precise;
9
- add(other: any): Precise;
10
- mod(other: any): Precise;
11
- sub(other: any): Precise;
6
+ constructor(number: bigint | string, decimals?: Int);
7
+ mul(other: Precise): Precise;
8
+ div(other: Precise, precision?: number): Precise;
9
+ add(other: Precise): Precise;
10
+ mod(other: Precise): Precise;
11
+ sub(other: Precise): Precise;
12
12
  abs(): Precise;
13
13
  neg(): Precise;
14
- min(other: any): any;
15
- max(other: any): any;
16
- gt(other: any): boolean;
17
- ge(other: any): boolean;
18
- lt(other: any): any;
19
- le(other: any): any;
14
+ min(other: Precise): Precise;
15
+ max(other: Precise): Precise;
16
+ gt(other: Precise): boolean;
17
+ ge(other: Precise): boolean;
18
+ lt(other: Precise): boolean;
19
+ le(other: Precise): boolean;
20
20
  reduce(): this;
21
21
  equals(other: any): boolean;
22
22
  toString(): string;
23
23
  static stringMul(string1: Str, string2: Str): string;
24
- static stringDiv(string1: any, string2: any, precision?: number): string;
24
+ static stringDiv(string1: Str, string2: Str, precision?: number): string;
25
25
  static stringAdd(string1: Str, string2: Str): string;
26
26
  static stringSub(string1: Str, string2: Str): string;
27
- static stringAbs(string: any): string;
28
- static stringNeg(string: any): string;
27
+ static stringAbs(string: Str): string;
28
+ static stringNeg(string: Str): string;
29
29
  static stringMod(string1: Str, string2: Str): string;
30
30
  static stringEquals(string1: Str, string2: Str): boolean;
31
31
  static stringEq(string1: Str, string2: Str): boolean;
32
- static stringMin(string1: Str, string2: Str): any;
33
- static stringMax(string1: Str, string2: Str): any;
32
+ static stringMin(string1: Str, string2: Str): string;
33
+ static stringMax(string1: Str, string2: Str): string;
34
34
  static stringGt(string1: Str, string2: Str): boolean;
35
35
  static stringGe(string1: Str, string2: Str): boolean;
36
- static stringLt(string1: Str, string2: Str): any;
37
- static stringLe(string1: Str, string2: Str): any;
36
+ static stringLt(string1: Str, string2: Str): boolean;
37
+ static stringLe(string1: Str, string2: Str): boolean;
38
38
  }
39
39
  export default Precise;
40
40
  export { Precise };
@@ -14,8 +14,9 @@ class Precise {
14
14
  let modifier = 0;
15
15
  number = number.toLowerCase();
16
16
  if (number.indexOf('e') > -1) {
17
- [number, modifier] = number.split('e');
18
- modifier = parseInt(modifier.toString());
17
+ let modifierString = '0';
18
+ [number, modifierString] = number.split('e');
19
+ modifier = parseInt(modifierString);
19
20
  }
20
21
  const decimalIndex = number.indexOf('.');
21
22
  this.decimals = (decimalIndex > -1) ? number.length - decimalIndex - 1 : 0;
package/js/src/binance.js CHANGED
@@ -2622,7 +2622,7 @@ export default class binance extends Exchange {
2622
2622
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2623
2623
  * @returns {object} an associative dictionary of currencies
2624
2624
  */
2625
- const fetchCurrenciesEnabled = this.safeValue(this.options, 'fetchCurrencies');
2625
+ const fetchCurrenciesEnabled = this.safeBool(this.options, 'fetchCurrencies');
2626
2626
  if (!fetchCurrenciesEnabled) {
2627
2627
  return undefined;
2628
2628
  }
@@ -4546,7 +4546,7 @@ export default class binance extends Exchange {
4546
4546
  market = this.safeMarket(marketId, market, undefined, marketType);
4547
4547
  const symbol = market['symbol'];
4548
4548
  let side = undefined;
4549
- const buyerMaker = this.safeValue2(trade, 'm', 'isBuyerMaker');
4549
+ const buyerMaker = this.safeBool2(trade, 'm', 'isBuyerMaker');
4550
4550
  let takerOrMaker = undefined;
4551
4551
  if (buyerMaker !== undefined) {
4552
4552
  side = buyerMaker ? 'sell' : 'buy'; // this is reversed intentionally
@@ -4854,7 +4854,7 @@ export default class binance extends Exchange {
4854
4854
  uppercaseType = 'STOP_LOSS_LIMIT';
4855
4855
  }
4856
4856
  }
4857
- const validOrderTypes = this.safeValue(market['info'], 'orderTypes');
4857
+ const validOrderTypes = this.safeList(market['info'], 'orderTypes');
4858
4858
  if (!this.inArray(uppercaseType, validOrderTypes)) {
4859
4859
  if (initialUppercaseType !== uppercaseType) {
4860
4860
  throw new InvalidOrder(this.id + ' stopPrice parameter is not allowed for ' + symbol + ' ' + type + ' orders');
@@ -4864,7 +4864,7 @@ export default class binance extends Exchange {
4864
4864
  }
4865
4865
  }
4866
4866
  if (clientOrderId === undefined) {
4867
- const broker = this.safeValue(this.options, 'broker');
4867
+ const broker = this.safeDict(this.options, 'broker');
4868
4868
  if (broker !== undefined) {
4869
4869
  const brokerId = this.safeString(broker, 'spot');
4870
4870
  if (brokerId !== undefined) {
@@ -5750,6 +5750,7 @@ export default class binance extends Exchange {
5750
5750
  * @param {float} [params.stopLossPrice] the price that a stop loss order is triggered at
5751
5751
  * @param {float} [params.takeProfitPrice] the price that a take profit order is triggered at
5752
5752
  * @param {boolean} [params.portfolioMargin] set to true if you would like to create an order in a portfolio margin account
5753
+ * @param {string} [params.stopLossOrTakeProfit] 'stopLoss' or 'takeProfit', required for spot trailing orders
5753
5754
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
5754
5755
  */
5755
5756
  await this.loadMarkets();
@@ -5875,8 +5876,8 @@ export default class binance extends Exchange {
5875
5876
  const stopLossPrice = this.safeString(params, 'stopLossPrice', triggerPrice); // fallback to stopLoss
5876
5877
  const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
5877
5878
  const trailingDelta = this.safeString(params, 'trailingDelta');
5878
- const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activationPrice', this.numberToString(price));
5879
- const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRate');
5879
+ const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activationPrice');
5880
+ const trailingPercent = this.safeStringN(params, ['trailingPercent', 'callbackRate', 'trailingDelta']);
5880
5881
  const priceMatch = this.safeString(params, 'priceMatch');
5881
5882
  const isTrailingPercentOrder = trailingPercent !== undefined;
5882
5883
  const isStopLoss = stopLossPrice !== undefined || trailingDelta !== undefined;
@@ -5888,10 +5889,33 @@ export default class binance extends Exchange {
5888
5889
  let uppercaseType = type.toUpperCase();
5889
5890
  let stopPrice = undefined;
5890
5891
  if (isTrailingPercentOrder) {
5891
- uppercaseType = 'TRAILING_STOP_MARKET';
5892
- request['callbackRate'] = trailingPercent;
5893
- if (trailingTriggerPrice !== undefined) {
5894
- request['activationPrice'] = this.priceToPrecision(symbol, trailingTriggerPrice);
5892
+ if (market['swap']) {
5893
+ uppercaseType = 'TRAILING_STOP_MARKET';
5894
+ request['callbackRate'] = trailingPercent;
5895
+ if (trailingTriggerPrice !== undefined) {
5896
+ request['activationPrice'] = this.priceToPrecision(symbol, trailingTriggerPrice);
5897
+ }
5898
+ }
5899
+ else {
5900
+ if (isMarketOrder) {
5901
+ throw new InvalidOrder(this.id + ' trailingPercent orders are not supported for ' + symbol + ' ' + type + ' orders');
5902
+ }
5903
+ const stopLossOrTakeProfit = this.safeString(params, 'stopLossOrTakeProfit');
5904
+ params = this.omit(params, 'stopLossOrTakeProfit');
5905
+ if (stopLossOrTakeProfit !== 'stopLoss' && stopLossOrTakeProfit !== 'takeProfit') {
5906
+ throw new InvalidOrder(this.id + symbol + ' trailingPercent orders require a stopLossOrTakeProfit parameter of either stopLoss or takeProfit');
5907
+ }
5908
+ if (stopLossOrTakeProfit === 'stopLoss') {
5909
+ uppercaseType = 'STOP_LOSS_LIMIT';
5910
+ }
5911
+ else if (stopLossOrTakeProfit === 'takeProfit') {
5912
+ uppercaseType = 'TAKE_PROFIT_LIMIT';
5913
+ }
5914
+ if (trailingTriggerPrice !== undefined) {
5915
+ stopPrice = this.priceToPrecision(symbol, trailingTriggerPrice);
5916
+ }
5917
+ const trailingPercentConverted = Precise.stringMul(trailingPercent, '100');
5918
+ request['trailingDelta'] = trailingPercentConverted;
5895
5919
  }
5896
5920
  }
5897
5921
  else if (isStopLoss) {
@@ -6078,8 +6102,8 @@ export default class binance extends Exchange {
6078
6102
  }
6079
6103
  else {
6080
6104
  // check for delta price as well
6081
- if (trailingDelta === undefined && stopPrice === undefined) {
6082
- throw new InvalidOrder(this.id + ' createOrder() requires a stopPrice or trailingDelta param for a ' + type + ' order');
6105
+ if (trailingDelta === undefined && stopPrice === undefined && trailingPercent === undefined) {
6106
+ throw new InvalidOrder(this.id + ' createOrder() requires a stopPrice, trailingDelta or trailingPercent param for a ' + type + ' order');
6083
6107
  }
6084
6108
  }
6085
6109
  if (stopPrice !== undefined) {
@@ -7663,7 +7687,7 @@ export default class binance extends Exchange {
7663
7687
  request['endTime'] = until;
7664
7688
  }
7665
7689
  const raw = await this.sapiGetFiatOrders(this.extend(request, params));
7666
- response = this.safeValue(raw, 'data');
7690
+ response = this.safeList(raw, 'data', []);
7667
7691
  // {
7668
7692
  // "code": "000000",
7669
7693
  // "message": "success",
@@ -7778,7 +7802,7 @@ export default class binance extends Exchange {
7778
7802
  request['beginTime'] = since;
7779
7803
  }
7780
7804
  const raw = await this.sapiGetFiatOrders(this.extend(request, params));
7781
- response = this.safeValue(raw, 'data');
7805
+ response = this.safeList(raw, 'data', []);
7782
7806
  // {
7783
7807
  // "code": "000000",
7784
7808
  // "message": "success",
@@ -7996,7 +8020,7 @@ export default class binance extends Exchange {
7996
8020
  if (txType !== undefined) {
7997
8021
  type = (txType === '0') ? 'deposit' : 'withdrawal';
7998
8022
  }
7999
- const legalMoneyCurrenciesById = this.safeValue(this.options, 'legalMoneyCurrenciesById');
8023
+ const legalMoneyCurrenciesById = this.safeDict(this.options, 'legalMoneyCurrenciesById');
8000
8024
  code = this.safeString(legalMoneyCurrenciesById, code, code);
8001
8025
  }
8002
8026
  const status = this.parseTransactionStatusByType(this.safeString(transaction, 'status'), type);
@@ -8350,7 +8374,7 @@ export default class binance extends Exchange {
8350
8374
  }
8351
8375
  }
8352
8376
  impliedNetwork = this.safeString(reverseNetworks, topLevel);
8353
- const impliedNetworks = this.safeValue(this.options, 'impliedNetworks', {
8377
+ const impliedNetworks = this.safeDict(this.options, 'impliedNetworks', {
8354
8378
  'ETH': { 'ERC20': 'ETH' },
8355
8379
  'TRX': { 'TRC20': 'TRX' },
8356
8380
  });
@@ -9659,7 +9683,7 @@ export default class binance extends Exchange {
9659
9683
  await this.loadMarkets();
9660
9684
  // by default cache the leverage bracket
9661
9685
  // it contains useful stuff like the maintenance margin and initial margin for positions
9662
- const leverageBrackets = this.safeValue(this.options, 'leverageBrackets');
9686
+ const leverageBrackets = this.safeDict(this.options, 'leverageBrackets', {});
9663
9687
  if ((leverageBrackets === undefined) || (reload)) {
9664
9688
  const defaultType = this.safeString(this.options, 'defaultType', 'future');
9665
9689
  const type = this.safeString(params, 'type', defaultType);
package/js/src/bybit.js CHANGED
@@ -1494,6 +1494,7 @@ export default class bybit extends Exchange {
1494
1494
  // "quoteCoin": "USDT",
1495
1495
  // "innovation": "0",
1496
1496
  // "status": "Trading",
1497
+ // "marginTrading": "both",
1497
1498
  // "lotSizeFilter": {
1498
1499
  // "basePrecision": "0.000001",
1499
1500
  // "quotePrecision": "0.00000001",
@@ -1530,7 +1531,9 @@ export default class bybit extends Exchange {
1530
1531
  const lotSizeFilter = this.safeDict(market, 'lotSizeFilter');
1531
1532
  const priceFilter = this.safeDict(market, 'priceFilter');
1532
1533
  const quotePrecision = this.safeNumber(lotSizeFilter, 'quotePrecision');
1533
- result.push({
1534
+ const marginTrading = this.safeString(market, 'marginTrading', 'none');
1535
+ const allowsMargin = marginTrading !== 'none';
1536
+ result.push(this.safeMarketStructure({
1534
1537
  'id': id,
1535
1538
  'symbol': symbol,
1536
1539
  'base': base,
@@ -1541,7 +1544,7 @@ export default class bybit extends Exchange {
1541
1544
  'settleId': undefined,
1542
1545
  'type': 'spot',
1543
1546
  'spot': true,
1544
- 'margin': undefined,
1547
+ 'margin': allowsMargin,
1545
1548
  'swap': false,
1546
1549
  'future': false,
1547
1550
  'option': false,
@@ -1580,7 +1583,7 @@ export default class bybit extends Exchange {
1580
1583
  },
1581
1584
  'created': undefined,
1582
1585
  'info': market,
1583
- });
1586
+ }));
1584
1587
  }
1585
1588
  return result;
1586
1589
  }
@@ -1705,7 +1708,7 @@ export default class bybit extends Exchange {
1705
1708
  symbol = symbol + '-' + this.yymmdd(expiry);
1706
1709
  }
1707
1710
  const contractSize = inverse ? this.safeNumber2(lotSizeFilter, 'minTradingQty', 'minOrderQty') : this.parseNumber('1');
1708
- result.push({
1711
+ result.push(this.safeMarketStructure({
1709
1712
  'id': id,
1710
1713
  'symbol': symbol,
1711
1714
  'base': base,
@@ -1755,7 +1758,7 @@ export default class bybit extends Exchange {
1755
1758
  },
1756
1759
  'created': this.safeInteger(market, 'launchTime'),
1757
1760
  'info': market,
1758
- });
1761
+ }));
1759
1762
  }
1760
1763
  return result;
1761
1764
  }
@@ -1838,7 +1841,7 @@ export default class bybit extends Exchange {
1838
1841
  const optionLetter = this.safeString(splitId, 3);
1839
1842
  const isActive = (status === 'Trading');
1840
1843
  if (isActive || (this.options['loadAllOptions']) || (this.options['loadExpiredOptions'])) {
1841
- result.push({
1844
+ result.push(this.safeMarketStructure({
1842
1845
  'id': id,
1843
1846
  'symbol': base + '/' + quote + ':' + settle + '-' + this.yymmdd(expiry) + '-' + strike + '-' + optionLetter,
1844
1847
  'base': base,
@@ -1888,7 +1891,7 @@ export default class bybit extends Exchange {
1888
1891
  },
1889
1892
  'created': this.safeInteger(market, 'launchTime'),
1890
1893
  'info': market,
1891
- });
1894
+ }));
1892
1895
  }
1893
1896
  }
1894
1897
  return result;
package/js/src/htx.d.ts CHANGED
@@ -68,8 +68,8 @@ export default class htx extends Exchange {
68
68
  };
69
69
  fetchAccountIdByType(type: any, marginMode?: any, symbol?: any, params?: {}): Promise<any>;
70
70
  fetchCurrencies(params?: {}): Promise<Currencies>;
71
- networkIdToCode(networkId: any, currencyCode?: any): string;
72
- networkCodeToId(networkCode: any, currencyCode?: any): any;
71
+ networkIdToCode(networkId?: Str, currencyCode?: Str): string;
72
+ networkCodeToId(networkCode: string, currencyCode?: Str): any;
73
73
  fetchBalance(params?: {}): Promise<Balances>;
74
74
  fetchOrder(id: string, symbol?: Str, params?: {}): Promise<Order>;
75
75
  parseMarginBalanceHelper(balance: any, code: any, result: any): any;
package/js/src/htx.js CHANGED
@@ -3306,7 +3306,7 @@ export default class htx extends Exchange {
3306
3306
  }
3307
3307
  return result;
3308
3308
  }
3309
- networkIdToCode(networkId, currencyCode = undefined) {
3309
+ networkIdToCode(networkId = undefined, currencyCode = undefined) {
3310
3310
  // here network-id is provided as a pair of currency & chain (i.e. trc20usdt)
3311
3311
  const keys = Object.keys(this.options['networkNamesByChainIds']);
3312
3312
  const keysLength = keys.length;
package/js/src/kuna.d.ts CHANGED
@@ -21,7 +21,7 @@ export default class kuna extends Exchange {
21
21
  deposit: any;
22
22
  withdraw: any;
23
23
  fee: any;
24
- precision: any;
24
+ precision: string;
25
25
  limits: {
26
26
  amount: {
27
27
  min: any;
package/js/src/okx.js CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import Exchange from './abstract/okx.js';
9
- import { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, InsufficientFunds, InvalidNonce, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, BadSymbol, RateLimitExceeded, NetworkError, CancelPending, NotSupported, AccountNotEnabled, ContractUnavailable } from './base/errors.js';
9
+ import { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, DDoSProtection, PermissionDenied, InsufficientFunds, InvalidNonce, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, BadSymbol, RateLimitExceeded, NetworkError, CancelPending, NotSupported, AccountNotEnabled, ContractUnavailable } from './base/errors.js';
10
10
  import { Precise } from './base/Precise.js';
11
11
  import { TICK_SIZE } from './base/functions/number.js';
12
12
  import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
@@ -892,7 +892,24 @@ export default class okx extends Exchange {
892
892
  '60017': BadRequest,
893
893
  '60018': BadRequest,
894
894
  '60019': BadRequest,
895
+ '60020': ExchangeError,
896
+ '60021': AccountNotEnabled,
897
+ '60022': AuthenticationError,
898
+ '60023': DDoSProtection,
899
+ '60024': AuthenticationError,
900
+ '60025': ExchangeError,
901
+ '60026': AuthenticationError,
902
+ '60027': ArgumentsRequired,
903
+ '60028': NotSupported,
904
+ '60029': AccountNotEnabled,
905
+ '60030': AccountNotEnabled,
906
+ '60031': AuthenticationError,
907
+ '60032': AuthenticationError,
895
908
  '63999': ExchangeError,
909
+ '64000': BadRequest,
910
+ '64001': BadRequest,
911
+ '64002': BadRequest,
912
+ '64003': AccountNotEnabled,
896
913
  '70010': BadRequest,
897
914
  '70013': BadRequest,
898
915
  '70016': BadRequest, // Please specify your instrument settings for at least one instType.
@@ -685,6 +685,8 @@ export default class bitfinex2 extends bitfinex2Rest {
685
685
  const responseChecksum = this.safeInteger(message, 2);
686
686
  if (responseChecksum !== localChecksum) {
687
687
  const error = new InvalidNonce(this.id + ' invalid checksum');
688
+ delete client.subscriptions[messageHash];
689
+ delete this.orderbooks[symbol];
688
690
  client.reject(error, messageHash);
689
691
  }
690
692
  }
@@ -563,7 +563,10 @@ export default class bitget extends bitgetRest {
563
563
  const responseChecksum = this.safeInteger(rawOrderBook, 'checksum');
564
564
  if (calculatedChecksum !== responseChecksum) {
565
565
  const error = new InvalidNonce(this.id + ' invalid checksum');
566
+ delete client.subscriptions[messageHash];
567
+ delete this.orderbooks[symbol];
566
568
  client.reject(error, messageHash);
569
+ return;
567
570
  }
568
571
  }
569
572
  }
@@ -15,11 +15,11 @@ export default class bybit extends bybitRest {
15
15
  return this.deepExtend(super.describe(), {
16
16
  'has': {
17
17
  'ws': true,
18
- 'createOrderWs': false,
19
- 'editOrderWs': false,
18
+ 'createOrderWs': true,
19
+ 'editOrderWs': true,
20
20
  'fetchOpenOrdersWs': false,
21
21
  'fetchOrderWs': false,
22
- 'cancelOrderWs': false,
22
+ 'cancelOrderWs': true,
23
23
  'cancelOrdersWs': false,
24
24
  'cancelAllOrdersWs': false,
25
25
  'fetchTradesWs': false,
@@ -53,7 +53,7 @@ export default class bybit extends bybitRest {
53
53
  },
54
54
  'contract': 'wss://stream.{hostname}/v5/private',
55
55
  'usdc': 'wss://stream.{hostname}/trade/option/usdc/private/v1',
56
- 'trade': 'wss://stream-testnet.bybit.com/v5/trade',
56
+ 'trade': 'wss://stream.bybit.com/v5/trade',
57
57
  },
58
58
  },
59
59
  },
@@ -287,7 +287,9 @@ export default class bybit extends bybitRest {
287
287
  const url = this.urls['api']['ws']['private']['trade'];
288
288
  await this.authenticate(url);
289
289
  const requestId = this.requestId().toString();
290
- delete orderRequest['orderFilter'];
290
+ if ('orderFilter' in orderRequest) {
291
+ delete orderRequest['orderFilter'];
292
+ }
291
293
  const request = {
292
294
  'op': 'order.cancel',
293
295
  'reqId': requestId,
package/js/src/pro/htx.js CHANGED
@@ -435,6 +435,8 @@ export default class htx extends htxRest {
435
435
  }
436
436
  }
437
437
  catch (e) {
438
+ delete client.subscriptions[messageHash];
439
+ delete this.orderbooks[symbol];
438
440
  client.reject(e, messageHash);
439
441
  }
440
442
  }
@@ -220,6 +220,8 @@ export default class independentreserve extends independentreserveRest {
220
220
  const responseChecksum = this.safeInteger(orderBook, 'Crc32');
221
221
  if (calculatedChecksum !== responseChecksum) {
222
222
  const error = new InvalidNonce(this.id + ' invalid checksum');
223
+ delete client.subscriptions[messageHash];
224
+ delete this.orderbooks[symbol];
223
225
  client.reject(error, messageHash);
224
226
  }
225
227
  }
@@ -770,6 +770,8 @@ export default class kraken extends krakenRest {
770
770
  const localChecksum = this.crc32(payload, false);
771
771
  if (localChecksum !== c) {
772
772
  const error = new InvalidNonce(this.id + ' invalid checksum');
773
+ delete client.subscriptions[messageHash];
774
+ delete this.orderbooks[symbol];
773
775
  client.reject(error, messageHash);
774
776
  return;
775
777
  }
package/js/src/pro/okx.js CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import okxRest from '../okx.js';
9
- import { ArgumentsRequired, AuthenticationError, BadRequest, InvalidNonce } from '../base/errors.js';
9
+ import { ArgumentsRequired, BadRequest, ExchangeError, InvalidNonce, AuthenticationError } from '../base/errors.js';
10
10
  import { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide } from '../base/ws/Cache.js';
11
11
  import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
12
12
  // ---------------------------------------------------------------------------
@@ -453,10 +453,12 @@ export default class okx extends okxRest {
453
453
  /**
454
454
  * @method
455
455
  * @name okx#watchOrderBook
456
+ * @see https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-order-book-channel
456
457
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
457
458
  * @param {string} symbol unified symbol of the market to fetch the order book for
458
459
  * @param {int} [limit] the maximum amount of order book entries to return
459
460
  * @param {object} [params] extra parameters specific to the exchange API endpoint
461
+ * @param {string} [params.depth] okx order book depth, can be books, books5, books-l2-tbt, books50-l2-tbt, bbo-tbt
460
462
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
461
463
  */
462
464
  //
@@ -488,16 +490,18 @@ export default class okx extends okxRest {
488
490
  /**
489
491
  * @method
490
492
  * @name okx#watchOrderBookForSymbols
493
+ * @see https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-order-book-channel
491
494
  * @description watches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
492
495
  * @param {string[]} symbols unified array of symbols
493
496
  * @param {int} [limit] 1,5, 400, 50 (l2-tbt, vip4+) or 40000 (vip5+) the maximum amount of order book entries to return
494
497
  * @param {object} [params] extra parameters specific to the exchange API endpoint
498
+ * @param {string} [params.depth] okx order book depth, can be books, books5, books-l2-tbt, books50-l2-tbt, bbo-tbt
495
499
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
496
500
  */
497
501
  await this.loadMarkets();
498
502
  symbols = this.marketSymbols(symbols);
499
- const options = this.safeValue(this.options, 'watchOrderBook', {});
500
- let depth = this.safeString(options, 'depth', 'books');
503
+ let depth = undefined;
504
+ [depth, params] = this.handleOptionAndParams(params, 'watchOrderBook', 'depth', 'books');
501
505
  if (limit !== undefined) {
502
506
  if (limit === 1) {
503
507
  depth = 'bbo-tbt';
@@ -505,17 +509,17 @@ export default class okx extends okxRest {
505
509
  else if (limit > 1 && limit <= 5) {
506
510
  depth = 'books5';
507
511
  }
508
- else if (limit === 400) {
509
- depth = 'books';
510
- }
511
512
  else if (limit === 50) {
512
513
  depth = 'books50-l2-tbt'; // Make sure you have VIP4 and above
513
514
  }
514
- else if (limit === 4000) {
515
- depth = 'books-l2-tbt'; // Make sure you have VIP5 and above
515
+ else if (limit === 400) {
516
+ depth = 'books';
516
517
  }
517
518
  }
518
519
  if ((depth === 'books-l2-tbt') || (depth === 'books50-l2-tbt')) {
520
+ if (!this.checkRequiredCredentials(false)) {
521
+ throw new AuthenticationError(this.id + ' watchOrderBook/watchOrderBookForSymbols requires authentication for this depth. Add credentials or change the depth option to books or books5');
522
+ }
519
523
  await this.authenticate({ 'access': 'public' });
520
524
  }
521
525
  const topics = [];
@@ -579,6 +583,8 @@ export default class okx extends okxRest {
579
583
  const storedBids = orderbook['bids'];
580
584
  this.handleDeltas(storedAsks, asks);
581
585
  this.handleDeltas(storedBids, bids);
586
+ const marketId = this.safeString(message, 'instId');
587
+ const symbol = this.safeSymbol(marketId);
582
588
  const checksum = this.safeBool(this.options, 'checksum', true);
583
589
  if (checksum) {
584
590
  const asksLength = storedAsks.length;
@@ -599,6 +605,8 @@ export default class okx extends okxRest {
599
605
  const localChecksum = this.crc32(payload, true);
600
606
  if (responseChecksum !== localChecksum) {
601
607
  const error = new InvalidNonce(this.id + ' invalid checksum');
608
+ delete client.subscriptions[messageHash];
609
+ delete this.orderbooks[symbol];
602
610
  client.reject(error, messageHash);
603
611
  }
604
612
  }
@@ -693,10 +701,10 @@ export default class okx extends okxRest {
693
701
  // ]
694
702
  // }
695
703
  //
696
- const arg = this.safeValue(message, 'arg', {});
704
+ const arg = this.safeDict(message, 'arg', {});
697
705
  const channel = this.safeString(arg, 'channel');
698
706
  const action = this.safeString(message, 'action');
699
- const data = this.safeValue(message, 'data', []);
707
+ const data = this.safeList(message, 'data', []);
700
708
  const marketId = this.safeString(arg, 'instId');
701
709
  const market = this.safeMarket(marketId);
702
710
  const symbol = market['symbol'];
@@ -1526,29 +1534,21 @@ export default class okx extends okxRest {
1526
1534
  // { event: 'error', msg: "Illegal request: {"op":"subscribe","args":["spot/ticker:BTC-USDT"]}", code: "60012" }
1527
1535
  // { event: 'error", msg: "channel:ticker,instId:BTC-USDT doesn"t exist", code: "60018" }
1528
1536
  //
1529
- const errorCode = this.safeInteger(message, 'code');
1537
+ const errorCode = this.safeString(message, 'code');
1530
1538
  try {
1531
- if (errorCode) {
1539
+ if (errorCode && errorCode !== '0') {
1532
1540
  const feedback = this.id + ' ' + this.json(message);
1533
1541
  this.throwExactlyMatchedException(this.exceptions['exact'], errorCode, feedback);
1534
1542
  const messageString = this.safeValue(message, 'msg');
1535
1543
  if (messageString !== undefined) {
1536
1544
  this.throwBroadlyMatchedException(this.exceptions['broad'], messageString, feedback);
1537
1545
  }
1546
+ throw new ExchangeError(feedback);
1538
1547
  }
1539
1548
  }
1540
1549
  catch (e) {
1541
- if (e instanceof AuthenticationError) {
1542
- const messageHash = 'authenticated';
1543
- client.reject(e, messageHash);
1544
- if (messageHash in client.subscriptions) {
1545
- delete client.subscriptions[messageHash];
1546
- }
1547
- return false;
1548
- }
1549
- else {
1550
- client.reject(e);
1551
- }
1550
+ client.reject(e);
1551
+ return false;
1552
1552
  }
1553
1553
  return message;
1554
1554
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccxt",
3
- "version": "4.3.16",
3
+ "version": "4.3.18",
4
4
  "description": "A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges",
5
5
  "unpkg": "dist/ccxt.browser.js",
6
6
  "type": "module",