ccxt 4.3.62 → 4.3.64

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 (86) hide show
  1. package/README.md +3 -3
  2. package/dist/ccxt.browser.min.js +3 -3
  3. package/dist/cjs/ccxt.js +2 -1
  4. package/dist/cjs/src/ace.js +34 -15
  5. package/dist/cjs/src/alpaca.js +1 -0
  6. package/dist/cjs/src/base/Exchange.js +11 -4
  7. package/dist/cjs/src/base/errors.js +8 -1
  8. package/dist/cjs/src/binance.js +6 -9
  9. package/dist/cjs/src/bingx.js +554 -151
  10. package/dist/cjs/src/bitfinex.js +1 -1
  11. package/dist/cjs/src/bitfinex2.js +1 -1
  12. package/dist/cjs/src/cryptocom.js +18 -2
  13. package/dist/cjs/src/independentreserve.js +107 -0
  14. package/dist/cjs/src/kucoin.js +2 -0
  15. package/dist/cjs/src/mercado.js +5 -1
  16. package/dist/cjs/src/pro/binance.js +58 -34
  17. package/dist/cjs/src/pro/bitfinex2.js +6 -3
  18. package/dist/cjs/src/pro/bitget.js +4 -1
  19. package/dist/cjs/src/pro/bitmart.js +3 -3
  20. package/dist/cjs/src/pro/bitvavo.js +1 -1
  21. package/dist/cjs/src/pro/bybit.js +44 -18
  22. package/dist/cjs/src/pro/cryptocom.js +7 -1
  23. package/dist/cjs/src/pro/gate.js +7 -3
  24. package/dist/cjs/src/pro/gemini.js +4 -2
  25. package/dist/cjs/src/pro/htx.js +5 -1
  26. package/dist/cjs/src/pro/independentreserve.js +5 -3
  27. package/dist/cjs/src/pro/kraken.js +82 -4
  28. package/dist/cjs/src/pro/okx.js +3 -3
  29. package/dist/cjs/src/pro/onetrading.js +3 -2
  30. package/dist/cjs/src/pro/poloniexfutures.js +5 -1
  31. package/dist/cjs/src/pro/vertex.js +3 -2
  32. package/dist/cjs/src/pro/woo.js +2 -1
  33. package/dist/cjs/src/pro/woofipro.js +3 -2
  34. package/dist/cjs/src/woo.js +344 -81
  35. package/js/ccxt.d.ts +3 -3
  36. package/js/ccxt.js +3 -3
  37. package/js/src/abstract/cryptocom.d.ts +11 -0
  38. package/js/src/abstract/kucoin.d.ts +1 -0
  39. package/js/src/abstract/kucoinfutures.d.ts +1 -0
  40. package/js/src/abstract/woo.d.ts +3 -0
  41. package/js/src/ace.js +34 -15
  42. package/js/src/alpaca.js +1 -0
  43. package/js/src/base/Exchange.d.ts +1 -0
  44. package/js/src/base/Exchange.js +11 -4
  45. package/js/src/base/errorHierarchy.d.ts +3 -1
  46. package/js/src/base/errorHierarchy.js +3 -1
  47. package/js/src/base/errors.d.ts +5 -1
  48. package/js/src/base/errors.js +8 -2
  49. package/js/src/binance.js +6 -9
  50. package/js/src/bingx.d.ts +4 -1
  51. package/js/src/bingx.js +554 -151
  52. package/js/src/bitfinex.js +1 -1
  53. package/js/src/bitfinex2.js +1 -1
  54. package/js/src/coinbaseinternational.d.ts +1 -1
  55. package/js/src/cryptocom.js +18 -2
  56. package/js/src/independentreserve.d.ts +3 -1
  57. package/js/src/independentreserve.js +106 -0
  58. package/js/src/kucoin.js +2 -0
  59. package/js/src/mercado.js +5 -1
  60. package/js/src/pro/binance.d.ts +1 -0
  61. package/js/src/pro/binance.js +59 -35
  62. package/js/src/pro/bitfinex2.js +7 -4
  63. package/js/src/pro/bitget.js +5 -2
  64. package/js/src/pro/bitmart.js +3 -3
  65. package/js/src/pro/bitvavo.js +1 -1
  66. package/js/src/pro/bybit.d.ts +1 -0
  67. package/js/src/pro/bybit.js +44 -18
  68. package/js/src/pro/cryptocom.js +8 -2
  69. package/js/src/pro/gate.js +8 -4
  70. package/js/src/pro/gemini.js +4 -2
  71. package/js/src/pro/htx.js +6 -2
  72. package/js/src/pro/independentreserve.js +6 -4
  73. package/js/src/pro/kraken.d.ts +3 -1
  74. package/js/src/pro/kraken.js +83 -5
  75. package/js/src/pro/okx.js +4 -4
  76. package/js/src/pro/onetrading.js +3 -2
  77. package/js/src/pro/poloniexfutures.js +6 -2
  78. package/js/src/pro/vertex.js +3 -2
  79. package/js/src/pro/woo.js +2 -1
  80. package/js/src/pro/woofipro.js +3 -2
  81. package/js/src/whitebit.d.ts +1 -1
  82. package/js/src/woo.d.ts +6 -2
  83. package/js/src/woo.js +344 -81
  84. package/js/src/xt.d.ts +3 -3
  85. package/js/src/zonda.d.ts +1 -1
  86. package/package.json +1 -1
@@ -1638,7 +1638,7 @@ class bitfinex extends bitfinex$1 {
1638
1638
  // ]
1639
1639
  //
1640
1640
  const response = this.safeValue(responses, 0, {});
1641
- const id = this.safeNumber(response, 'withdrawal_id');
1641
+ const id = this.safeInteger(response, 'withdrawal_id');
1642
1642
  const message = this.safeString(response, 'message');
1643
1643
  const errorMessage = this.findBroadlyMatchedKey(this.exceptions['broad'], message);
1644
1644
  if (id === 0) {
@@ -2357,7 +2357,7 @@ class bitfinex2 extends bitfinex2$1 {
2357
2357
  feeCost = Precise["default"].stringAbs(feeCost);
2358
2358
  }
2359
2359
  amount = this.safeNumber(data, 5);
2360
- id = this.safeString(data, 0);
2360
+ id = this.safeInteger(data, 0);
2361
2361
  status = 'ok';
2362
2362
  if (id === 0) {
2363
2363
  id = undefined;
@@ -161,6 +161,9 @@ class cryptocom extends cryptocom$1 {
161
161
  'public/get-expired-settlement-price': 10 / 3,
162
162
  'public/get-insurance': 1,
163
163
  },
164
+ 'post': {
165
+ 'public/staking/get-conversion-rate': 2,
166
+ },
164
167
  },
165
168
  'private': {
166
169
  'post': {
@@ -190,6 +193,16 @@ class cryptocom extends cryptocom$1 {
190
193
  'private/get-accounts': 10 / 3,
191
194
  'private/get-withdrawal-history': 10 / 3,
192
195
  'private/get-deposit-history': 10 / 3,
196
+ 'private/staking/stake': 2,
197
+ 'private/staking/unstake': 2,
198
+ 'private/staking/get-staking-position': 2,
199
+ 'private/staking/get-staking-instruments': 2,
200
+ 'private/staking/get-open-stake': 2,
201
+ 'private/staking/get-stake-history': 2,
202
+ 'private/staking/get-reward-history': 2,
203
+ 'private/staking/convert': 2,
204
+ 'private/staking/get-open-convert': 2,
205
+ 'private/staking/get-convert-history': 2,
193
206
  },
194
207
  },
195
208
  },
@@ -815,6 +828,9 @@ class cryptocom extends cryptocom$1 {
815
828
  'timeframe': this.safeString(this.timeframes, timeframe, timeframe),
816
829
  };
817
830
  if (limit !== undefined) {
831
+ if (limit > 300) {
832
+ limit = 300;
833
+ }
818
834
  request['count'] = limit;
819
835
  }
820
836
  const now = this.microseconds();
@@ -822,9 +838,9 @@ class cryptocom extends cryptocom$1 {
822
838
  const until = this.safeInteger(params, 'until', now);
823
839
  params = this.omit(params, ['until']);
824
840
  if (since !== undefined) {
825
- request['start_ts'] = since;
841
+ request['start_ts'] = since - duration * 1000;
826
842
  if (limit !== undefined) {
827
- request['end_ts'] = this.sum(since, duration * (limit + 1) * 1000) - 1;
843
+ request['end_ts'] = this.sum(since, duration * limit * 1000);
828
844
  }
829
845
  else {
830
846
  request['end_ts'] = until;
@@ -4,6 +4,8 @@ var independentreserve$1 = require('./abstract/independentreserve.js');
4
4
  var Precise = require('./base/Precise.js');
5
5
  var number = require('./base/functions/number.js');
6
6
  var sha256 = require('./static_dependencies/noble-hashes/sha256.js');
7
+ require('../ccxt.js');
8
+ var errors = require('./base/errors.js');
7
9
 
8
10
  // ---------------------------------------------------------------------------
9
11
  // ---------------------------------------------------------------------------
@@ -77,6 +79,7 @@ class independentreserve extends independentreserve$1 {
77
79
  'setLeverage': false,
78
80
  'setMarginMode': false,
79
81
  'setPositionMode': false,
82
+ 'withdraw': true,
80
83
  },
81
84
  'urls': {
82
85
  'logo': 'https://user-images.githubusercontent.com/51840849/87182090-1e9e9080-c2ec-11ea-8e49-563db9a38f37.jpg',
@@ -803,6 +806,110 @@ class independentreserve extends independentreserve$1 {
803
806
  'network': undefined,
804
807
  };
805
808
  }
809
+ async withdraw(code, amount, address, tag = undefined, params = {}) {
810
+ /**
811
+ * @method
812
+ * @name independentreserve#withdraw
813
+ * @description make a withdrawal
814
+ * @see https://www.independentreserve.com/features/api#WithdrawDigitalCurrency
815
+ * @param {string} code unified currency code
816
+ * @param {float} amount the amount to withdraw
817
+ * @param {string} address the address to withdraw to
818
+ * @param {string} tag
819
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
820
+ *
821
+ * EXCHANGE SPECIFIC PARAMETERS
822
+ * @param {object} [params.comment] withdrawal comment, should not exceed 500 characters
823
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
824
+ */
825
+ [tag, params] = this.handleWithdrawTagAndParams(tag, params);
826
+ await this.loadMarkets();
827
+ const currency = this.currency(code);
828
+ const request = {
829
+ 'primaryCurrencyCode': currency['id'],
830
+ 'withdrawalAddress': address,
831
+ 'amount': this.currencyToPrecision(code, amount),
832
+ };
833
+ if (tag !== undefined) {
834
+ request['destinationTag'] = tag;
835
+ }
836
+ let networkCode = undefined;
837
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
838
+ if (networkCode !== undefined) {
839
+ throw new errors.BadRequest(this.id + ' withdraw () does not accept params["networkCode"]');
840
+ }
841
+ const response = await this.privatePostWithdrawDigitalCurrency(this.extend(request, params));
842
+ //
843
+ // {
844
+ // "TransactionGuid": "dc932e19-562b-4c50-821e-a73fd048b93b",
845
+ // "PrimaryCurrencyCode": "Bch",
846
+ // "CreatedTimestampUtc": "2020-04-01T05:26:30.5093622+00:00",
847
+ // "Amount": {
848
+ // "Total": 0.1231,
849
+ // "Fee": 0.0001
850
+ // },
851
+ // "Destination": {
852
+ // "Address": "bc1qhpqxkjpvgkckw530yfmxyr53c94q8f4273a7ez",
853
+ // "Tag": null
854
+ // },
855
+ // "Status": "Pending",
856
+ // "Transaction": null
857
+ // }
858
+ //
859
+ return this.parseTransaction(response, currency);
860
+ }
861
+ parseTransaction(transaction, currency = undefined) {
862
+ //
863
+ // {
864
+ // "TransactionGuid": "dc932e19-562b-4c50-821e-a73fd048b93b",
865
+ // "PrimaryCurrencyCode": "Bch",
866
+ // "CreatedTimestampUtc": "2020-04-01T05:26:30.5093622+00:00",
867
+ // "Amount": {
868
+ // "Total": 0.1231,
869
+ // "Fee": 0.0001
870
+ // },
871
+ // "Destination": {
872
+ // "Address": "bc1qhpqxkjpvgkckw530yfmxyr53c94q8f4273a7ez",
873
+ // "Tag": null
874
+ // },
875
+ // "Status": "Pending",
876
+ // "Transaction": null
877
+ // }
878
+ //
879
+ const amount = this.safeDict(transaction, 'Amount');
880
+ const destination = this.safeDict(transaction, 'Destination');
881
+ const currencyId = this.safeString(transaction, 'PrimaryCurrencyCode');
882
+ const datetime = this.safeString(transaction, 'CreatedTimestampUtc');
883
+ const address = this.safeString(destination, 'Address');
884
+ const tag = this.safeString(destination, 'Tag');
885
+ const code = this.safeCurrencyCode(currencyId, currency);
886
+ return {
887
+ 'info': transaction,
888
+ 'id': this.safeString(transaction, 'TransactionGuid'),
889
+ 'txid': undefined,
890
+ 'type': 'withdraw',
891
+ 'currency': code,
892
+ 'network': undefined,
893
+ 'amount': this.safeNumber(amount, 'Total'),
894
+ 'status': this.safeString(transaction, 'Status'),
895
+ 'timestamp': this.parse8601(datetime),
896
+ 'datetime': datetime,
897
+ 'address': address,
898
+ 'addressFrom': undefined,
899
+ 'addressTo': address,
900
+ 'tag': tag,
901
+ 'tagFrom': undefined,
902
+ 'tagTo': tag,
903
+ 'updated': undefined,
904
+ 'comment': undefined,
905
+ 'fee': {
906
+ 'currency': code,
907
+ 'cost': this.safeNumber(amount, 'Fee'),
908
+ 'rate': undefined,
909
+ },
910
+ 'internal': false,
911
+ };
912
+ }
806
913
  sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
807
914
  let url = this.urls['api'][api] + '/' + path;
808
915
  if (api === 'public') {
@@ -159,6 +159,7 @@ class kucoin extends kucoin$1 {
159
159
  'status': 4.5,
160
160
  // margin trading
161
161
  'mark-price/{symbol}/current': 3,
162
+ 'mark-price/all-symbols': 3,
162
163
  'margin/config': 25, // 25SW
163
164
  },
164
165
  'post': {
@@ -644,6 +645,7 @@ class kucoin extends kucoin$1 {
644
645
  'currencies': 'v3',
645
646
  'currencies/{currency}': 'v3',
646
647
  'symbols': 'v2',
648
+ 'mark-price/all-symbols': 'v3',
647
649
  },
648
650
  },
649
651
  'private': {
@@ -4,6 +4,7 @@ var mercado$1 = require('./abstract/mercado.js');
4
4
  var errors = require('./base/errors.js');
5
5
  var number = require('./base/functions/number.js');
6
6
  var sha512 = require('./static_dependencies/noble-hashes/sha512.js');
7
+ var Precise = require('./base/Precise.js');
7
8
 
8
9
  // ---------------------------------------------------------------------------
9
10
  // ---------------------------------------------------------------------------
@@ -460,7 +461,10 @@ class mercado extends mercado$1 {
460
461
  if (price === undefined) {
461
462
  throw new errors.InvalidOrder(this.id + ' createOrder() requires the price argument with market buy orders to calculate total order cost (amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount');
462
463
  }
463
- request['cost'] = this.priceToPrecision(market['symbol'], amount * price);
464
+ const amountString = this.numberToString(amount);
465
+ const priceString = this.numberToString(price);
466
+ const cost = this.parseToNumeric(Precise["default"].stringMul(amountString, priceString));
467
+ request['cost'] = this.priceToPrecision(market['symbol'], cost);
464
468
  }
465
469
  else {
466
470
  request['quantity'] = this.amountToPrecision(market['symbol'], amount);
@@ -24,7 +24,7 @@ class binance extends binance$1 {
24
24
  'watchBidsAsks': true,
25
25
  'watchMyTrades': true,
26
26
  'watchOHLCV': true,
27
- 'watchOHLCVForSymbols': false,
27
+ 'watchOHLCVForSymbols': true,
28
28
  'watchOrderBook': true,
29
29
  'watchOrderBookForSymbols': true,
30
30
  'watchOrders': true,
@@ -127,6 +127,7 @@ class binance extends binance$1 {
127
127
  },
128
128
  'watchOrderBook': {
129
129
  'maxRetries': 3,
130
+ 'checksum': true,
130
131
  },
131
132
  'watchBalance': {
132
133
  'fetchBalanceSnapshot': false,
@@ -854,10 +855,10 @@ class binance extends binance$1 {
854
855
  }
855
856
  }
856
857
  else {
857
- const checksum = this.safeBool(this.options, 'checksum', true);
858
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
858
859
  if (checksum) {
859
860
  // todo: client.reject from handleOrderBookMessage properly
860
- throw new errors.InvalidNonce(this.id + ' handleOrderBook received an out-of-order nonce');
861
+ throw new errors.ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
861
862
  }
862
863
  }
863
864
  }
@@ -875,10 +876,10 @@ class binance extends binance$1 {
875
876
  }
876
877
  }
877
878
  else {
878
- const checksum = this.safeBool(this.options, 'checksum', true);
879
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
879
880
  if (checksum) {
880
881
  // todo: client.reject from handleOrderBookMessage properly
881
- throw new errors.InvalidNonce(this.id + ' handleOrderBook received an out-of-order nonce');
882
+ throw new errors.ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
882
883
  }
883
884
  }
884
885
  }
@@ -1188,40 +1189,63 @@ class binance extends binance$1 {
1188
1189
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1189
1190
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1190
1191
  */
1192
+ params['callerMethodName'] = 'watchOHLCV';
1193
+ const result = await this.watchOHLCVForSymbols([[symbol, timeframe]], since, limit, params);
1194
+ return result[symbol][timeframe];
1195
+ }
1196
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
1197
+ /**
1198
+ * @method
1199
+ * @name binance#watchOHLCVForSymbols
1200
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1201
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
1202
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
1203
+ * @param {int} [limit] the maximum amount of candles to fetch
1204
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1205
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1206
+ */
1191
1207
  await this.loadMarkets();
1192
- const market = this.market(symbol);
1193
- let marketId = market['lowercaseId'];
1194
- const interval = this.safeString(this.timeframes, timeframe, timeframe);
1195
- const options = this.safeValue(this.options, 'watchOHLCV', {});
1196
- const nameOption = this.safeString(options, 'name', 'kline');
1197
- const name = this.safeString(params, 'name', nameOption);
1198
- if (name === 'indexPriceKline') {
1199
- marketId = marketId.replace('_perp', '');
1200
- // weird behavior for index price kline we can't use the perp suffix
1201
- }
1202
- params = this.omit(params, 'name');
1203
- const messageHash = marketId + '@' + name + '_' + interval;
1204
- let type = market['type'];
1205
- if (market['contract']) {
1206
- type = market['linear'] ? 'future' : 'delivery';
1207
- }
1208
- const url = this.urls['api']['ws'][type] + '/' + this.stream(type, messageHash);
1208
+ let klineType = undefined;
1209
+ [klineType, params] = this.handleParamString2(params, 'channel', 'name', 'kline');
1210
+ const symbols = this.getListFromObjectValues(symbolsAndTimeframes, 0);
1211
+ const marketSymbols = this.marketSymbols(symbols, undefined, false, false, true);
1212
+ const firstMarket = this.market(marketSymbols[0]);
1213
+ let type = firstMarket['type'];
1214
+ if (firstMarket['contract']) {
1215
+ type = firstMarket['linear'] ? 'future' : 'delivery';
1216
+ }
1217
+ const rawHashes = [];
1218
+ const messageHashes = [];
1219
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
1220
+ const symAndTf = symbolsAndTimeframes[i];
1221
+ const symbolString = symAndTf[0];
1222
+ const timeframeString = symAndTf[1];
1223
+ const interval = this.safeString(this.timeframes, timeframeString, timeframeString);
1224
+ const market = this.market(symbolString);
1225
+ let marketId = market['lowercaseId'];
1226
+ if (klineType === 'indexPriceKline') {
1227
+ // weird behavior for index price kline we can't use the perp suffix
1228
+ marketId = marketId.replace('_perp', '');
1229
+ }
1230
+ rawHashes.push(marketId + '@' + klineType + '_' + interval);
1231
+ messageHashes.push('ohlcv::' + symbolString + '::' + timeframeString);
1232
+ }
1233
+ const url = this.urls['api']['ws'][type] + '/' + this.stream(type, 'multipleOHLCV');
1209
1234
  const requestId = this.requestId(url);
1210
1235
  const request = {
1211
1236
  'method': 'SUBSCRIBE',
1212
- 'params': [
1213
- messageHash,
1214
- ],
1237
+ 'params': rawHashes,
1215
1238
  'id': requestId,
1216
1239
  };
1217
1240
  const subscribe = {
1218
1241
  'id': requestId,
1219
1242
  };
1220
- const ohlcv = await this.watch(url, messageHash, this.extend(request, params), messageHash, subscribe);
1243
+ const [symbol, timeframe, candles] = await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes, subscribe);
1221
1244
  if (this.newUpdates) {
1222
- limit = ohlcv.getLimit(symbol, limit);
1245
+ limit = candles.getLimit(symbol, limit);
1223
1246
  }
1224
- return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
1247
+ const filtered = this.filterBySinceLimit(candles, since, limit, 0, true);
1248
+ return this.createOHLCVObject(symbol, timeframe, filtered);
1225
1249
  }
1226
1250
  handleOHLCV(client, message) {
1227
1251
  //
@@ -1262,11 +1286,9 @@ class binance extends binance$1 {
1262
1286
  // indexPriceKline doesn't have the _PERP suffix
1263
1287
  marketId = this.safeString(message, 'ps');
1264
1288
  }
1265
- const lowercaseMarketId = marketId.toLowerCase();
1266
1289
  const interval = this.safeString(kline, 'i');
1267
1290
  // use a reverse lookup in a static map instead
1268
- const timeframe = this.findTimeframe(interval);
1269
- const messageHash = lowercaseMarketId + '@' + event + '_' + interval;
1291
+ const unifiedTimeframe = this.findTimeframe(interval);
1270
1292
  const parsed = [
1271
1293
  this.safeInteger(kline, 't'),
1272
1294
  this.safeFloat(kline, 'o'),
@@ -1278,15 +1300,17 @@ class binance extends binance$1 {
1278
1300
  const isSpot = ((client.url.indexOf('/stream') > -1) || (client.url.indexOf('/testnet.binance') > -1));
1279
1301
  const marketType = (isSpot) ? 'spot' : 'contract';
1280
1302
  const symbol = this.safeSymbol(marketId, undefined, undefined, marketType);
1303
+ const messageHash = 'ohlcv::' + symbol + '::' + unifiedTimeframe;
1281
1304
  this.ohlcvs[symbol] = this.safeValue(this.ohlcvs, symbol, {});
1282
- let stored = this.safeValue(this.ohlcvs[symbol], timeframe);
1305
+ let stored = this.safeValue(this.ohlcvs[symbol], unifiedTimeframe);
1283
1306
  if (stored === undefined) {
1284
1307
  const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
1285
1308
  stored = new Cache.ArrayCacheByTimestamp(limit);
1286
- this.ohlcvs[symbol][timeframe] = stored;
1309
+ this.ohlcvs[symbol][unifiedTimeframe] = stored;
1287
1310
  }
1288
1311
  stored.append(parsed);
1289
- client.resolve(stored, messageHash);
1312
+ const resolveData = [symbol, unifiedTimeframe, stored];
1313
+ client.resolve(resolveData, messageHash);
1290
1314
  }
1291
1315
  async fetchTickerWs(symbol, params = {}) {
1292
1316
  /**
@@ -34,9 +34,9 @@ class bitfinex2 extends bitfinex2$1 {
34
34
  'watchOrderBook': {
35
35
  'prec': 'P0',
36
36
  'freq': 'F0',
37
+ 'checksum': true,
37
38
  },
38
39
  'ordersLimit': 1000,
39
- 'checksum': true,
40
40
  },
41
41
  });
42
42
  }
@@ -681,10 +681,13 @@ class bitfinex2 extends bitfinex2$1 {
681
681
  const localChecksum = this.crc32(payload, true);
682
682
  const responseChecksum = this.safeInteger(message, 2);
683
683
  if (responseChecksum !== localChecksum) {
684
- const error = new errors.InvalidNonce(this.id + ' invalid checksum');
685
684
  delete client.subscriptions[messageHash];
686
685
  delete this.orderbooks[symbol];
687
- client.reject(error, messageHash);
686
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
687
+ if (checksum) {
688
+ const error = new errors.ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
689
+ client.reject(error, messageHash);
690
+ }
688
691
  }
689
692
  }
690
693
  async watchBalance(params = {}) {
@@ -62,6 +62,9 @@ class bitget extends bitget$1 {
62
62
  '1d': '1D',
63
63
  '1w': '1W',
64
64
  },
65
+ 'watchOrderBook': {
66
+ 'checksum': true,
67
+ },
65
68
  },
66
69
  'streaming': {
67
70
  'ping': this.ping,
@@ -559,9 +562,9 @@ class bitget extends bitget$1 {
559
562
  const calculatedChecksum = this.crc32(payload, true);
560
563
  const responseChecksum = this.safeInteger(rawOrderBook, 'checksum');
561
564
  if (calculatedChecksum !== responseChecksum) {
562
- const error = new errors.InvalidNonce(this.id + ' invalid checksum');
563
565
  delete client.subscriptions[messageHash];
564
566
  delete this.orderbooks[symbol];
567
+ const error = new errors.ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
565
568
  client.reject(error, messageHash);
566
569
  return;
567
570
  }
@@ -754,8 +754,8 @@ class bitmart extends bitmart$1 {
754
754
  const symbol = market['symbol'];
755
755
  const openTimestamp = this.safeInteger(position, 'create_time');
756
756
  const timestamp = this.safeInteger(position, 'update_time');
757
- const side = this.safeNumber(position, 'position_type');
758
- const marginModeId = this.safeNumber(position, 'open_type');
757
+ const side = this.safeInteger(position, 'position_type');
758
+ const marginModeId = this.safeInteger(position, 'open_type');
759
759
  return this.safePosition({
760
760
  'info': position,
761
761
  'id': undefined,
@@ -1319,7 +1319,7 @@ class bitmart extends bitmart$1 {
1319
1319
  this.orderbooks[symbol] = ob;
1320
1320
  }
1321
1321
  const orderbook = this.orderbooks[symbol];
1322
- const way = this.safeNumber(data, 'way');
1322
+ const way = this.safeInteger(data, 'way');
1323
1323
  const side = (way === 1) ? 'bids' : 'asks';
1324
1324
  if (way === 1) {
1325
1325
  orderbook[side] = new OrderBookSide.Bids([], limit);
@@ -500,7 +500,7 @@ class bitvavo extends bitvavo$1 {
500
500
  * @param {int} [since] the earliest time in ms to fetch trades for
501
501
  * @param {int} [limit] the maximum number of trade structures to retrieve
502
502
  * @param {object} [params] extra parameters specific to the exchange API endpoint
503
- * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=ortradeder-structure
503
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
504
504
  */
505
505
  if (symbol === undefined) {
506
506
  throw new errors.ArgumentsRequired(this.id + ' watchMyTrades() requires a symbol argument');
@@ -28,7 +28,7 @@ class bybit extends bybit$1 {
28
28
  'watchMyLiquidationsForSymbols': false,
29
29
  'watchMyTrades': true,
30
30
  'watchOHLCV': true,
31
- 'watchOHLCVForSymbols': false,
31
+ 'watchOHLCVForSymbols': true,
32
32
  'watchOrderBook': true,
33
33
  'watchOrderBookForSymbols': true,
34
34
  'watchOrders': true,
@@ -530,20 +530,46 @@ class bybit extends bybit$1 {
530
530
  * @param {object} [params] extra parameters specific to the exchange API endpoint
531
531
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
532
532
  */
533
+ params['callerMethodName'] = 'watchOHLCV';
534
+ const result = await this.watchOHLCVForSymbols([[symbol, timeframe]], since, limit, params);
535
+ return result[symbol][timeframe];
536
+ }
537
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
538
+ /**
539
+ * @method
540
+ * @name bybit#watchOHLCVForSymbols
541
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
542
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/kline
543
+ * @see https://bybit-exchange.github.io/docs/v5/websocket/public/etp-kline
544
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
545
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
546
+ * @param {int} [limit] the maximum amount of candles to fetch
547
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
548
+ * @returns {object} A list of candles ordered as timestamp, open, high, low, close, volume
549
+ */
533
550
  await this.loadMarkets();
534
- const market = this.market(symbol);
535
- symbol = market['symbol'];
536
- const url = await this.getUrlByMarketType(symbol, false, 'watchOHLCV', params);
537
- params = this.cleanParams(params);
538
- let ohlcv = undefined;
539
- const timeframeId = this.safeString(this.timeframes, timeframe, timeframe);
540
- const topics = ['kline.' + timeframeId + '.' + market['id']];
541
- const messageHash = 'kline' + ':' + timeframeId + ':' + symbol;
542
- ohlcv = await this.watchTopics(url, [messageHash], topics, params);
551
+ const symbols = this.getListFromObjectValues(symbolsAndTimeframes, 0);
552
+ const marketSymbols = this.marketSymbols(symbols, undefined, false, true, true);
553
+ const firstSymbol = marketSymbols[0];
554
+ const url = await this.getUrlByMarketType(firstSymbol, false, 'watchOHLCVForSymbols', params);
555
+ const rawHashes = [];
556
+ const messageHashes = [];
557
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
558
+ const data = symbolsAndTimeframes[i];
559
+ let symbolString = this.safeString(data, 0);
560
+ const market = this.market(symbolString);
561
+ symbolString = market['symbol'];
562
+ const unfiedTimeframe = this.safeString(data, 1);
563
+ const timeframeId = this.safeString(this.timeframes, unfiedTimeframe, unfiedTimeframe);
564
+ rawHashes.push('kline.' + timeframeId + '.' + market['id']);
565
+ messageHashes.push('ohlcv::' + symbolString + '::' + unfiedTimeframe);
566
+ }
567
+ const [symbol, timeframe, stored] = await this.watchTopics(url, messageHashes, rawHashes, params);
543
568
  if (this.newUpdates) {
544
- limit = ohlcv.getLimit(symbol, limit);
569
+ limit = stored.getLimit(symbol, limit);
545
570
  }
546
- return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
571
+ const filtered = this.filterBySinceLimit(stored, since, limit, 0, true);
572
+ return this.createOHLCVObject(symbol, timeframe, filtered);
547
573
  }
548
574
  handleOHLCV(client, message) {
549
575
  //
@@ -583,18 +609,18 @@ class bybit extends bybit$1 {
583
609
  if (ohlcvsByTimeframe === undefined) {
584
610
  this.ohlcvs[symbol] = {};
585
611
  }
586
- let stored = this.safeValue(ohlcvsByTimeframe, timeframe);
587
- if (stored === undefined) {
612
+ if (this.safeValue(ohlcvsByTimeframe, timeframe) === undefined) {
588
613
  const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
589
- stored = new Cache.ArrayCacheByTimestamp(limit);
590
- this.ohlcvs[symbol][timeframe] = stored;
614
+ this.ohlcvs[symbol][timeframe] = new Cache.ArrayCacheByTimestamp(limit);
591
615
  }
616
+ const stored = this.ohlcvs[symbol][timeframe];
592
617
  for (let i = 0; i < data.length; i++) {
593
618
  const parsed = this.parseWsOHLCV(data[i]);
594
619
  stored.append(parsed);
595
620
  }
596
- const messageHash = 'kline' + ':' + timeframeId + ':' + symbol;
597
- client.resolve(stored, messageHash);
621
+ const messageHash = 'ohlcv::' + symbol + '::' + timeframe;
622
+ const resolveData = [symbol, timeframe, stored];
623
+ client.resolve(resolveData, messageHash);
598
624
  }
599
625
  parseWsOHLCV(ohlcv, market = undefined) {
600
626
  //
@@ -44,6 +44,9 @@ class cryptocom extends cryptocom$1 {
44
44
  'fetchPositionsSnapshot': true,
45
45
  'awaitPositionsSnapshot': true, // whether to wait for the positions snapshot before providing updates
46
46
  },
47
+ 'watchOrderBook': {
48
+ 'checksum': true,
49
+ },
47
50
  },
48
51
  'streaming': {},
49
52
  });
@@ -217,7 +220,10 @@ class cryptocom extends cryptocom$1 {
217
220
  const previousNonce = this.safeInteger(data, 'pu');
218
221
  const currentNonce = orderbook['nonce'];
219
222
  if (currentNonce !== previousNonce) {
220
- throw new errors.InvalidNonce(this.id + ' watchOrderBook() ' + symbol + ' ' + previousNonce + ' != ' + nonce);
223
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
224
+ if (checksum) {
225
+ throw new errors.ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
226
+ }
221
227
  }
222
228
  }
223
229
  this.handleDeltas(orderbook['asks'], this.safeValue(books, 'asks', []));
@@ -94,6 +94,7 @@ class gate extends gate$1 {
94
94
  'interval': '100ms',
95
95
  'snapshotDelay': 10,
96
96
  'snapshotMaxRetries': 3,
97
+ 'checksum': true,
97
98
  },
98
99
  'watchBalance': {
99
100
  'settle': 'usdt',
@@ -479,10 +480,13 @@ class gate extends gate$1 {
479
480
  this.handleDelta(storedOrderBook, delta);
480
481
  }
481
482
  else {
482
- const error = new errors.InvalidNonce(this.id + ' orderbook update has a nonce bigger than u');
483
483
  delete client.subscriptions[messageHash];
484
484
  delete this.orderbooks[symbol];
485
- client.reject(error, messageHash);
485
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
486
+ if (checksum) {
487
+ const error = new errors.ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
488
+ client.reject(error, messageHash);
489
+ }
486
490
  }
487
491
  client.resolve(storedOrderBook, messageHash);
488
492
  }
@@ -1282,7 +1286,7 @@ class gate extends gate$1 {
1282
1286
  else if (event === 'finish') {
1283
1287
  const status = this.safeString(parsed, 'status');
1284
1288
  if (status === undefined) {
1285
- const left = this.safeNumber(info, 'left');
1289
+ const left = this.safeInteger(info, 'left');
1286
1290
  parsed['status'] = (left === 0) ? 'closed' : 'canceled';
1287
1291
  }
1288
1292
  }