ccxt 4.2.58 → 4.2.60

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 (92) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +3 -3
  3. package/build.sh +1 -1
  4. package/cleanup.sh +3 -0
  5. package/dist/ccxt.browser.js +716 -382
  6. package/dist/ccxt.browser.min.js +3 -3
  7. package/dist/cjs/ccxt.js +1 -1
  8. package/dist/cjs/src/ascendex.js +10 -12
  9. package/dist/cjs/src/base/Exchange.js +2 -0
  10. package/dist/cjs/src/binance.js +2 -2
  11. package/dist/cjs/src/bingx.js +41 -3
  12. package/dist/cjs/src/bitfinex2.js +21 -4
  13. package/dist/cjs/src/bitget.js +10 -3
  14. package/dist/cjs/src/bitmart.js +41 -23
  15. package/dist/cjs/src/bitmex.js +1 -1
  16. package/dist/cjs/src/blofin.js +60 -2
  17. package/dist/cjs/src/coinbase.js +24 -14
  18. package/dist/cjs/src/hitbtc.js +1 -1
  19. package/dist/cjs/src/htx.js +4 -1
  20. package/dist/cjs/src/kraken.js +42 -39
  21. package/dist/cjs/src/kucoinfutures.js +1 -0
  22. package/dist/cjs/src/lbank.js +1 -1
  23. package/dist/cjs/src/mexc.js +1 -1
  24. package/dist/cjs/src/okx.js +1 -1
  25. package/dist/cjs/src/phemex.js +1 -1
  26. package/dist/cjs/src/pro/binance.js +17 -4
  27. package/dist/cjs/src/pro/bitfinex2.js +1 -1
  28. package/dist/cjs/src/pro/bitget.js +1 -1
  29. package/dist/cjs/src/pro/bitmart.js +51 -89
  30. package/dist/cjs/src/pro/bitvavo.js +1 -1
  31. package/dist/cjs/src/pro/bybit.js +1 -1
  32. package/dist/cjs/src/pro/coinex.js +1 -1
  33. package/dist/cjs/src/pro/cryptocom.js +1 -1
  34. package/dist/cjs/src/pro/deribit.js +201 -84
  35. package/dist/cjs/src/pro/gate.js +1 -1
  36. package/dist/cjs/src/pro/independentreserve.js +1 -1
  37. package/dist/cjs/src/pro/kraken.js +1 -1
  38. package/dist/cjs/src/pro/kucoinfutures.js +1 -1
  39. package/dist/cjs/src/pro/mexc.js +5 -3
  40. package/dist/cjs/src/pro/okx.js +1 -1
  41. package/dist/cjs/src/pro/woo.js +1 -1
  42. package/dist/cjs/src/wazirx.js +6 -1
  43. package/dist/cjs/src/woo.js +159 -79
  44. package/js/ccxt.d.ts +1 -1
  45. package/js/ccxt.js +1 -1
  46. package/js/src/abstract/blofin.d.ts +1 -0
  47. package/js/src/abstract/wazirx.d.ts +5 -0
  48. package/js/src/ascendex.d.ts +2 -2
  49. package/js/src/ascendex.js +10 -12
  50. package/js/src/base/Exchange.js +2 -0
  51. package/js/src/binance.js +2 -2
  52. package/js/src/bingx.d.ts +3 -1
  53. package/js/src/bingx.js +41 -3
  54. package/js/src/bitfinex2.js +21 -4
  55. package/js/src/bitget.js +10 -3
  56. package/js/src/bitmart.d.ts +9 -2
  57. package/js/src/bitmart.js +41 -23
  58. package/js/src/bitmex.js +1 -1
  59. package/js/src/blofin.d.ts +2 -1
  60. package/js/src/blofin.js +60 -2
  61. package/js/src/coinbase.js +24 -14
  62. package/js/src/hitbtc.js +1 -1
  63. package/js/src/htx.js +4 -1
  64. package/js/src/kraken.js +42 -39
  65. package/js/src/kucoinfutures.js +1 -0
  66. package/js/src/lbank.js +1 -1
  67. package/js/src/mexc.js +1 -1
  68. package/js/src/okx.js +1 -1
  69. package/js/src/phemex.js +1 -1
  70. package/js/src/pro/binance.js +17 -4
  71. package/js/src/pro/bitfinex2.js +1 -1
  72. package/js/src/pro/bitget.js +1 -1
  73. package/js/src/pro/bitmart.d.ts +2 -2
  74. package/js/src/pro/bitmart.js +51 -89
  75. package/js/src/pro/bitvavo.js +1 -1
  76. package/js/src/pro/bybit.js +1 -1
  77. package/js/src/pro/coinex.js +1 -1
  78. package/js/src/pro/cryptocom.js +1 -1
  79. package/js/src/pro/deribit.d.ts +5 -0
  80. package/js/src/pro/deribit.js +202 -85
  81. package/js/src/pro/gate.js +1 -1
  82. package/js/src/pro/independentreserve.js +1 -1
  83. package/js/src/pro/kraken.js +1 -1
  84. package/js/src/pro/kucoinfutures.js +1 -1
  85. package/js/src/pro/mexc.js +6 -4
  86. package/js/src/pro/okx.js +1 -1
  87. package/js/src/pro/woo.js +1 -1
  88. package/js/src/wazirx.js +6 -1
  89. package/js/src/woo.d.ts +8 -0
  90. package/js/src/woo.js +159 -79
  91. package/package.json +1 -1
  92. package/skip-tests.json +44 -18
package/dist/cjs/ccxt.js CHANGED
@@ -176,7 +176,7 @@ var woo$1 = require('./src/pro/woo.js');
176
176
 
177
177
  //-----------------------------------------------------------------------------
178
178
  // this is updated by vss.js when building
179
- const version = '4.2.58';
179
+ const version = '4.2.60';
180
180
  Exchange["default"].ccxtVersion = version;
181
181
  const exchanges = {
182
182
  'ace': ace,
@@ -754,11 +754,10 @@ class ascendex extends ascendex$1 {
754
754
  ];
755
755
  }
756
756
  parseBalance(response) {
757
- const timestamp = this.milliseconds();
758
757
  const result = {
759
758
  'info': response,
760
- 'timestamp': timestamp,
761
- 'datetime': this.iso8601(timestamp),
759
+ 'timestamp': undefined,
760
+ 'datetime': undefined,
762
761
  };
763
762
  const balances = this.safeValue(response, 'data', []);
764
763
  for (let i = 0; i < balances.length; i++) {
@@ -772,11 +771,10 @@ class ascendex extends ascendex$1 {
772
771
  return this.safeBalance(result);
773
772
  }
774
773
  parseMarginBalance(response) {
775
- const timestamp = this.milliseconds();
776
774
  const result = {
777
775
  'info': response,
778
- 'timestamp': timestamp,
779
- 'datetime': this.iso8601(timestamp),
776
+ 'timestamp': undefined,
777
+ 'datetime': undefined,
780
778
  };
781
779
  const balances = this.safeValue(response, 'data', []);
782
780
  for (let i = 0; i < balances.length; i++) {
@@ -793,11 +791,10 @@ class ascendex extends ascendex$1 {
793
791
  return this.safeBalance(result);
794
792
  }
795
793
  parseSwapBalance(response) {
796
- const timestamp = this.milliseconds();
797
794
  const result = {
798
795
  'info': response,
799
- 'timestamp': timestamp,
800
- 'datetime': this.iso8601(timestamp),
796
+ 'timestamp': undefined,
797
+ 'datetime': undefined,
801
798
  };
802
799
  const data = this.safeValue(response, 'data', {});
803
800
  const collaterals = this.safeValue(data, 'collaterals', []);
@@ -819,6 +816,8 @@ class ascendex extends ascendex$1 {
819
816
  * @see https://ascendex.github.io/ascendex-pro-api/#margin-account-balance
820
817
  * @see https://ascendex.github.io/ascendex-futures-pro-api-v2/#position
821
818
  * @param {object} [params] extra parameters specific to the exchange API endpoint
819
+ * @param {string} [params.type] wallet type, 'spot', 'margin', or 'swap'
820
+ * @param {string} [params.marginMode] 'cross' or undefined, for spot margin trading, value of 'isolated' is invalid
822
821
  * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
823
822
  */
824
823
  await this.loadMarkets();
@@ -3181,12 +3180,11 @@ class ascendex extends ascendex$1 {
3181
3180
  //
3182
3181
  const status = this.safeInteger(transfer, 'code');
3183
3182
  const currencyCode = this.safeCurrencyCode(undefined, currency);
3184
- const timestamp = this.milliseconds();
3185
3183
  return {
3186
3184
  'info': transfer,
3187
3185
  'id': undefined,
3188
- 'timestamp': timestamp,
3189
- 'datetime': this.iso8601(timestamp),
3186
+ 'timestamp': undefined,
3187
+ 'datetime': undefined,
3190
3188
  'currency': currencyCode,
3191
3189
  'amount': undefined,
3192
3190
  'fromAccount': undefined,
@@ -3895,6 +3895,8 @@ class Exchange {
3895
3895
  params = this.omit(params, [optionName, defaultOptionName]);
3896
3896
  }
3897
3897
  else {
3898
+ // handle routed methods like "watchTrades > watchTradesForSymbols" (or "watchTicker > watchTickers")
3899
+ [methodName, params] = this.handleParamString(params, 'callerMethodName', methodName);
3898
3900
  // check if exchange has properties for this method
3899
3901
  const exchangeWideMethodOptions = this.safeValue(this.options, methodName);
3900
3902
  if (exchangeWideMethodOptions !== undefined) {
@@ -4810,7 +4810,7 @@ class binance extends binance$1 {
4810
4810
  let stopPriceIsRequired = false;
4811
4811
  let quantityIsRequired = false;
4812
4812
  if (uppercaseType === 'MARKET') {
4813
- const quoteOrderQty = this.safeValue(this.options, 'quoteOrderQty', true);
4813
+ const quoteOrderQty = this.safeBool(this.options, 'quoteOrderQty', true);
4814
4814
  if (quoteOrderQty) {
4815
4815
  const quoteOrderQtyNew = this.safeValue2(params, 'quoteOrderQty', 'cost');
4816
4816
  const precision = market['precision']['price'];
@@ -10318,7 +10318,7 @@ class binance extends binance$1 {
10318
10318
  // POST https://fapi.binance.com/fapi/v1/marginType 400 Bad Request
10319
10319
  // binanceusdm
10320
10320
  if (e instanceof errors.MarginModeAlreadySet) {
10321
- const throwMarginModeAlreadySet = this.safeValue(this.options, 'throwMarginModeAlreadySet', false);
10321
+ const throwMarginModeAlreadySet = this.safeBool(this.options, 'throwMarginModeAlreadySet', false);
10322
10322
  if (throwMarginModeAlreadySet) {
10323
10323
  throw e;
10324
10324
  }
@@ -59,6 +59,7 @@ class bingx extends bingx$1 {
59
59
  'fetchFundingRates': true,
60
60
  'fetchLeverage': true,
61
61
  'fetchLiquidations': false,
62
+ 'fetchMarginMode': true,
62
63
  'fetchMarkets': true,
63
64
  'fetchMarkOHLCV': true,
64
65
  'fetchMyLiquidations': true,
@@ -449,7 +450,7 @@ class bingx extends bingx$1 {
449
450
  if (!this.checkRequiredCredentials(false)) {
450
451
  return undefined;
451
452
  }
452
- const isSandbox = this.safeValue(this.options, 'sandboxMode', false);
453
+ const isSandbox = this.safeBool(this.options, 'sandboxMode', false);
453
454
  if (isSandbox) {
454
455
  return undefined;
455
456
  }
@@ -693,7 +694,7 @@ class bingx extends bingx$1 {
693
694
  * @returns {object[]} an array of objects representing market data
694
695
  */
695
696
  const requests = [this.fetchSwapMarkets(params)];
696
- const isSandbox = this.safeValue(this.options, 'sandboxMode', false);
697
+ const isSandbox = this.safeBool(this.options, 'sandboxMode', false);
697
698
  if (!isSandbox) {
698
699
  requests.push(this.fetchSpotMarkets(params)); // sandbox is swap only
699
700
  }
@@ -4166,11 +4167,48 @@ class bingx extends bingx$1 {
4166
4167
  const data = this.safeDict(response, 'data');
4167
4168
  return this.parseOrder(data, market);
4168
4169
  }
4170
+ async fetchMarginMode(symbol, params = {}) {
4171
+ /**
4172
+ * @method
4173
+ * @name bingx#fetchMarginMode
4174
+ * @description fetches the margin mode of the trading pair
4175
+ * @see https://bingx-api.github.io/docs/#/en-us/swapV2/trade-api.html#Query%20Margin%20Mode
4176
+ * @param {string} symbol unified symbol of the market to fetch the margin mode for
4177
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
4178
+ * @returns {object} Struct of MarginMode
4179
+ */
4180
+ await this.loadMarkets();
4181
+ const market = this.market(symbol);
4182
+ const request = {
4183
+ 'symbol': market['id'],
4184
+ };
4185
+ const response = await this.swapV2PrivateGetTradeMarginType(this.extend(request, params));
4186
+ //
4187
+ // {
4188
+ // "code": 0,
4189
+ // "msg": "",
4190
+ // "data": {
4191
+ // "marginType": "CROSSED"
4192
+ // }
4193
+ // }
4194
+ //
4195
+ const data = this.safeDict(response, 'data', {});
4196
+ return this.parseMarginMode(data, market);
4197
+ }
4198
+ parseMarginMode(marginMode, market = undefined) {
4199
+ let marginType = this.safeStringLower(marginMode, 'marginType');
4200
+ marginType = (marginType === 'crossed') ? 'cross' : marginType;
4201
+ return {
4202
+ 'info': marginMode,
4203
+ 'symbol': market['symbol'],
4204
+ 'marginMode': marginType,
4205
+ };
4206
+ }
4169
4207
  sign(path, section = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
4170
4208
  const type = section[0];
4171
4209
  const version = section[1];
4172
4210
  const access = section[2];
4173
- const isSandbox = this.safeValue(this.options, 'sandboxMode', false);
4211
+ const isSandbox = this.safeBool(this.options, 'sandboxMode', false);
4174
4212
  if (isSandbox && (type !== 'swap')) {
4175
4213
  throw new errors.NotSupported(this.id + ' does not have a testnet/sandbox URL for ' + type + ' endpoints');
4176
4214
  }
@@ -27,8 +27,8 @@ class bitfinex2 extends bitfinex2$1 {
27
27
  'spot': true,
28
28
  'margin': true,
29
29
  'swap': true,
30
- 'future': undefined,
31
- 'option': undefined,
30
+ 'future': false,
31
+ 'option': false,
32
32
  'addMargin': false,
33
33
  'borrowCrossMargin': false,
34
34
  'borrowIsolatedMargin': false,
@@ -39,6 +39,7 @@ class bitfinex2 extends bitfinex2$1 {
39
39
  'createLimitOrder': true,
40
40
  'createMarketOrder': true,
41
41
  'createOrder': true,
42
+ 'createPostOnlyOrder': true,
42
43
  'createReduceOnlyOrder': true,
43
44
  'createStopLimitOrder': true,
44
45
  'createStopMarketOrder': true,
@@ -49,8 +50,11 @@ class bitfinex2 extends bitfinex2$1 {
49
50
  'editOrder': true,
50
51
  'fetchBalance': true,
51
52
  'fetchBorrowInterest': false,
52
- 'fetchBorrowRateHistories': false,
53
+ 'fetchBorrowRate': false,
53
54
  'fetchBorrowRateHistory': false,
55
+ 'fetchBorrowRateHistories': false,
56
+ 'fetchBorrowRates': false,
57
+ 'fetchBorrowRatesPerSymbol': false,
54
58
  'fetchClosedOrder': true,
55
59
  'fetchClosedOrders': true,
56
60
  'fetchCrossBorrowRate': false,
@@ -79,6 +83,8 @@ class bitfinex2 extends bitfinex2$1 {
79
83
  'fetchOpenOrder': true,
80
84
  'fetchOpenOrders': true,
81
85
  'fetchOrder': true,
86
+ 'fetchOrderBook': true,
87
+ 'fetchOrderBooks': false,
82
88
  'fetchOrderTrades': true,
83
89
  'fetchPosition': false,
84
90
  'fetchPositionMode': false,
@@ -98,6 +104,8 @@ class bitfinex2 extends bitfinex2$1 {
98
104
  'setMargin': true,
99
105
  'setMarginMode': false,
100
106
  'setPositionMode': false,
107
+ 'signIn': false,
108
+ 'transfer': true,
101
109
  'withdraw': true,
102
110
  },
103
111
  'timeframes': {
@@ -1530,7 +1538,16 @@ class bitfinex2 extends bitfinex2$1 {
1530
1538
  * @param {float} amount how much you want to trade in units of the base currency
1531
1539
  * @param {float} [price] the price of the order, in units of the quote currency, ignored in market orders
1532
1540
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1533
- * @returns {object} request to be sent to the exchange
1541
+ * @param {float} [params.stopPrice] The price at which a trigger order is triggered at
1542
+ * @param {string} [params.timeInForce] "GTC", "IOC", "FOK", or "PO"
1543
+ * @param {bool} [params.postOnly]
1544
+ * @param {bool} [params.reduceOnly] Ensures that the executed order does not flip the opened position.
1545
+ * @param {int} [params.flags] additional order parameters: 4096 (Post Only), 1024 (Reduce Only), 16384 (OCO), 64 (Hidden), 512 (Close), 524288 (No Var Rates)
1546
+ * @param {int} [params.lev] leverage for a derivative order, supported by derivative symbol orders only. The value should be between 1 and 100 inclusive.
1547
+ * @param {string} [params.price_traling] The trailing price for a trailing stop order
1548
+ * @param {string} [params.price_aux_limit] Order price for stop limit orders
1549
+ * @param {string} [params.price_oco_stop] OCO stop price
1550
+ * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1534
1551
  */
1535
1552
  const market = this.market(symbol);
1536
1553
  let amountString = this.amountToPrecision(symbol, amount);
@@ -2928,8 +2928,15 @@ class bitget extends bitget$1 {
2928
2928
  const currencyCode = this.safeCurrencyCode(this.safeString(feeStructure, 'feeCoin'));
2929
2929
  fee = {
2930
2930
  'currency': currencyCode,
2931
- 'cost': Precise["default"].stringAbs(this.safeString(feeStructure, 'totalFee')),
2932
2931
  };
2932
+ const feeCostString = this.safeString(feeStructure, 'totalFee');
2933
+ const deduction = this.safeString(feeStructure, 'deduction') === 'yes' ? true : false;
2934
+ if (deduction) {
2935
+ fee['cost'] = feeCostString;
2936
+ }
2937
+ else {
2938
+ fee['cost'] = Precise["default"].stringNeg(feeCostString);
2939
+ }
2933
2940
  }
2934
2941
  return this.safeTrade({
2935
2942
  'info': trade,
@@ -4028,7 +4035,7 @@ class bitget extends bitget$1 {
4028
4035
  * @see https://www.bitget.com/api-doc/margin/isolated/trade/Isolated-Place-Order
4029
4036
  * @param {string} symbol unified symbol of the market to create an order in
4030
4037
  * @param {string} type 'market' or 'limit'
4031
- * @param {string} side 'buy' or 'sell' or 'open_long' or 'open_short' or 'close_long' or 'close_short'
4038
+ * @param {string} side 'buy' or 'sell'
4032
4039
  * @param {float} amount how much you want to trade in units of the base currency
4033
4040
  * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
4034
4041
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -4513,7 +4520,7 @@ class bitget extends bitget$1 {
4513
4520
  params = this.omit(params, ['stopPrice', 'triggerType', 'stopLossPrice', 'takeProfitPrice', 'stopLoss', 'takeProfit', 'clientOrderId', 'trailingTriggerPrice', 'trailingPercent']);
4514
4521
  let response = undefined;
4515
4522
  if (market['spot']) {
4516
- const editMarketBuyOrderRequiresPrice = this.safeValue(this.options, 'editMarketBuyOrderRequiresPrice', true);
4523
+ const editMarketBuyOrderRequiresPrice = this.safeBool(this.options, 'editMarketBuyOrderRequiresPrice', true);
4517
4524
  if (editMarketBuyOrderRequiresPrice && isMarketOrder && (side === 'buy')) {
4518
4525
  if (price === undefined) {
4519
4526
  throw new errors.InvalidOrder(this.id + ' editOrder() requires price argument for market buy orders on spot markets to calculate the total amount to spend (amount * price), alternatively set the editMarketBuyOrderRequiresPrice option to false and pass in the cost to spend into the amount parameter');
@@ -512,6 +512,7 @@ class bitmart extends bitmart$1 {
512
512
  },
513
513
  'networks': {
514
514
  'ERC20': 'ERC20',
515
+ 'SOL': 'SOL',
515
516
  'BTC': 'BTC',
516
517
  'TRC20': 'TRC20',
517
518
  // todo: should be TRX after unification
@@ -534,7 +535,6 @@ class bitmart extends bitmart$1 {
534
535
  'FIO': 'FIO',
535
536
  'SCRT': 'SCRT',
536
537
  'IOTX': 'IOTX',
537
- 'SOL': 'SOL',
538
538
  'ALGO': 'ALGO',
539
539
  'ATOM': 'ATOM',
540
540
  'DOT': 'DOT',
@@ -3087,6 +3087,7 @@ class bitmart extends bitmart$1 {
3087
3087
  * @method
3088
3088
  * @name bitmart#fetchDepositAddress
3089
3089
  * @description fetch the deposit address for a currency associated with this account
3090
+ * @see https://developer-pro.bitmart.com/en/spot/#deposit-address-keyed
3090
3091
  * @param {string} code unified currency code
3091
3092
  * @param {object} [params] extra parameters specific to the exchange API endpoint
3092
3093
  * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
@@ -3109,40 +3110,57 @@ class bitmart extends bitmart$1 {
3109
3110
  }
3110
3111
  const response = await this.privateGetAccountV1DepositAddress(this.extend(request, params));
3111
3112
  //
3112
- // {
3113
- // "message":"OK",
3114
- // "code":1000,
3115
- // "trace":"0e6edd79-f77f-4251-abe5-83ba75d06c1a",
3116
- // "data":{
3117
- // "currency":"USDT-TRC20",
3118
- // "chain":"USDT-TRC20",
3119
- // "address":"TGR3ghy2b5VLbyAYrmiE15jasR6aPHTvC5",
3120
- // "address_memo":""
3121
- // }
3122
- // }
3113
+ // {
3114
+ // "message": "OK",
3115
+ // "code": 1000,
3116
+ // "trace": "0e6edd79-f77f-4251-abe5-83ba75d06c1a",
3117
+ // "data": {
3118
+ // currency: 'ETH',
3119
+ // chain: 'Ethereum',
3120
+ // address: '0x99B5EEc2C520f86F0F62F05820d28D05D36EccCf',
3121
+ // address_memo: ''
3122
+ // }
3123
+ // }
3123
3124
  //
3124
3125
  const data = this.safeValue(response, 'data', {});
3125
- const address = this.safeString(data, 'address');
3126
- const tag = this.safeString(data, 'address_memo');
3127
- const chain = this.safeString(data, 'chain');
3126
+ return this.parseDepositAddress(data, currency);
3127
+ }
3128
+ parseDepositAddress(depositAddress, currency = undefined) {
3129
+ //
3130
+ // {
3131
+ // currency: 'ETH',
3132
+ // chain: 'Ethereum',
3133
+ // address: '0x99B5EEc2C520f86F0F62F05820d28D05D36EccCf',
3134
+ // address_memo: ''
3135
+ // }
3136
+ //
3137
+ const currencyId = this.safeString(depositAddress, 'currency');
3138
+ const address = this.safeString(depositAddress, 'address');
3139
+ const chain = this.safeString(depositAddress, 'chain');
3128
3140
  let network = undefined;
3141
+ currency = this.safeCurrency(currencyId, currency);
3129
3142
  if (chain !== undefined) {
3130
3143
  const parts = chain.split('-');
3131
- const networkId = this.safeString(parts, 1);
3132
- network = this.safeNetwork(networkId);
3144
+ const partsLength = parts.length;
3145
+ const networkId = this.safeString(parts, partsLength - 1);
3146
+ network = this.safeNetworkCode(networkId, currency);
3133
3147
  }
3134
3148
  this.checkAddress(address);
3135
3149
  return {
3136
- 'currency': code,
3150
+ 'info': depositAddress,
3151
+ 'currency': this.safeString(currency, 'code'),
3137
3152
  'address': address,
3138
- 'tag': tag,
3153
+ 'tag': this.safeString(depositAddress, 'address_memo'),
3139
3154
  'network': network,
3140
- 'info': response,
3141
3155
  };
3142
3156
  }
3143
- safeNetwork(networkId) {
3144
- // TODO: parse
3145
- return networkId;
3157
+ safeNetworkCode(networkId, currency = undefined) {
3158
+ const name = this.safeString(currency, 'name');
3159
+ if (networkId === name) {
3160
+ const code = this.safeString(currency, 'code');
3161
+ return code;
3162
+ }
3163
+ return this.networkIdToCode(networkId);
3146
3164
  }
3147
3165
  async withdraw(code, amount, address, tag = undefined, params = {}) {
3148
3166
  /**
@@ -1507,7 +1507,7 @@ class bitmex extends bitmex$1 {
1507
1507
  request['endTime'] = this.iso8601(until);
1508
1508
  }
1509
1509
  const duration = this.parseTimeframe(timeframe) * 1000;
1510
- const fetchOHLCVOpenTimestamp = this.safeValue(this.options, 'fetchOHLCVOpenTimestamp', true);
1510
+ const fetchOHLCVOpenTimestamp = this.safeBool(this.options, 'fetchOHLCVOpenTimestamp', true);
1511
1511
  // if since is not set, they will return candles starting from 2017-01-01
1512
1512
  if (since !== undefined) {
1513
1513
  let timestamp = since;
@@ -80,6 +80,7 @@ class blofin extends blofin$1 {
80
80
  'fetchLedger': true,
81
81
  'fetchLedgerEntry': undefined,
82
82
  'fetchLeverage': true,
83
+ 'fetchLeverages': true,
83
84
  'fetchLeverageTiers': false,
84
85
  'fetchMarketLeverageTiers': false,
85
86
  'fetchMarkets': true,
@@ -184,6 +185,7 @@ class blofin extends blofin$1 {
184
185
  'account/balance': 1,
185
186
  'account/positions': 1,
186
187
  'account/leverage-info': 1,
188
+ 'account/batch-leverage-info': 1,
187
189
  'trade/orders-tpsl-pending': 1,
188
190
  'trade/orders-history': 1,
189
191
  'trade/orders-tpsl-history': 1,
@@ -488,7 +490,7 @@ class blofin extends blofin$1 {
488
490
  const symbol = market['symbol'];
489
491
  const last = this.safeString(ticker, 'last');
490
492
  const open = this.safeString(ticker, 'open24h');
491
- const spot = this.safeValue(market, 'spot', false);
493
+ const spot = this.safeBool(market, 'spot', false);
492
494
  const quoteVolume = spot ? this.safeString(ticker, 'volCurrency24h') : undefined;
493
495
  const baseVolume = this.safeString(ticker, 'vol24h');
494
496
  const high = this.safeString(ticker, 'high24h');
@@ -1881,12 +1883,68 @@ class blofin extends blofin$1 {
1881
1883
  'takeProfitPrice': undefined,
1882
1884
  });
1883
1885
  }
1886
+ async fetchLeverages(symbols = undefined, params = {}) {
1887
+ /**
1888
+ * @method
1889
+ * @name blofin#fetchLeverages
1890
+ * @description fetch the set leverage for all contract markets
1891
+ * @see https://docs.blofin.com/index.html#get-multiple-leverage
1892
+ * @param {string[]} symbols a list of unified market symbols, required on blofin
1893
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1894
+ * @param {string} [params.marginMode] 'cross' or 'isolated'
1895
+ * @returns {object} a list of [leverage structures]{@link https://docs.ccxt.com/#/?id=leverage-structure}
1896
+ */
1897
+ await this.loadMarkets();
1898
+ if (symbols === undefined) {
1899
+ throw new errors.ArgumentsRequired(this.id + ' fetchLeverages() requires a symbols argument');
1900
+ }
1901
+ let marginMode = undefined;
1902
+ [marginMode, params] = this.handleMarginModeAndParams('fetchLeverages', params);
1903
+ if (marginMode === undefined) {
1904
+ marginMode = this.safeString(params, 'marginMode', 'cross'); // cross as default marginMode
1905
+ }
1906
+ if ((marginMode !== 'cross') && (marginMode !== 'isolated')) {
1907
+ throw new errors.BadRequest(this.id + ' fetchLeverages() requires a marginMode parameter that must be either cross or isolated');
1908
+ }
1909
+ symbols = this.marketSymbols(symbols);
1910
+ let instIds = '';
1911
+ for (let i = 0; i < symbols.length; i++) {
1912
+ const entry = symbols[i];
1913
+ const entryMarket = this.market(entry);
1914
+ if (i > 0) {
1915
+ instIds = instIds + ',' + entryMarket['id'];
1916
+ }
1917
+ else {
1918
+ instIds = instIds + entryMarket['id'];
1919
+ }
1920
+ }
1921
+ const request = {
1922
+ 'instId': instIds,
1923
+ 'marginMode': marginMode,
1924
+ };
1925
+ const response = await this.privateGetAccountBatchLeverageInfo(this.extend(request, params));
1926
+ //
1927
+ // {
1928
+ // "code": "0",
1929
+ // "msg": "success",
1930
+ // "data": [
1931
+ // {
1932
+ // "leverage": "3",
1933
+ // "marginMode": "cross",
1934
+ // "instId": "BTC-USDT"
1935
+ // },
1936
+ // ]
1937
+ // }
1938
+ //
1939
+ const leverages = this.safeList(response, 'data', []);
1940
+ return this.parseLeverages(leverages, symbols, 'instId');
1941
+ }
1884
1942
  async fetchLeverage(symbol, params = {}) {
1885
1943
  /**
1886
1944
  * @method
1887
1945
  * @name blofin#fetchLeverage
1888
1946
  * @description fetch the set leverage for a market
1889
- * @see https://blofin.com/docs#set-leverage
1947
+ * @see https://docs.blofin.com/index.html#get-leverage
1890
1948
  * @param {string} symbol unified market symbol
1891
1949
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1892
1950
  * @param {string} [params.marginMode] 'cross' or 'isolated'
@@ -3065,10 +3065,12 @@ class coinbase extends coinbase$1 {
3065
3065
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
3066
3066
  */
3067
3067
  await this.loadMarkets();
3068
+ const maxLimit = 300;
3069
+ limit = (limit === undefined) ? maxLimit : Math.min(limit, maxLimit);
3068
3070
  let paginate = false;
3069
3071
  [paginate, params] = this.handleOptionAndParams(params, 'fetchOHLCV', 'paginate', false);
3070
3072
  if (paginate) {
3071
- return await this.fetchPaginatedCallDeterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 299);
3073
+ return await this.fetchPaginatedCallDeterministic('fetchOHLCV', symbol, since, limit, timeframe, params, maxLimit - 1);
3072
3074
  }
3073
3075
  const market = this.market(symbol);
3074
3076
  const request = {
@@ -3078,20 +3080,20 @@ class coinbase extends coinbase$1 {
3078
3080
  const until = this.safeValueN(params, ['until', 'till', 'end']);
3079
3081
  params = this.omit(params, ['until', 'till']);
3080
3082
  const duration = this.parseTimeframe(timeframe);
3081
- const candles300 = 300 * duration;
3083
+ const requestedDuration = limit * duration;
3082
3084
  let sinceString = undefined;
3083
3085
  if (since !== undefined) {
3084
3086
  sinceString = this.numberToString(this.parseToInt(since / 1000));
3085
3087
  }
3086
3088
  else {
3087
3089
  const now = this.seconds().toString();
3088
- sinceString = Precise["default"].stringSub(now, candles300.toString());
3090
+ sinceString = Precise["default"].stringSub(now, requestedDuration.toString());
3089
3091
  }
3090
3092
  request['start'] = sinceString;
3091
3093
  let endString = this.numberToString(until);
3092
3094
  if (until === undefined) {
3093
3095
  // 300 candles max
3094
- endString = Precise["default"].stringAdd(sinceString, candles300.toString());
3096
+ endString = Precise["default"].stringAdd(sinceString, requestedDuration.toString());
3095
3097
  }
3096
3098
  request['end'] = endString;
3097
3099
  const response = await this.v3PrivateGetBrokerageProductsProductIdCandles(this.extend(request, params));
@@ -3151,8 +3153,19 @@ class coinbase extends coinbase$1 {
3151
3153
  const request = {
3152
3154
  'product_id': market['id'],
3153
3155
  };
3156
+ if (since !== undefined) {
3157
+ request['start'] = this.numberToString(this.parseToInt(since / 1000));
3158
+ }
3154
3159
  if (limit !== undefined) {
3155
- request['limit'] = limit;
3160
+ request['limit'] = Math.min(limit, 1000);
3161
+ }
3162
+ let until = undefined;
3163
+ [until, params] = this.handleOptionAndParams(params, 'fetchTrades', 'until');
3164
+ if (until !== undefined) {
3165
+ request['end'] = this.numberToString(this.parseToInt(until / 1000));
3166
+ }
3167
+ else if (since !== undefined) {
3168
+ throw new errors.ArgumentsRequired(this.id + ' fetchTrades() requires a `until` parameter when you use `since` argument');
3156
3169
  }
3157
3170
  const response = await this.v3PrivateGetBrokerageProductsProductIdTicker(this.extend(request, params));
3158
3171
  //
@@ -3286,7 +3299,7 @@ class coinbase extends coinbase$1 {
3286
3299
  // }
3287
3300
  // }
3288
3301
  //
3289
- const data = this.safeValue(response, 'pricebook', {});
3302
+ const data = this.safeDict(response, 'pricebook', {});
3290
3303
  const time = this.safeString(data, 'time');
3291
3304
  const timestamp = this.parse8601(time);
3292
3305
  return this.parseOrderBook(data, symbol, timestamp, 'bids', 'asks', 'price', 'size');
@@ -3739,7 +3752,7 @@ class coinbase extends coinbase$1 {
3739
3752
  }
3740
3753
  else {
3741
3754
  this.checkRequiredCredentials();
3742
- const nonce = this.nonce().toString();
3755
+ const timestampString = this.seconds().toString();
3743
3756
  let payload = '';
3744
3757
  if (method !== 'GET') {
3745
3758
  if (Object.keys(query).length) {
@@ -3747,17 +3760,14 @@ class coinbase extends coinbase$1 {
3747
3760
  payload = body;
3748
3761
  }
3749
3762
  }
3750
- else {
3751
- if (Object.keys(query).length) {
3752
- payload += '?' + this.urlencode(query);
3753
- }
3754
- }
3755
- const auth = nonce + method + savedPath + payload;
3763
+ // 'GET' doesn't need payload in the signature. inside url is enough
3764
+ // https://docs.cloud.coinbase.com/advanced-trade-api/docs/auth#example-request
3765
+ const auth = timestampString + method + savedPath + payload;
3756
3766
  const signature = this.hmac(this.encode(auth), this.encode(this.secret), sha256.sha256);
3757
3767
  headers = {
3758
3768
  'CB-ACCESS-KEY': this.apiKey,
3759
3769
  'CB-ACCESS-SIGN': signature,
3760
- 'CB-ACCESS-TIMESTAMP': nonce,
3770
+ 'CB-ACCESS-TIMESTAMP': timestampString,
3761
3771
  'Content-Type': 'application/json',
3762
3772
  };
3763
3773
  }
@@ -2699,7 +2699,7 @@ class hitbtc extends hitbtc$1 {
2699
2699
  if ((network !== undefined) && (code === 'USDT')) {
2700
2700
  const parsedNetwork = this.safeString(networks, network);
2701
2701
  if (parsedNetwork !== undefined) {
2702
- request['currency'] = parsedNetwork;
2702
+ request['network_code'] = parsedNetwork;
2703
2703
  }
2704
2704
  params = this.omit(params, 'network');
2705
2705
  }
@@ -2591,7 +2591,10 @@ class htx extends htx$1 {
2591
2591
  amountString = this.safeString(trade, 'trade_volume', amountString);
2592
2592
  const costString = this.safeString(trade, 'trade_turnover');
2593
2593
  let fee = undefined;
2594
- let feeCost = this.safeString2(trade, 'filled-fees', 'trade_fee');
2594
+ let feeCost = this.safeString(trade, 'filled-fees');
2595
+ if (feeCost === undefined) {
2596
+ feeCost = Precise["default"].stringNeg(this.safeString(trade, 'trade_fee'));
2597
+ }
2595
2598
  const feeCurrencyId = this.safeString2(trade, 'fee-currency', 'fee_asset');
2596
2599
  let feeCurrency = this.safeCurrencyCode(feeCurrencyId);
2597
2600
  const filledPoints = this.safeString(trade, 'filled-points');