ccxt 4.4.96 → 4.4.98

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 (79) hide show
  1. package/README.md +15 -15
  2. package/dist/ccxt.browser.min.js +2 -2
  3. package/dist/cjs/ccxt.js +2 -1
  4. package/dist/cjs/src/base/Exchange.js +63 -15
  5. package/dist/cjs/src/base/errors.js +8 -1
  6. package/dist/cjs/src/base/functions/number.js +30 -9
  7. package/dist/cjs/src/binance.js +95 -34
  8. package/dist/cjs/src/binancecoinm.js +5 -1
  9. package/dist/cjs/src/binanceus.js +3 -1
  10. package/dist/cjs/src/binanceusdm.js +3 -1
  11. package/dist/cjs/src/bingx.js +1 -1
  12. package/dist/cjs/src/bitget.js +18 -2
  13. package/dist/cjs/src/coinmetro.js +2 -3
  14. package/dist/cjs/src/cryptocom.js +77 -1
  15. package/dist/cjs/src/exmo.js +1 -1
  16. package/dist/cjs/src/foxbit.js +1 -1
  17. package/dist/cjs/src/gate.js +1 -2
  18. package/dist/cjs/src/hashkey.js +39 -0
  19. package/dist/cjs/src/hyperliquid.js +42 -27
  20. package/dist/cjs/src/independentreserve.js +35 -0
  21. package/dist/cjs/src/indodax.js +34 -0
  22. package/dist/cjs/src/kucoin.js +2 -1
  23. package/dist/cjs/src/latoken.js +42 -0
  24. package/dist/cjs/src/luno.js +36 -0
  25. package/dist/cjs/src/mercado.js +34 -0
  26. package/dist/cjs/src/mexc.js +3 -25
  27. package/dist/cjs/src/ndax.js +8 -0
  28. package/dist/cjs/src/okx.js +1 -0
  29. package/dist/cjs/src/phemex.js +36 -31
  30. package/dist/cjs/src/pro/binancecoinm.js +3 -1
  31. package/dist/cjs/src/pro/binanceus.js +3 -1
  32. package/dist/cjs/src/pro/binanceusdm.js +3 -1
  33. package/dist/cjs/src/pro/bybit.js +33 -0
  34. package/js/ccxt.d.ts +3 -3
  35. package/js/ccxt.js +3 -3
  36. package/js/src/abstract/binance.d.ts +3 -0
  37. package/js/src/abstract/binancecoinm.d.ts +3 -0
  38. package/js/src/abstract/binanceus.d.ts +3 -0
  39. package/js/src/abstract/binanceusdm.d.ts +3 -0
  40. package/js/src/abstract/phemex.d.ts +1 -0
  41. package/js/src/base/Exchange.d.ts +11 -3
  42. package/js/src/base/Exchange.js +63 -15
  43. package/js/src/base/errorHierarchy.d.ts +1 -0
  44. package/js/src/base/errorHierarchy.js +1 -0
  45. package/js/src/base/errors.d.ts +5 -1
  46. package/js/src/base/errors.js +8 -2
  47. package/js/src/base/functions/number.js +30 -9
  48. package/js/src/binance.d.ts +1 -0
  49. package/js/src/binance.js +95 -34
  50. package/js/src/binancecoinm.js +5 -1
  51. package/js/src/binanceus.js +3 -1
  52. package/js/src/binanceusdm.js +3 -1
  53. package/js/src/bingx.js +1 -1
  54. package/js/src/bitget.js +18 -2
  55. package/js/src/coinmetro.js +2 -3
  56. package/js/src/cryptocom.d.ts +12 -1
  57. package/js/src/cryptocom.js +77 -1
  58. package/js/src/exmo.js +1 -1
  59. package/js/src/foxbit.js +1 -1
  60. package/js/src/gate.js +1 -2
  61. package/js/src/hashkey.js +39 -0
  62. package/js/src/hyperliquid.js +42 -27
  63. package/js/src/independentreserve.js +35 -0
  64. package/js/src/indodax.js +34 -0
  65. package/js/src/kucoin.js +2 -1
  66. package/js/src/latoken.js +42 -0
  67. package/js/src/luno.js +36 -0
  68. package/js/src/mercado.js +34 -0
  69. package/js/src/mexc.d.ts +0 -1
  70. package/js/src/mexc.js +3 -25
  71. package/js/src/ndax.js +8 -0
  72. package/js/src/okx.js +2 -1
  73. package/js/src/phemex.js +36 -31
  74. package/js/src/pro/binancecoinm.js +3 -1
  75. package/js/src/pro/binanceus.js +3 -1
  76. package/js/src/pro/binanceusdm.js +3 -1
  77. package/js/src/pro/bybit.d.ts +11 -1
  78. package/js/src/pro/bybit.js +33 -0
  79. package/package.json +1 -2
package/dist/cjs/ccxt.js CHANGED
@@ -194,7 +194,7 @@ var xt$1 = require('./src/pro/xt.js');
194
194
 
195
195
  //-----------------------------------------------------------------------------
196
196
  // this is updated by vss.js when building
197
- const version = '4.4.96';
197
+ const version = '4.4.98';
198
198
  Exchange["default"].ccxtVersion = version;
199
199
  const exchanges = {
200
200
  'alpaca': alpaca,
@@ -427,6 +427,7 @@ exports.OrderNotFound = errors.OrderNotFound;
427
427
  exports.PermissionDenied = errors.PermissionDenied;
428
428
  exports.RateLimitExceeded = errors.RateLimitExceeded;
429
429
  exports.RequestTimeout = errors.RequestTimeout;
430
+ exports.RestrictedLocation = errors.RestrictedLocation;
430
431
  exports.UnsubscribeError = errors.UnsubscribeError;
431
432
  exports.errors = errors;
432
433
  exports.alpaca = alpaca;
@@ -1582,6 +1582,17 @@ class Exchange {
1582
1582
  'watchLiquidations': undefined,
1583
1583
  'watchLiquidationsForSymbols': undefined,
1584
1584
  'watchMyLiquidations': undefined,
1585
+ 'unWatchOrders': undefined,
1586
+ 'unWatchTrades': undefined,
1587
+ 'unWatchTradesForSymbols': undefined,
1588
+ 'unWatchOHLCVForSymbols': undefined,
1589
+ 'unWatchOrderBookForSymbols': undefined,
1590
+ 'unWatchPositions': undefined,
1591
+ 'unWatchOrderBook': undefined,
1592
+ 'unWatchTickers': undefined,
1593
+ 'unWatchMyTrades': undefined,
1594
+ 'unWatchTicker': undefined,
1595
+ 'unWatchOHLCV': undefined,
1585
1596
  'watchMyLiquidationsForSymbols': undefined,
1586
1597
  'withdraw': undefined,
1587
1598
  'ws': undefined,
@@ -2143,6 +2154,9 @@ class Exchange {
2143
2154
  async unWatchOrderBookForSymbols(symbols, params = {}) {
2144
2155
  throw new errors.NotSupported(this.id + ' unWatchOrderBookForSymbols() is not supported yet');
2145
2156
  }
2157
+ async unWatchPositions(symbols = undefined, params = {}) {
2158
+ throw new errors.NotSupported(this.id + ' unWatchPositions() is not supported yet');
2159
+ }
2146
2160
  async fetchDepositAddresses(codes = undefined, params = {}) {
2147
2161
  throw new errors.NotSupported(this.id + ' fetchDepositAddresses() is not supported yet');
2148
2162
  }
@@ -3259,19 +3273,7 @@ class Exchange {
3259
3273
  const symbol = (market !== undefined) ? market['symbol'] : undefined;
3260
3274
  return this.filterBySymbolSinceLimit(results, symbol, since, limit);
3261
3275
  }
3262
- calculateFee(symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) {
3263
- /**
3264
- * @method
3265
- * @description calculates the presumptive fee that would be charged for an order
3266
- * @param {string} symbol unified market symbol
3267
- * @param {string} type 'market' or 'limit'
3268
- * @param {string} side 'buy' or 'sell'
3269
- * @param {float} amount how much you want to trade, in units of the base currency on most exchanges, or number of contracts
3270
- * @param {float} price the price for the order to be filled at, in units of the quote currency
3271
- * @param {string} takerOrMaker 'taker' or 'maker'
3272
- * @param {object} params
3273
- * @returns {object} contains the rate, the percentage multiplied to the order amount to obtain the fee amount, and cost, the total value of the fee in units of the quote currency, for the order
3274
- */
3276
+ calculateFeeWithRate(symbol, type, side, amount, price, takerOrMaker = 'taker', feeRate = undefined, params = {}) {
3275
3277
  if (type === 'market' && takerOrMaker === 'maker') {
3276
3278
  throw new errors.ArgumentsRequired(this.id + ' calculateFee() - you have provided incompatible arguments - "market" type order can not be "maker". Change either the "type" or the "takerOrMaker" argument to calculate the fee.');
3277
3279
  }
@@ -3308,7 +3310,7 @@ class Exchange {
3308
3310
  if (type === 'market') {
3309
3311
  takerOrMaker = 'taker';
3310
3312
  }
3311
- const rate = this.safeString(market, takerOrMaker);
3313
+ const rate = (feeRate !== undefined) ? this.numberToString(feeRate) : this.safeString(market, takerOrMaker);
3312
3314
  cost = Precise["default"].stringMul(cost, rate);
3313
3315
  return {
3314
3316
  'type': takerOrMaker,
@@ -3317,6 +3319,21 @@ class Exchange {
3317
3319
  'cost': this.parseNumber(cost),
3318
3320
  };
3319
3321
  }
3322
+ calculateFee(symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) {
3323
+ /**
3324
+ * @method
3325
+ * @description calculates the presumptive fee that would be charged for an order
3326
+ * @param {string} symbol unified market symbol
3327
+ * @param {string} type 'market' or 'limit'
3328
+ * @param {string} side 'buy' or 'sell'
3329
+ * @param {float} amount how much you want to trade, in units of the base currency on most exchanges, or number of contracts
3330
+ * @param {float} price the price for the order to be filled at, in units of the quote currency
3331
+ * @param {string} takerOrMaker 'taker' or 'maker'
3332
+ * @param {object} params
3333
+ * @returns {object} contains the rate, the percentage multiplied to the order amount to obtain the fee amount, and cost, the total value of the fee in units of the quote currency, for the order
3334
+ */
3335
+ return this.calculateFeeWithRate(symbol, type, side, amount, price, takerOrMaker, undefined, params);
3336
+ }
3320
3337
  safeLiquidation(liquidation, market = undefined) {
3321
3338
  const contracts = this.safeString(liquidation, 'contracts');
3322
3339
  const contractSize = this.safeString(market, 'contractSize');
@@ -3361,6 +3378,26 @@ class Exchange {
3361
3378
  trade['cost'] = this.parseNumber(cost);
3362
3379
  return trade;
3363
3380
  }
3381
+ createCcxtTradeId(timestamp = undefined, side = undefined, amount = undefined, price = undefined, takerOrMaker = undefined) {
3382
+ // this approach is being used by multiple exchanges (mexc, woo, coinsbit, dydx, ...)
3383
+ let id = undefined;
3384
+ if (timestamp !== undefined) {
3385
+ id = this.numberToString(timestamp);
3386
+ if (side !== undefined) {
3387
+ id += '-' + side;
3388
+ }
3389
+ if (amount !== undefined) {
3390
+ id += '-' + this.numberToString(amount);
3391
+ }
3392
+ if (price !== undefined) {
3393
+ id += '-' + this.numberToString(price);
3394
+ }
3395
+ if (takerOrMaker !== undefined) {
3396
+ id += '-' + takerOrMaker;
3397
+ }
3398
+ }
3399
+ return id;
3400
+ }
3364
3401
  parsedFeeAndFees(container) {
3365
3402
  let fee = this.safeDict(container, 'fee');
3366
3403
  let fees = this.safeList(container, 'fees');
@@ -6605,7 +6642,7 @@ class Exchange {
6605
6642
  let calls = 0;
6606
6643
  let result = [];
6607
6644
  let errors$1 = 0;
6608
- const until = this.safeInteger2(params, 'untill', 'till'); // do not omit it from params here
6645
+ const until = this.safeIntegerN(params, ['until', 'untill', 'till']); // do not omit it from params here
6609
6646
  [maxEntriesPerRequest, params] = this.handleMaxEntriesPerRequestAndParams(method, maxEntriesPerRequest, params);
6610
6647
  if ((paginationDirection === 'forward')) {
6611
6648
  if (since === undefined) {
@@ -7299,6 +7336,17 @@ class Exchange {
7299
7336
  else if (topic === 'orders' && (this.orders !== undefined)) {
7300
7337
  this.orders = undefined;
7301
7338
  }
7339
+ else if (topic === 'positions' && (this.positions !== undefined)) {
7340
+ this.positions = undefined;
7341
+ const clients = Object.values(this.clients);
7342
+ for (let i = 0; i < clients.length; i++) {
7343
+ const client = clients[i];
7344
+ const futures = this.safeDict(client, 'futures');
7345
+ if ((futures !== undefined) && ('fetchPositionsSnapshot' in futures)) {
7346
+ delete futures['fetchPositionsSnapshot'];
7347
+ }
7348
+ }
7349
+ }
7302
7350
  else if (topic === 'ticker' && (this.tickers !== undefined)) {
7303
7351
  const tickerSymbols = Object.keys(this.tickers);
7304
7352
  for (let i = 0; i < tickerSymbols.length; i++) {
@@ -93,6 +93,12 @@ class ManualInteractionNeeded extends OperationRejected {
93
93
  this.name = 'ManualInteractionNeeded';
94
94
  }
95
95
  }
96
+ class RestrictedLocation extends OperationRejected {
97
+ constructor(message) {
98
+ super(message);
99
+ this.name = 'RestrictedLocation';
100
+ }
101
+ }
96
102
  class InsufficientFunds extends ExchangeError {
97
103
  constructor(message) {
98
104
  super(message);
@@ -249,7 +255,7 @@ class UnsubscribeError extends BaseError {
249
255
  this.name = 'UnsubscribeError';
250
256
  }
251
257
  }
252
- var errors = { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, ManualInteractionNeeded, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, InvalidProxySettings, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, ChecksumError, RequestTimeout, BadResponse, NullResponse, CancelPending, UnsubscribeError };
258
+ var errors = { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, ManualInteractionNeeded, RestrictedLocation, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, InvalidProxySettings, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, ChecksumError, RequestTimeout, BadResponse, NullResponse, CancelPending, UnsubscribeError };
253
259
 
254
260
  exports.AccountNotEnabled = AccountNotEnabled;
255
261
  exports.AccountSuspended = AccountSuspended;
@@ -290,5 +296,6 @@ exports.OrderNotFound = OrderNotFound;
290
296
  exports.PermissionDenied = PermissionDenied;
291
297
  exports.RateLimitExceeded = RateLimitExceeded;
292
298
  exports.RequestTimeout = RequestTimeout;
299
+ exports.RestrictedLocation = RestrictedLocation;
293
300
  exports.UnsubscribeError = UnsubscribeError;
294
301
  exports["default"] = errors;
@@ -40,6 +40,8 @@ const precisionConstants = {
40
40
  NO_PADDING,
41
41
  PAD_WITH_ZERO,
42
42
  };
43
+ const assert = (x, y) => { if (!x)
44
+ throw new Error(y || 'assertion failed'); };
43
45
  /* ------------------------------------------------------------------------ */
44
46
  // See https://stackoverflow.com/questions/1685680/how-to-avoid-scientific-notation-for-large-numbers-in-javascript for discussion
45
47
  function numberToString(x) {
@@ -105,14 +107,21 @@ const decimalToPrecision = (x, roundingMode, numPrecisionDigits, countingMode =
105
107
  return _decimalToPrecision(x, roundingMode, numPrecisionDigits, countingMode, paddingMode);
106
108
  };
107
109
  const _decimalToPrecision = (x, roundingMode, numPrecisionDigits, countingMode = DECIMAL_PLACES, paddingMode = NO_PADDING) => {
110
+ assert(numPrecisionDigits !== undefined, 'numPrecisionDigits should not be undefined');
111
+ if (typeof numPrecisionDigits === 'string') {
112
+ numPrecisionDigits = parseFloat(numPrecisionDigits);
113
+ }
114
+ assert(Number.isFinite(numPrecisionDigits), 'numPrecisionDigits has an invalid number');
108
115
  if (countingMode === TICK_SIZE) {
109
- if (typeof numPrecisionDigits === 'string') {
110
- numPrecisionDigits = parseFloat(numPrecisionDigits);
111
- }
112
- if (numPrecisionDigits <= 0) {
113
- throw new Error('TICK_SIZE cant be used with negative or zero numPrecisionDigits');
114
- }
116
+ assert(numPrecisionDigits > 0, 'negative or zero numPrecisionDigits can not be used with TICK_SIZE precisionMode');
117
+ }
118
+ else {
119
+ assert(Number.isInteger(numPrecisionDigits), 'numPrecisionDigits must be an integer with DECIMAL_PLACES or SIGNIFICANT_DIGITS precisionMode');
115
120
  }
121
+ assert((roundingMode === ROUND) || (roundingMode === TRUNCATE), 'invalid roundingMode provided');
122
+ assert(countingMode === DECIMAL_PLACES || countingMode === SIGNIFICANT_DIGITS || countingMode === TICK_SIZE, 'invalid countingMode provided');
123
+ assert(paddingMode === NO_PADDING || paddingMode === PAD_WITH_ZERO, 'invalid paddingMode provided');
124
+ // end of checks
116
125
  if (numPrecisionDigits < 0) {
117
126
  const toNearest = Math.pow(10, -numPrecisionDigits);
118
127
  if (roundingMode === ROUND) {
@@ -126,6 +135,21 @@ const _decimalToPrecision = (x, roundingMode, numPrecisionDigits, countingMode =
126
135
  if (countingMode === TICK_SIZE) {
127
136
  const precisionDigitsString = _decimalToPrecision(numPrecisionDigits, ROUND, 22, DECIMAL_PLACES, NO_PADDING);
128
137
  const newNumPrecisionDigits = precisionFromString(precisionDigitsString);
138
+ if (roundingMode === TRUNCATE) {
139
+ // First, truncate the string to avoid floating-point precision issues
140
+ const xStr = numberToString(x);
141
+ const truncatedX = truncate_to_string(xStr, Math.max(0, newNumPrecisionDigits));
142
+ const xNum = Number(truncatedX);
143
+ const scale = Math.pow(10, newNumPrecisionDigits);
144
+ const xScaled = Math.round(xNum * scale);
145
+ const tickScaled = Math.round(numPrecisionDigits * scale);
146
+ const ticks = Math.trunc(xScaled / tickScaled);
147
+ x = (ticks * tickScaled) / scale;
148
+ if (paddingMode === NO_PADDING) {
149
+ return String(Number(x.toFixed(newNumPrecisionDigits)));
150
+ }
151
+ return _decimalToPrecision(x, ROUND, newNumPrecisionDigits, DECIMAL_PLACES, paddingMode);
152
+ }
129
153
  let missing = x % numPrecisionDigits;
130
154
  // See: https://github.com/ccxt/ccxt/pull/6486
131
155
  missing = Number(_decimalToPrecision(missing, ROUND, 8, DECIMAL_PLACES, NO_PADDING));
@@ -149,9 +173,6 @@ const _decimalToPrecision = (x, roundingMode, numPrecisionDigits, countingMode =
149
173
  }
150
174
  }
151
175
  }
152
- else if (roundingMode === TRUNCATE) {
153
- x = x - missing;
154
- }
155
176
  }
156
177
  return _decimalToPrecision(x, ROUND, newNumPrecisionDigits, DECIMAL_PLACES, paddingMode);
157
178
  }
@@ -482,6 +482,7 @@ class binance extends binance$1 {
482
482
  'portfolio/balance': 2,
483
483
  'portfolio/negative-balance-exchange-record': 2,
484
484
  'portfolio/pmloan-history': 5,
485
+ 'portfolio/earn-asset-balance': 150,
485
486
  // staking
486
487
  'staking/productList': 0.1,
487
488
  'staking/position': 0.1,
@@ -640,6 +641,7 @@ class binance extends binance$1 {
640
641
  'portfolio/repay-futures-negative-balance': 150,
641
642
  'portfolio/mint': 20,
642
643
  'portfolio/redeem': 20,
644
+ 'portfolio/earn-asset-transfer': 150,
643
645
  'lending/auto-invest/plan/add': 0.1,
644
646
  'lending/auto-invest/plan/edit': 0.1,
645
647
  'lending/auto-invest/plan/edit-status': 0.1,
@@ -828,6 +830,7 @@ class binance extends binance$1 {
828
830
  'apiTradingStatus': { 'cost': 1, 'noSymbol': 10 },
829
831
  'lvtKlines': 1,
830
832
  'convert/exchangeInfo': 4,
833
+ 'insuranceBalance': 1,
831
834
  },
832
835
  },
833
836
  'fapiData': {
@@ -1265,12 +1268,14 @@ class binance extends binance$1 {
1265
1268
  'options': {
1266
1269
  'sandboxMode': false,
1267
1270
  'fetchMargins': true,
1268
- 'fetchMarkets': [
1269
- 'spot',
1270
- 'linear',
1271
- 'inverse', // allows CORS in browsers
1272
- // 'option', // does not allow CORS, enable outside of the browser only
1273
- ],
1271
+ 'fetchMarkets': {
1272
+ 'types': [
1273
+ 'spot',
1274
+ 'linear',
1275
+ 'inverse', // allows CORS in browsers
1276
+ // 'option', // does not allow CORS, enable outside of the browser only
1277
+ ],
1278
+ },
1274
1279
  'loadAllOptions': false,
1275
1280
  'fetchCurrencies': true,
1276
1281
  // 'fetchTradesMethod': 'publicGetAggTrades', // publicGetTrades, publicGetHistoricalTrades, eapiPublicGetTrades
@@ -3037,7 +3042,16 @@ class binance extends binance$1 {
3037
3042
  */
3038
3043
  async fetchMarkets(params = {}) {
3039
3044
  const promisesRaw = [];
3040
- const rawFetchMarkets = this.safeList(this.options, 'fetchMarkets', ['spot', 'linear', 'inverse']);
3045
+ let rawFetchMarkets = undefined;
3046
+ const defaultTypes = ['spot', 'linear', 'inverse'];
3047
+ const fetchMarketsOptions = this.safeDict(this.options, 'fetchMarkets');
3048
+ if (fetchMarketsOptions !== undefined) {
3049
+ rawFetchMarkets = this.safeList(fetchMarketsOptions, 'types', defaultTypes);
3050
+ }
3051
+ else {
3052
+ // for backward-compatibility
3053
+ rawFetchMarkets = this.safeList(this.options, 'fetchMarkets', defaultTypes);
3054
+ }
3041
3055
  // handle loadAllOptions option
3042
3056
  const loadAllOptions = this.safeBool(this.options, 'loadAllOptions', false);
3043
3057
  if (loadAllOptions) {
@@ -4007,29 +4021,52 @@ class binance extends binance$1 {
4007
4021
  // "time": 1597370495002
4008
4022
  // }
4009
4023
  //
4010
- // {
4011
- // "symbol": "ETHBTC",
4012
- // "priceChange": "0.00068700",
4013
- // "priceChangePercent": "2.075",
4014
- // "weightedAvgPrice": "0.03342681",
4015
- // "prevClosePrice": "0.03310300",
4016
- // "lastPrice": "0.03378900",
4017
- // "lastQty": "0.07700000",
4018
- // "bidPrice": "0.03378900",
4019
- // "bidQty": "7.16800000",
4020
- // "askPrice": "0.03379000",
4021
- // "askQty": "24.00000000",
4022
- // "openPrice": "0.03310200",
4023
- // "highPrice": "0.03388900",
4024
- // "lowPrice": "0.03306900",
4025
- // "volume": "205478.41000000",
4026
- // "quoteVolume": "6868.48826294",
4027
- // "openTime": 1601469986932,
4028
- // "closeTime": 1601556386932,
4029
- // "firstId": 196098772,
4030
- // "lastId": 196186315,
4031
- // "count": 87544
4032
- // }
4024
+ // spot - ticker
4025
+ //
4026
+ // {
4027
+ // "symbol": "BTCUSDT",
4028
+ // "priceChange": "-188.18000000",
4029
+ // "priceChangePercent": "-0.159",
4030
+ // "weightedAvgPrice": "118356.64734074",
4031
+ // "lastPrice": "118449.03000000",
4032
+ // "prevClosePrice": "118637.22000000", // field absent in rolling ticker
4033
+ // "lastQty": "0.00731000", // field absent in rolling ticker
4034
+ // "bidPrice": "118449.02000000", // field absent in rolling ticker
4035
+ // "bidQty": "7.15931000", // field absent in rolling ticker
4036
+ // "askPrice": "118449.03000000", // field absent in rolling ticker
4037
+ // "askQty": "0.09592000", // field absent in rolling ticker
4038
+ // "openPrice": "118637.21000000",
4039
+ // "highPrice": "119273.36000000",
4040
+ // "lowPrice": "117427.50000000",
4041
+ // "volume": "14741.41491000",
4042
+ // "quoteVolume": "1744744445.80640740",
4043
+ // "openTime": "1753701474013",
4044
+ // "closeTime": "1753787874013",
4045
+ // "firstId": "5116031635",
4046
+ // "lastId": "5117964946",
4047
+ // "count": "1933312"
4048
+ // }
4049
+ //
4050
+ // usdm tickers
4051
+ //
4052
+ // {
4053
+ // "symbol": "SUSDT",
4054
+ // "priceChange": "-0.0229000",
4055
+ // "priceChangePercent": "-6.777",
4056
+ // "weightedAvgPrice": "0.3210035",
4057
+ // "lastPrice": "0.3150000",
4058
+ // "lastQty": "16",
4059
+ // "openPrice": "0.3379000",
4060
+ // "highPrice": "0.3411000",
4061
+ // "lowPrice": "0.3071000",
4062
+ // "volume": "120588225",
4063
+ // "quoteVolume": "38709237.2289000",
4064
+ // "openTime": "1753701720000",
4065
+ // "closeTime": "1753788172414",
4066
+ // "firstId": "72234973",
4067
+ // "lastId": "72423677",
4068
+ // "count": "188700"
4069
+ // }
4033
4070
  //
4034
4071
  // coinm
4035
4072
  //
@@ -4402,11 +4439,24 @@ class binance extends binance$1 {
4402
4439
  response = await this.dapiPublicGetTicker24hr(params);
4403
4440
  }
4404
4441
  else if (type === 'spot') {
4405
- const request = {};
4406
- if (symbols !== undefined) {
4407
- request['symbols'] = this.json(this.marketIds(symbols));
4442
+ const rolling = this.safeBool(params, 'rolling', false);
4443
+ params = this.omit(params, 'rolling');
4444
+ if (rolling) {
4445
+ symbols = this.marketSymbols(symbols);
4446
+ const request = {
4447
+ 'symbols': this.json(this.marketIds(symbols)),
4448
+ };
4449
+ response = await this.publicGetTicker(this.extend(request, params));
4450
+ // parseTicker is not able to handle marketType for spot-rolling ticker fields, so we need custom parsing
4451
+ return this.parseTickersForRolling(response, symbols);
4452
+ }
4453
+ else {
4454
+ const request = {};
4455
+ if (symbols !== undefined) {
4456
+ request['symbols'] = this.json(this.marketIds(symbols));
4457
+ }
4458
+ response = await this.publicGetTicker24hr(this.extend(request, params));
4408
4459
  }
4409
- response = await this.publicGetTicker24hr(this.extend(request, params));
4410
4460
  }
4411
4461
  else if (type === 'option') {
4412
4462
  response = await this.eapiPublicGetTicker(params);
@@ -4416,6 +4466,17 @@ class binance extends binance$1 {
4416
4466
  }
4417
4467
  return this.parseTickers(response, symbols);
4418
4468
  }
4469
+ parseTickersForRolling(response, symbols) {
4470
+ const results = [];
4471
+ for (let i = 0; i < response.length; i++) {
4472
+ const marketId = this.safeString(response[i], 'symbol');
4473
+ const tickerMarket = this.safeMarket(marketId, undefined, undefined, 'spot');
4474
+ const parsedTicker = this.parseTicker(response[i]);
4475
+ parsedTicker['symbol'] = tickerMarket['symbol'];
4476
+ results.push(parsedTicker);
4477
+ }
4478
+ return this.filterByArray(results, 'symbol', symbols);
4479
+ }
4419
4480
  /**
4420
4481
  * @method
4421
4482
  * @name binance#fetchMarkPrice
@@ -27,7 +27,11 @@ class binancecoinm extends binance {
27
27
  'createStopMarketOrder': true,
28
28
  },
29
29
  'options': {
30
- 'fetchMarkets': ['inverse'],
30
+ 'fetchMarkets': {
31
+ 'types': [
32
+ 'inverse',
33
+ ],
34
+ },
31
35
  'defaultSubType': 'inverse',
32
36
  'leverageBrackets': undefined,
33
37
  },
@@ -38,7 +38,9 @@ class binanceus extends binance {
38
38
  },
39
39
  },
40
40
  'options': {
41
- 'fetchMarkets': ['spot'],
41
+ 'fetchMarkets': {
42
+ 'types': ['spot'],
43
+ },
42
44
  'defaultType': 'spot',
43
45
  'fetchMargins': false,
44
46
  'quoteOrderQty': false,
@@ -28,7 +28,9 @@ class binanceusdm extends binance {
28
28
  'createStopMarketOrder': true,
29
29
  },
30
30
  'options': {
31
- 'fetchMarkets': ['linear'],
31
+ 'fetchMarkets': {
32
+ 'types': ['linear'],
33
+ },
32
34
  'defaultSubType': 'linear',
33
35
  // https://www.binance.com/en/support/faq/360033162192
34
36
  // tier amount, maintenance margin, initial margin,
@@ -5301,7 +5301,7 @@ class bingx extends bingx$1 {
5301
5301
  const id = this.safeString(transaction, 'id', dataId);
5302
5302
  const address = this.safeString(transaction, 'address');
5303
5303
  const tag = this.safeString(transaction, 'addressTag');
5304
- let timestamp = this.safeInteger(transaction, 'insertTime');
5304
+ let timestamp = this.safeInteger2(transaction, 'insertTime', 'timestamp');
5305
5305
  let datetime = this.iso8601(timestamp);
5306
5306
  if (timestamp === undefined) {
5307
5307
  datetime = this.safeString(transaction, 'applyTime');
@@ -3912,6 +3912,10 @@ class bitget extends bitget$1 {
3912
3912
  response = await this.publicSpotGetV2SpotMarketHistoryCandles(this.extend(request, params));
3913
3913
  }
3914
3914
  else {
3915
+ if (!limitDefined) {
3916
+ request['limit'] = 1000;
3917
+ limit = 1000;
3918
+ }
3915
3919
  response = await this.publicSpotGetV2SpotMarketCandles(this.extend(request, params));
3916
3920
  }
3917
3921
  }
@@ -3922,8 +3926,16 @@ class bitget extends bitget$1 {
3922
3926
  [productType, params] = this.handleProductTypeAndParams(market, params);
3923
3927
  request['productType'] = productType;
3924
3928
  const extended = this.extend(request, params);
3925
- // todo: mark & index also have their "recent" endpoints, but not priority now.
3926
- if (priceType === 'mark') {
3929
+ if (!historicalEndpointNeeded && (priceType === 'mark' || priceType === 'index')) {
3930
+ if (!limitDefined) {
3931
+ extended['limit'] = 1000;
3932
+ limit = 1000;
3933
+ }
3934
+ // Recent endpoint for mark/index prices
3935
+ // https://www.bitget.com/api-doc/contract/market/Get-Candle-Data
3936
+ response = await this.publicMixGetV2MixMarketCandles(this.extend({ 'kLineType': priceType }, extended));
3937
+ }
3938
+ else if (priceType === 'mark') {
3927
3939
  response = await this.publicMixGetV2MixMarketHistoryMarkCandles(extended);
3928
3940
  }
3929
3941
  else if (priceType === 'index') {
@@ -3934,6 +3946,10 @@ class bitget extends bitget$1 {
3934
3946
  response = await this.publicMixGetV2MixMarketHistoryCandles(extended);
3935
3947
  }
3936
3948
  else {
3949
+ if (!limitDefined) {
3950
+ extended['limit'] = 1000;
3951
+ limit = 1000;
3952
+ }
3937
3953
  response = await this.publicMixGetV2MixMarketCandles(extended);
3938
3954
  }
3939
3955
  }
@@ -210,7 +210,6 @@ class coinmetro extends coinmetro$1 {
210
210
  'options': {
211
211
  'currenciesByIdForParseMarket': undefined,
212
212
  'currencyIdsListForParseMarket': ['QRDO'],
213
- 'skippedMarkets': ['VXVUSDT'], // broken markets which do not have enough info in API
214
213
  },
215
214
  'features': {
216
215
  'spot': {
@@ -458,11 +457,11 @@ class coinmetro extends coinmetro$1 {
458
457
  // ...
459
458
  // ]
460
459
  //
461
- const skippedMarkets = this.safeList(this.options, 'skippedMarkets', []);
462
460
  const result = [];
463
461
  for (let i = 0; i < response.length; i++) {
464
462
  const market = this.parseMarket(response[i]);
465
- if (this.inArray(market['id'], skippedMarkets)) {
463
+ // there are several broken (unavailable info) markets
464
+ if (market['base'] === undefined || market['quote'] === undefined) {
466
465
  continue;
467
466
  }
468
467
  result.push(market);
@@ -61,7 +61,7 @@ class cryptocom extends cryptocom$1 {
61
61
  'fetchDepositWithdrawFee': 'emulated',
62
62
  'fetchDepositWithdrawFees': true,
63
63
  'fetchFundingHistory': false,
64
- 'fetchFundingRate': false,
64
+ 'fetchFundingRate': true,
65
65
  'fetchFundingRateHistory': true,
66
66
  'fetchFundingRates': false,
67
67
  'fetchGreeks': false,
@@ -462,6 +462,7 @@ class cryptocom extends cryptocom$1 {
462
462
  'exceptions': {
463
463
  'exact': {
464
464
  '219': errors.InvalidOrder,
465
+ '306': errors.InsufficientFunds,
465
466
  '314': errors.InvalidOrder,
466
467
  '325': errors.InvalidOrder,
467
468
  '415': errors.InvalidOrder,
@@ -2991,6 +2992,81 @@ class cryptocom extends cryptocom$1 {
2991
2992
  }
2992
2993
  return result;
2993
2994
  }
2995
+ /**
2996
+ * @method
2997
+ * @name cryptocom#fetchFundingRate
2998
+ * @description fetches historical funding rates
2999
+ * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-valuations
3000
+ * @param {string} symbol unified symbol of the market to fetch the funding rate history for
3001
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
3002
+ * @returns {object[]} a list of [funding rate structures]{@link https://docs.ccxt.com/#/?id=funding-rate-history-structure}
3003
+ */
3004
+ async fetchFundingRate(symbol, params = {}) {
3005
+ await this.loadMarkets();
3006
+ const market = this.market(symbol);
3007
+ if (!market['swap']) {
3008
+ throw new errors.BadSymbol(this.id + ' fetchFundingRate() supports swap contracts only');
3009
+ }
3010
+ const request = {
3011
+ 'instrument_name': market['id'],
3012
+ 'valuation_type': 'estimated_funding_rate',
3013
+ 'count': 1,
3014
+ };
3015
+ const response = await this.v1PublicGetPublicGetValuations(this.extend(request, params));
3016
+ //
3017
+ // {
3018
+ // "id": -1,
3019
+ // "method": "public/get-valuations",
3020
+ // "code": 0,
3021
+ // "result": {
3022
+ // "data": [
3023
+ // {
3024
+ // "v": "-0.000001884",
3025
+ // "t": 1687892400000
3026
+ // },
3027
+ // ],
3028
+ // "instrument_name": "BTCUSD-PERP"
3029
+ // }
3030
+ // }
3031
+ //
3032
+ const result = this.safeDict(response, 'result', {});
3033
+ const data = this.safeList(result, 'data', []);
3034
+ const entry = this.safeDict(data, 0, {});
3035
+ return this.parseFundingRate(entry, market);
3036
+ }
3037
+ parseFundingRate(contract, market = undefined) {
3038
+ //
3039
+ // {
3040
+ // "v": "-0.000001884",
3041
+ // "t": 1687892400000
3042
+ // },
3043
+ //
3044
+ const timestamp = this.safeInteger(contract, 't');
3045
+ let fundingTimestamp = undefined;
3046
+ if (timestamp !== undefined) {
3047
+ fundingTimestamp = Math.ceil(timestamp / 3600000) * 3600000; // end of the next hour
3048
+ }
3049
+ return {
3050
+ 'info': contract,
3051
+ 'symbol': this.safeSymbol(undefined, market),
3052
+ 'markPrice': undefined,
3053
+ 'indexPrice': undefined,
3054
+ 'interestRate': undefined,
3055
+ 'estimatedSettlePrice': undefined,
3056
+ 'timestamp': timestamp,
3057
+ 'datetime': this.iso8601(timestamp),
3058
+ 'fundingRate': this.safeNumber(contract, 'v'),
3059
+ 'fundingTimestamp': fundingTimestamp,
3060
+ 'fundingDatetime': this.iso8601(fundingTimestamp),
3061
+ 'nextFundingRate': undefined,
3062
+ 'nextFundingTimestamp': undefined,
3063
+ 'nextFundingDatetime': undefined,
3064
+ 'previousFundingRate': undefined,
3065
+ 'previousFundingTimestamp': undefined,
3066
+ 'previousFundingDatetime': undefined,
3067
+ 'interval': '1h',
3068
+ };
3069
+ }
2994
3070
  /**
2995
3071
  * @method
2996
3072
  * @name cryptocom#fetchFundingRateHistory