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
@@ -1641,7 +1641,7 @@ export default class bitfinex extends Exchange {
1641
1641
  // ]
1642
1642
  //
1643
1643
  const response = this.safeValue(responses, 0, {});
1644
- const id = this.safeNumber(response, 'withdrawal_id');
1644
+ const id = this.safeInteger(response, 'withdrawal_id');
1645
1645
  const message = this.safeString(response, 'message');
1646
1646
  const errorMessage = this.findBroadlyMatchedKey(this.exceptions['broad'], message);
1647
1647
  if (id === 0) {
@@ -2360,7 +2360,7 @@ export default class bitfinex2 extends Exchange {
2360
2360
  feeCost = Precise.stringAbs(feeCost);
2361
2361
  }
2362
2362
  amount = this.safeNumber(data, 5);
2363
- id = this.safeString(data, 0);
2363
+ id = this.safeInteger(data, 0);
2364
2364
  status = 'ok';
2365
2365
  if (id === 0) {
2366
2366
  id = undefined;
@@ -67,7 +67,7 @@ export default class coinbaseinternational extends Exchange {
67
67
  };
68
68
  };
69
69
  setMargin(symbol: string, amount: number, params?: {}): Promise<any>;
70
- fetchDepositsWithdrawals(code?: string, since?: Int, limit?: Int, params?: {}): Promise<Transaction[]>;
70
+ fetchDepositsWithdrawals(code?: Str, since?: Int, limit?: Int, params?: {}): Promise<Transaction[]>;
71
71
  fetchPosition(symbol: string, params?: {}): Promise<Position>;
72
72
  parsePosition(position: Dict, market?: Market): Position;
73
73
  fetchPositions(symbols?: Strings, params?: {}): Promise<Position[]>;
@@ -164,6 +164,9 @@ export default class cryptocom extends Exchange {
164
164
  'public/get-expired-settlement-price': 10 / 3,
165
165
  'public/get-insurance': 1,
166
166
  },
167
+ 'post': {
168
+ 'public/staking/get-conversion-rate': 2,
169
+ },
167
170
  },
168
171
  'private': {
169
172
  'post': {
@@ -193,6 +196,16 @@ export default class cryptocom extends Exchange {
193
196
  'private/get-accounts': 10 / 3,
194
197
  'private/get-withdrawal-history': 10 / 3,
195
198
  'private/get-deposit-history': 10 / 3,
199
+ 'private/staking/stake': 2,
200
+ 'private/staking/unstake': 2,
201
+ 'private/staking/get-staking-position': 2,
202
+ 'private/staking/get-staking-instruments': 2,
203
+ 'private/staking/get-open-stake': 2,
204
+ 'private/staking/get-stake-history': 2,
205
+ 'private/staking/get-reward-history': 2,
206
+ 'private/staking/convert': 2,
207
+ 'private/staking/get-open-convert': 2,
208
+ 'private/staking/get-convert-history': 2,
196
209
  },
197
210
  },
198
211
  },
@@ -818,6 +831,9 @@ export default class cryptocom extends Exchange {
818
831
  'timeframe': this.safeString(this.timeframes, timeframe, timeframe),
819
832
  };
820
833
  if (limit !== undefined) {
834
+ if (limit > 300) {
835
+ limit = 300;
836
+ }
821
837
  request['count'] = limit;
822
838
  }
823
839
  const now = this.microseconds();
@@ -825,9 +841,9 @@ export default class cryptocom extends Exchange {
825
841
  const until = this.safeInteger(params, 'until', now);
826
842
  params = this.omit(params, ['until']);
827
843
  if (since !== undefined) {
828
- request['start_ts'] = since;
844
+ request['start_ts'] = since - duration * 1000;
829
845
  if (limit !== undefined) {
830
- request['end_ts'] = this.sum(since, duration * (limit + 1) * 1000) - 1;
846
+ request['end_ts'] = this.sum(since, duration * limit * 1000);
831
847
  }
832
848
  else {
833
849
  request['end_ts'] = until;
@@ -1,5 +1,5 @@
1
1
  import Exchange from './abstract/independentreserve.js';
2
- import type { Balances, Currency, Dict, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Ticker, Trade, TradingFees } from './base/types.js';
2
+ import type { Balances, Currency, Dict, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Ticker, Trade, TradingFees, Transaction } from './base/types.js';
3
3
  /**
4
4
  * @class independentreserve
5
5
  * @augments Exchange
@@ -37,6 +37,8 @@ export default class independentreserve extends Exchange {
37
37
  tag: string;
38
38
  network: any;
39
39
  };
40
+ withdraw(code: string, amount: number, address: string, tag?: any, params?: {}): Promise<Transaction>;
41
+ parseTransaction(transaction: Dict, currency?: Currency): Transaction;
40
42
  sign(path: any, api?: string, method?: string, params?: {}, headers?: any, body?: any): {
41
43
  url: string;
42
44
  method: string;
@@ -9,6 +9,7 @@ import Exchange from './abstract/independentreserve.js';
9
9
  import { Precise } from './base/Precise.js';
10
10
  import { TICK_SIZE } from './base/functions/number.js';
11
11
  import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
12
+ import { BadRequest } from '../ccxt.js';
12
13
  // ---------------------------------------------------------------------------
13
14
  /**
14
15
  * @class independentreserve
@@ -80,6 +81,7 @@ export default class independentreserve extends Exchange {
80
81
  'setLeverage': false,
81
82
  'setMarginMode': false,
82
83
  'setPositionMode': false,
84
+ 'withdraw': true,
83
85
  },
84
86
  'urls': {
85
87
  'logo': 'https://user-images.githubusercontent.com/51840849/87182090-1e9e9080-c2ec-11ea-8e49-563db9a38f37.jpg',
@@ -806,6 +808,110 @@ export default class independentreserve extends Exchange {
806
808
  'network': undefined,
807
809
  };
808
810
  }
811
+ async withdraw(code, amount, address, tag = undefined, params = {}) {
812
+ /**
813
+ * @method
814
+ * @name independentreserve#withdraw
815
+ * @description make a withdrawal
816
+ * @see https://www.independentreserve.com/features/api#WithdrawDigitalCurrency
817
+ * @param {string} code unified currency code
818
+ * @param {float} amount the amount to withdraw
819
+ * @param {string} address the address to withdraw to
820
+ * @param {string} tag
821
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
822
+ *
823
+ * EXCHANGE SPECIFIC PARAMETERS
824
+ * @param {object} [params.comment] withdrawal comment, should not exceed 500 characters
825
+ * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/#/?id=transaction-structure}
826
+ */
827
+ [tag, params] = this.handleWithdrawTagAndParams(tag, params);
828
+ await this.loadMarkets();
829
+ const currency = this.currency(code);
830
+ const request = {
831
+ 'primaryCurrencyCode': currency['id'],
832
+ 'withdrawalAddress': address,
833
+ 'amount': this.currencyToPrecision(code, amount),
834
+ };
835
+ if (tag !== undefined) {
836
+ request['destinationTag'] = tag;
837
+ }
838
+ let networkCode = undefined;
839
+ [networkCode, params] = this.handleNetworkCodeAndParams(params);
840
+ if (networkCode !== undefined) {
841
+ throw new BadRequest(this.id + ' withdraw () does not accept params["networkCode"]');
842
+ }
843
+ const response = await this.privatePostWithdrawDigitalCurrency(this.extend(request, params));
844
+ //
845
+ // {
846
+ // "TransactionGuid": "dc932e19-562b-4c50-821e-a73fd048b93b",
847
+ // "PrimaryCurrencyCode": "Bch",
848
+ // "CreatedTimestampUtc": "2020-04-01T05:26:30.5093622+00:00",
849
+ // "Amount": {
850
+ // "Total": 0.1231,
851
+ // "Fee": 0.0001
852
+ // },
853
+ // "Destination": {
854
+ // "Address": "bc1qhpqxkjpvgkckw530yfmxyr53c94q8f4273a7ez",
855
+ // "Tag": null
856
+ // },
857
+ // "Status": "Pending",
858
+ // "Transaction": null
859
+ // }
860
+ //
861
+ return this.parseTransaction(response, currency);
862
+ }
863
+ parseTransaction(transaction, currency = undefined) {
864
+ //
865
+ // {
866
+ // "TransactionGuid": "dc932e19-562b-4c50-821e-a73fd048b93b",
867
+ // "PrimaryCurrencyCode": "Bch",
868
+ // "CreatedTimestampUtc": "2020-04-01T05:26:30.5093622+00:00",
869
+ // "Amount": {
870
+ // "Total": 0.1231,
871
+ // "Fee": 0.0001
872
+ // },
873
+ // "Destination": {
874
+ // "Address": "bc1qhpqxkjpvgkckw530yfmxyr53c94q8f4273a7ez",
875
+ // "Tag": null
876
+ // },
877
+ // "Status": "Pending",
878
+ // "Transaction": null
879
+ // }
880
+ //
881
+ const amount = this.safeDict(transaction, 'Amount');
882
+ const destination = this.safeDict(transaction, 'Destination');
883
+ const currencyId = this.safeString(transaction, 'PrimaryCurrencyCode');
884
+ const datetime = this.safeString(transaction, 'CreatedTimestampUtc');
885
+ const address = this.safeString(destination, 'Address');
886
+ const tag = this.safeString(destination, 'Tag');
887
+ const code = this.safeCurrencyCode(currencyId, currency);
888
+ return {
889
+ 'info': transaction,
890
+ 'id': this.safeString(transaction, 'TransactionGuid'),
891
+ 'txid': undefined,
892
+ 'type': 'withdraw',
893
+ 'currency': code,
894
+ 'network': undefined,
895
+ 'amount': this.safeNumber(amount, 'Total'),
896
+ 'status': this.safeString(transaction, 'Status'),
897
+ 'timestamp': this.parse8601(datetime),
898
+ 'datetime': datetime,
899
+ 'address': address,
900
+ 'addressFrom': undefined,
901
+ 'addressTo': address,
902
+ 'tag': tag,
903
+ 'tagFrom': undefined,
904
+ 'tagTo': tag,
905
+ 'updated': undefined,
906
+ 'comment': undefined,
907
+ 'fee': {
908
+ 'currency': code,
909
+ 'cost': this.safeNumber(amount, 'Fee'),
910
+ 'rate': undefined,
911
+ },
912
+ 'internal': false,
913
+ };
914
+ }
809
915
  sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
810
916
  let url = this.urls['api'][api] + '/' + path;
811
917
  if (api === 'public') {
package/js/src/kucoin.js CHANGED
@@ -162,6 +162,7 @@ export default class kucoin extends Exchange {
162
162
  'status': 4.5,
163
163
  // margin trading
164
164
  'mark-price/{symbol}/current': 3,
165
+ 'mark-price/all-symbols': 3,
165
166
  'margin/config': 25, // 25SW
166
167
  },
167
168
  'post': {
@@ -647,6 +648,7 @@ export default class kucoin extends Exchange {
647
648
  'currencies': 'v3',
648
649
  'currencies/{currency}': 'v3',
649
650
  'symbols': 'v2',
651
+ 'mark-price/all-symbols': 'v3',
650
652
  },
651
653
  },
652
654
  'private': {
package/js/src/mercado.js CHANGED
@@ -9,6 +9,7 @@ import Exchange from './abstract/mercado.js';
9
9
  import { ExchangeError, ArgumentsRequired, InvalidOrder } from './base/errors.js';
10
10
  import { TICK_SIZE } from './base/functions/number.js';
11
11
  import { sha512 } from './static_dependencies/noble-hashes/sha512.js';
12
+ import { Precise } from './base/Precise.js';
12
13
  // ---------------------------------------------------------------------------
13
14
  /**
14
15
  * @class mercado
@@ -463,7 +464,10 @@ export default class mercado extends Exchange {
463
464
  if (price === undefined) {
464
465
  throw new 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');
465
466
  }
466
- request['cost'] = this.priceToPrecision(market['symbol'], amount * price);
467
+ const amountString = this.numberToString(amount);
468
+ const priceString = this.numberToString(price);
469
+ const cost = this.parseToNumeric(Precise.stringMul(amountString, priceString));
470
+ request['cost'] = this.priceToPrecision(market['symbol'], cost);
467
471
  }
468
472
  else {
469
473
  request['quantity'] = this.amountToPrecision(market['symbol'], amount);
@@ -28,6 +28,7 @@ export default class binance extends binanceRest {
28
28
  parseWsTrade(trade: any, market?: any): Trade;
29
29
  handleTrade(client: Client, message: any): void;
30
30
  watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
31
+ watchOHLCVForSymbols(symbolsAndTimeframes: string[][], since?: Int, limit?: Int, params?: {}): Promise<import("../base/types.js").Dictionary<import("../base/types.js").Dictionary<OHLCV[]>>>;
31
32
  handleOHLCV(client: Client, message: any): void;
32
33
  fetchTickerWs(symbol: string, params?: {}): Promise<Ticker>;
33
34
  fetchOHLCVWs(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
@@ -7,7 +7,7 @@
7
7
  // ----------------------------------------------------------------------------
8
8
  import binanceRest from '../binance.js';
9
9
  import { Precise } from '../base/Precise.js';
10
- import { InvalidNonce, ArgumentsRequired, BadRequest, NotSupported } from '../base/errors.js';
10
+ import { ChecksumError, ArgumentsRequired, BadRequest, NotSupported } from '../base/errors.js';
11
11
  import { ArrayCache, ArrayCacheByTimestamp, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide } from '../base/ws/Cache.js';
12
12
  import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
13
13
  import { rsa } from '../base/functions/rsa.js';
@@ -27,7 +27,7 @@ export default class binance extends binanceRest {
27
27
  'watchBidsAsks': true,
28
28
  'watchMyTrades': true,
29
29
  'watchOHLCV': true,
30
- 'watchOHLCVForSymbols': false,
30
+ 'watchOHLCVForSymbols': true,
31
31
  'watchOrderBook': true,
32
32
  'watchOrderBookForSymbols': true,
33
33
  'watchOrders': true,
@@ -130,6 +130,7 @@ export default class binance extends binanceRest {
130
130
  },
131
131
  'watchOrderBook': {
132
132
  'maxRetries': 3,
133
+ 'checksum': true,
133
134
  },
134
135
  'watchBalance': {
135
136
  'fetchBalanceSnapshot': false,
@@ -857,10 +858,10 @@ export default class binance extends binanceRest {
857
858
  }
858
859
  }
859
860
  else {
860
- const checksum = this.safeBool(this.options, 'checksum', true);
861
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
861
862
  if (checksum) {
862
863
  // todo: client.reject from handleOrderBookMessage properly
863
- throw new InvalidNonce(this.id + ' handleOrderBook received an out-of-order nonce');
864
+ throw new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
864
865
  }
865
866
  }
866
867
  }
@@ -878,10 +879,10 @@ export default class binance extends binanceRest {
878
879
  }
879
880
  }
880
881
  else {
881
- const checksum = this.safeBool(this.options, 'checksum', true);
882
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
882
883
  if (checksum) {
883
884
  // todo: client.reject from handleOrderBookMessage properly
884
- throw new InvalidNonce(this.id + ' handleOrderBook received an out-of-order nonce');
885
+ throw new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
885
886
  }
886
887
  }
887
888
  }
@@ -1191,40 +1192,63 @@ export default class binance extends binanceRest {
1191
1192
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1192
1193
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1193
1194
  */
1195
+ params['callerMethodName'] = 'watchOHLCV';
1196
+ const result = await this.watchOHLCVForSymbols([[symbol, timeframe]], since, limit, params);
1197
+ return result[symbol][timeframe];
1198
+ }
1199
+ async watchOHLCVForSymbols(symbolsAndTimeframes, since = undefined, limit = undefined, params = {}) {
1200
+ /**
1201
+ * @method
1202
+ * @name binance#watchOHLCVForSymbols
1203
+ * @description watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
1204
+ * @param {string[][]} symbolsAndTimeframes array of arrays containing unified symbols and timeframes to fetch OHLCV data for, example [['BTC/USDT', '1m'], ['LTC/USDT', '5m']]
1205
+ * @param {int} [since] timestamp in ms of the earliest candle to fetch
1206
+ * @param {int} [limit] the maximum amount of candles to fetch
1207
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1208
+ * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
1209
+ */
1194
1210
  await this.loadMarkets();
1195
- const market = this.market(symbol);
1196
- let marketId = market['lowercaseId'];
1197
- const interval = this.safeString(this.timeframes, timeframe, timeframe);
1198
- const options = this.safeValue(this.options, 'watchOHLCV', {});
1199
- const nameOption = this.safeString(options, 'name', 'kline');
1200
- const name = this.safeString(params, 'name', nameOption);
1201
- if (name === 'indexPriceKline') {
1202
- marketId = marketId.replace('_perp', '');
1203
- // weird behavior for index price kline we can't use the perp suffix
1204
- }
1205
- params = this.omit(params, 'name');
1206
- const messageHash = marketId + '@' + name + '_' + interval;
1207
- let type = market['type'];
1208
- if (market['contract']) {
1209
- type = market['linear'] ? 'future' : 'delivery';
1210
- }
1211
- const url = this.urls['api']['ws'][type] + '/' + this.stream(type, messageHash);
1211
+ let klineType = undefined;
1212
+ [klineType, params] = this.handleParamString2(params, 'channel', 'name', 'kline');
1213
+ const symbols = this.getListFromObjectValues(symbolsAndTimeframes, 0);
1214
+ const marketSymbols = this.marketSymbols(symbols, undefined, false, false, true);
1215
+ const firstMarket = this.market(marketSymbols[0]);
1216
+ let type = firstMarket['type'];
1217
+ if (firstMarket['contract']) {
1218
+ type = firstMarket['linear'] ? 'future' : 'delivery';
1219
+ }
1220
+ const rawHashes = [];
1221
+ const messageHashes = [];
1222
+ for (let i = 0; i < symbolsAndTimeframes.length; i++) {
1223
+ const symAndTf = symbolsAndTimeframes[i];
1224
+ const symbolString = symAndTf[0];
1225
+ const timeframeString = symAndTf[1];
1226
+ const interval = this.safeString(this.timeframes, timeframeString, timeframeString);
1227
+ const market = this.market(symbolString);
1228
+ let marketId = market['lowercaseId'];
1229
+ if (klineType === 'indexPriceKline') {
1230
+ // weird behavior for index price kline we can't use the perp suffix
1231
+ marketId = marketId.replace('_perp', '');
1232
+ }
1233
+ rawHashes.push(marketId + '@' + klineType + '_' + interval);
1234
+ messageHashes.push('ohlcv::' + symbolString + '::' + timeframeString);
1235
+ }
1236
+ const url = this.urls['api']['ws'][type] + '/' + this.stream(type, 'multipleOHLCV');
1212
1237
  const requestId = this.requestId(url);
1213
1238
  const request = {
1214
1239
  'method': 'SUBSCRIBE',
1215
- 'params': [
1216
- messageHash,
1217
- ],
1240
+ 'params': rawHashes,
1218
1241
  'id': requestId,
1219
1242
  };
1220
1243
  const subscribe = {
1221
1244
  'id': requestId,
1222
1245
  };
1223
- const ohlcv = await this.watch(url, messageHash, this.extend(request, params), messageHash, subscribe);
1246
+ const [symbol, timeframe, candles] = await this.watchMultiple(url, messageHashes, this.extend(request, params), messageHashes, subscribe);
1224
1247
  if (this.newUpdates) {
1225
- limit = ohlcv.getLimit(symbol, limit);
1248
+ limit = candles.getLimit(symbol, limit);
1226
1249
  }
1227
- return this.filterBySinceLimit(ohlcv, since, limit, 0, true);
1250
+ const filtered = this.filterBySinceLimit(candles, since, limit, 0, true);
1251
+ return this.createOHLCVObject(symbol, timeframe, filtered);
1228
1252
  }
1229
1253
  handleOHLCV(client, message) {
1230
1254
  //
@@ -1265,11 +1289,9 @@ export default class binance extends binanceRest {
1265
1289
  // indexPriceKline doesn't have the _PERP suffix
1266
1290
  marketId = this.safeString(message, 'ps');
1267
1291
  }
1268
- const lowercaseMarketId = marketId.toLowerCase();
1269
1292
  const interval = this.safeString(kline, 'i');
1270
1293
  // use a reverse lookup in a static map instead
1271
- const timeframe = this.findTimeframe(interval);
1272
- const messageHash = lowercaseMarketId + '@' + event + '_' + interval;
1294
+ const unifiedTimeframe = this.findTimeframe(interval);
1273
1295
  const parsed = [
1274
1296
  this.safeInteger(kline, 't'),
1275
1297
  this.safeFloat(kline, 'o'),
@@ -1281,15 +1303,17 @@ export default class binance extends binanceRest {
1281
1303
  const isSpot = ((client.url.indexOf('/stream') > -1) || (client.url.indexOf('/testnet.binance') > -1));
1282
1304
  const marketType = (isSpot) ? 'spot' : 'contract';
1283
1305
  const symbol = this.safeSymbol(marketId, undefined, undefined, marketType);
1306
+ const messageHash = 'ohlcv::' + symbol + '::' + unifiedTimeframe;
1284
1307
  this.ohlcvs[symbol] = this.safeValue(this.ohlcvs, symbol, {});
1285
- let stored = this.safeValue(this.ohlcvs[symbol], timeframe);
1308
+ let stored = this.safeValue(this.ohlcvs[symbol], unifiedTimeframe);
1286
1309
  if (stored === undefined) {
1287
1310
  const limit = this.safeInteger(this.options, 'OHLCVLimit', 1000);
1288
1311
  stored = new ArrayCacheByTimestamp(limit);
1289
- this.ohlcvs[symbol][timeframe] = stored;
1312
+ this.ohlcvs[symbol][unifiedTimeframe] = stored;
1290
1313
  }
1291
1314
  stored.append(parsed);
1292
- client.resolve(stored, messageHash);
1315
+ const resolveData = [symbol, unifiedTimeframe, stored];
1316
+ client.resolve(resolveData, messageHash);
1293
1317
  }
1294
1318
  async fetchTickerWs(symbol, params = {}) {
1295
1319
  /**
@@ -7,7 +7,7 @@
7
7
  // ---------------------------------------------------------------------------
8
8
  import bitfinex2Rest from '../bitfinex2.js';
9
9
  import { Precise } from '../base/Precise.js';
10
- import { ExchangeError, AuthenticationError, InvalidNonce } from '../base/errors.js';
10
+ import { ExchangeError, AuthenticationError, ChecksumError } from '../base/errors.js';
11
11
  import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
12
12
  import { sha384 } from '../static_dependencies/noble-hashes/sha512.js';
13
13
  // ---------------------------------------------------------------------------
@@ -37,9 +37,9 @@ export default class bitfinex2 extends bitfinex2Rest {
37
37
  'watchOrderBook': {
38
38
  'prec': 'P0',
39
39
  'freq': 'F0',
40
+ 'checksum': true,
40
41
  },
41
42
  'ordersLimit': 1000,
42
- 'checksum': true,
43
43
  },
44
44
  });
45
45
  }
@@ -684,10 +684,13 @@ export default class bitfinex2 extends bitfinex2Rest {
684
684
  const localChecksum = this.crc32(payload, true);
685
685
  const responseChecksum = this.safeInteger(message, 2);
686
686
  if (responseChecksum !== localChecksum) {
687
- const error = new InvalidNonce(this.id + ' invalid checksum');
688
687
  delete client.subscriptions[messageHash];
689
688
  delete this.orderbooks[symbol];
690
- client.reject(error, messageHash);
689
+ const checksum = this.handleOption('watchOrderBook', 'checksum', true);
690
+ if (checksum) {
691
+ const error = new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
692
+ client.reject(error, messageHash);
693
+ }
691
694
  }
692
695
  }
693
696
  async watchBalance(params = {}) {
@@ -6,7 +6,7 @@
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  import bitgetRest from '../bitget.js';
9
- import { AuthenticationError, BadRequest, ArgumentsRequired, InvalidNonce, ExchangeError, RateLimitExceeded } from '../base/errors.js';
9
+ import { AuthenticationError, BadRequest, ArgumentsRequired, ChecksumError, ExchangeError, RateLimitExceeded } from '../base/errors.js';
10
10
  import { Precise } from '../base/Precise.js';
11
11
  import { ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp } from '../base/ws/Cache.js';
12
12
  import { sha256 } from '../static_dependencies/noble-hashes/sha256.js';
@@ -65,6 +65,9 @@ export default class bitget extends bitgetRest {
65
65
  '1d': '1D',
66
66
  '1w': '1W',
67
67
  },
68
+ 'watchOrderBook': {
69
+ 'checksum': true,
70
+ },
68
71
  },
69
72
  'streaming': {
70
73
  'ping': this.ping,
@@ -562,9 +565,9 @@ export default class bitget extends bitgetRest {
562
565
  const calculatedChecksum = this.crc32(payload, true);
563
566
  const responseChecksum = this.safeInteger(rawOrderBook, 'checksum');
564
567
  if (calculatedChecksum !== responseChecksum) {
565
- const error = new InvalidNonce(this.id + ' invalid checksum');
566
568
  delete client.subscriptions[messageHash];
567
569
  delete this.orderbooks[symbol];
570
+ const error = new ChecksumError(this.id + ' ' + this.orderbookChecksumMessage(symbol));
568
571
  client.reject(error, messageHash);
569
572
  return;
570
573
  }
@@ -757,8 +757,8 @@ export default class bitmart extends bitmartRest {
757
757
  const symbol = market['symbol'];
758
758
  const openTimestamp = this.safeInteger(position, 'create_time');
759
759
  const timestamp = this.safeInteger(position, 'update_time');
760
- const side = this.safeNumber(position, 'position_type');
761
- const marginModeId = this.safeNumber(position, 'open_type');
760
+ const side = this.safeInteger(position, 'position_type');
761
+ const marginModeId = this.safeInteger(position, 'open_type');
762
762
  return this.safePosition({
763
763
  'info': position,
764
764
  'id': undefined,
@@ -1322,7 +1322,7 @@ export default class bitmart extends bitmartRest {
1322
1322
  this.orderbooks[symbol] = ob;
1323
1323
  }
1324
1324
  const orderbook = this.orderbooks[symbol];
1325
- const way = this.safeNumber(data, 'way');
1325
+ const way = this.safeInteger(data, 'way');
1326
1326
  const side = (way === 1) ? 'bids' : 'asks';
1327
1327
  if (way === 1) {
1328
1328
  orderbook[side] = new Bids([], limit);
@@ -503,7 +503,7 @@ export default class bitvavo extends bitvavoRest {
503
503
  * @param {int} [since] the earliest time in ms to fetch trades for
504
504
  * @param {int} [limit] the maximum number of trade structures to retrieve
505
505
  * @param {object} [params] extra parameters specific to the exchange API endpoint
506
- * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=ortradeder-structure
506
+ * @returns {object[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
507
507
  */
508
508
  if (symbol === undefined) {
509
509
  throw new ArgumentsRequired(this.id + ' watchMyTrades() requires a symbol argument');
@@ -13,6 +13,7 @@ export default class bybit extends bybitRest {
13
13
  watchTickers(symbols?: Strings, params?: {}): Promise<Tickers>;
14
14
  handleTicker(client: Client, message: any): void;
15
15
  watchOHLCV(symbol: string, timeframe?: string, since?: Int, limit?: Int, params?: {}): Promise<OHLCV[]>;
16
+ watchOHLCVForSymbols(symbolsAndTimeframes: string[][], since?: Int, limit?: Int, params?: {}): Promise<import("../base/types.js").Dictionary<import("../base/types.js").Dictionary<OHLCV[]>>>;
16
17
  handleOHLCV(client: Client, message: any): void;
17
18
  parseWsOHLCV(ohlcv: any, market?: any): OHLCV;
18
19
  watchOrderBook(symbol: string, limit?: Int, params?: {}): Promise<OrderBook>;