ccxt 4.3.77 → 4.3.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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.3.77';
197
+ const version = '4.3.78';
198
198
  Exchange["default"].ccxtVersion = version;
199
199
  const exchanges = {
200
200
  'ace': ace,
@@ -2987,48 +2987,61 @@ class Exchange {
2987
2987
  }
2988
2988
  cost = Precise["default"].stringMul(multiplyPrice, amount);
2989
2989
  }
2990
- const parseFee = this.safeValue(trade, 'fee') === undefined;
2991
- const parseFees = this.safeValue(trade, 'fees') === undefined;
2992
- const shouldParseFees = parseFee || parseFees;
2993
- const fees = [];
2994
- const fee = this.safeValue(trade, 'fee');
2990
+ const [resultFee, resultFees] = this.parsedFeeAndFees(trade);
2991
+ trade['fee'] = resultFee;
2992
+ trade['fees'] = resultFees;
2993
+ trade['amount'] = this.parseNumber(amount);
2994
+ trade['price'] = this.parseNumber(price);
2995
+ trade['cost'] = this.parseNumber(cost);
2996
+ return trade;
2997
+ }
2998
+ parsedFeeAndFees(container) {
2999
+ let fee = this.safeDict(container, 'fee');
3000
+ let fees = this.safeList(container, 'fees');
3001
+ const feeDefined = fee !== undefined;
3002
+ const feesDefined = fees !== undefined;
3003
+ // parsing only if at least one of them is defined
3004
+ const shouldParseFees = (feeDefined || feesDefined);
2995
3005
  if (shouldParseFees) {
3006
+ if (feeDefined) {
3007
+ fee = this.parseFeeNumeric(fee);
3008
+ }
3009
+ if (!feesDefined) {
3010
+ // just set it directly, no further processing needed
3011
+ fees = [fee];
3012
+ }
3013
+ // 'fees' were set, so reparse them
2996
3014
  const reducedFees = this.reduceFees ? this.reduceFeesByCurrency(fees) : fees;
2997
3015
  const reducedLength = reducedFees.length;
2998
3016
  for (let i = 0; i < reducedLength; i++) {
2999
- reducedFees[i]['cost'] = this.safeNumber(reducedFees[i], 'cost');
3000
- if ('rate' in reducedFees[i]) {
3001
- reducedFees[i]['rate'] = this.safeNumber(reducedFees[i], 'rate');
3002
- }
3017
+ reducedFees[i] = this.parseFeeNumeric(reducedFees[i]);
3003
3018
  }
3004
- if (!parseFee && (reducedLength === 0)) {
3005
- // copy fee to avoid modification by reference
3006
- const feeCopy = this.deepExtend(fee);
3007
- feeCopy['cost'] = this.safeNumber(feeCopy, 'cost');
3008
- if ('rate' in feeCopy) {
3009
- feeCopy['rate'] = this.safeNumber(feeCopy, 'rate');
3010
- }
3011
- reducedFees.push(feeCopy);
3012
- }
3013
- if (parseFees) {
3014
- trade['fees'] = reducedFees;
3019
+ fees = reducedFees;
3020
+ if (reducedLength === 1) {
3021
+ fee = reducedFees[0];
3015
3022
  }
3016
- if (parseFee && (reducedLength === 1)) {
3017
- trade['fee'] = reducedFees[0];
3018
- }
3019
- const tradeFee = this.safeValue(trade, 'fee');
3020
- if (tradeFee !== undefined) {
3021
- tradeFee['cost'] = this.safeNumber(tradeFee, 'cost');
3022
- if ('rate' in tradeFee) {
3023
- tradeFee['rate'] = this.safeNumber(tradeFee, 'rate');
3024
- }
3025
- trade['fee'] = tradeFee;
3023
+ else if (reducedLength === 0) {
3024
+ fee = undefined;
3026
3025
  }
3027
3026
  }
3028
- trade['amount'] = this.parseNumber(amount);
3029
- trade['price'] = this.parseNumber(price);
3030
- trade['cost'] = this.parseNumber(cost);
3031
- return trade;
3027
+ // in case `fee & fees` are undefined, set `fees` as empty array
3028
+ if (fee === undefined) {
3029
+ fee = {
3030
+ 'cost': undefined,
3031
+ 'currency': undefined,
3032
+ };
3033
+ }
3034
+ if (fees === undefined) {
3035
+ fees = [];
3036
+ }
3037
+ return [fee, fees];
3038
+ }
3039
+ parseFeeNumeric(fee) {
3040
+ fee['cost'] = this.safeNumber(fee, 'cost'); // ensure numeric
3041
+ if ('rate' in fee) {
3042
+ fee['rate'] = this.safeNumber(fee, 'rate');
3043
+ }
3044
+ return fee;
3032
3045
  }
3033
3046
  findNearestCeiling(arr, providedValue) {
3034
3047
  // i.e. findNearestCeiling ([ 10, 30, 50], 23) returns 30
@@ -3102,12 +3115,13 @@ class Exchange {
3102
3115
  const reduced = {};
3103
3116
  for (let i = 0; i < fees.length; i++) {
3104
3117
  const fee = fees[i];
3105
- const feeCurrencyCode = this.safeString(fee, 'currency');
3118
+ const code = this.safeString(fee, 'currency');
3119
+ const feeCurrencyCode = code !== undefined ? code : i.toString();
3106
3120
  if (feeCurrencyCode !== undefined) {
3107
3121
  const rate = this.safeString(fee, 'rate');
3108
- const cost = this.safeValue(fee, 'cost');
3109
- if (Precise["default"].stringEq(cost, '0')) {
3110
- // omit zero cost fees
3122
+ const cost = this.safeString(fee, 'cost');
3123
+ if (cost === undefined) {
3124
+ // omit undefined cost, as it does not make sense, however, don't omit '0' costs, as they still make sense
3111
3125
  continue;
3112
3126
  }
3113
3127
  if (!(feeCurrencyCode in reduced)) {
@@ -3119,7 +3133,7 @@ class Exchange {
3119
3133
  }
3120
3134
  else {
3121
3135
  reduced[feeCurrencyCode][rateKey] = {
3122
- 'currency': feeCurrencyCode,
3136
+ 'currency': code,
3123
3137
  'cost': cost,
3124
3138
  };
3125
3139
  if (rate !== undefined) {
@@ -3160,7 +3174,15 @@ class Exchange {
3160
3174
  change = Precise["default"].stringSub(last, open);
3161
3175
  }
3162
3176
  if (average === undefined) {
3163
- average = Precise["default"].stringDiv(Precise["default"].stringAdd(last, open), '2');
3177
+ let precision = 18;
3178
+ if (market !== undefined && this.isTickPrecision()) {
3179
+ const marketPrecision = this.safeDict(market, 'precision');
3180
+ const precisionPrice = this.safeString(marketPrecision, 'price');
3181
+ if (precisionPrice !== undefined) {
3182
+ precision = this.precisionFromString(precisionPrice);
3183
+ }
3184
+ }
3185
+ average = Precise["default"].stringDiv(Precise["default"].stringAdd(last, open), '2', precision);
3164
3186
  }
3165
3187
  }
3166
3188
  if ((percentage === undefined) && (change !== undefined) && (open !== undefined) && Precise["default"].stringGt(open, '0')) {
@@ -1209,7 +1209,6 @@ class bingx extends bingx$1 {
1209
1209
  'fee': {
1210
1210
  'cost': this.parseNumber(Precise["default"].stringAbs(this.safeString2(trade, 'commission', 'n'))),
1211
1211
  'currency': currencyCode,
1212
- 'rate': undefined,
1213
1212
  },
1214
1213
  }, market);
1215
1214
  }
@@ -1309,6 +1309,7 @@ class bitget extends bitget$1 {
1309
1309
  'JADE': 'Jade Protocol',
1310
1310
  'DEGEN': 'DegenReborn',
1311
1311
  'TONCOIN': 'TON',
1312
+ 'OMNI': 'omni', // conflict with Omni Network
1312
1313
  },
1313
1314
  'options': {
1314
1315
  'timeframes': {
@@ -1937,7 +1937,6 @@ class bitteam extends bitteam$1 {
1937
1937
  const fee = {
1938
1938
  'currency': this.safeCurrencyCode(feeCurrencyId),
1939
1939
  'cost': feeCost,
1940
- 'rate': undefined,
1941
1940
  };
1942
1941
  const intTs = this.parseToInt(timestamp);
1943
1942
  return this.safeTrade({
@@ -3467,8 +3467,8 @@ class gate extends gate$1 {
3467
3467
  const side = this.safeString2(trade, 'side', 'type', contractSide);
3468
3468
  const orderId = this.safeString(trade, 'order_id');
3469
3469
  const feeAmount = this.safeString(trade, 'fee');
3470
- const gtFee = this.safeString(trade, 'gt_fee');
3471
- const pointFee = this.safeString(trade, 'point_fee');
3470
+ const gtFee = this.omitZero(this.safeString(trade, 'gt_fee'));
3471
+ const pointFee = this.omitZero(this.safeString(trade, 'point_fee'));
3472
3472
  const fees = [];
3473
3473
  if (feeAmount !== undefined) {
3474
3474
  const feeCurrencyId = this.safeString(trade, 'fee_currency');
@@ -1382,7 +1382,7 @@ class kraken extends kraken$1 {
1382
1382
  * @method
1383
1383
  * @name kraken#createMarketOrderWithCost
1384
1384
  * @description create a market order by providing the symbol, side and cost
1385
- * @see https://docs.kraken.com/rest/#tag/Trading/operation/addOrder
1385
+ * @see https://docs.kraken.com/rest/#tag/Spot-Trading/operation/addOrder
1386
1386
  * @param {string} symbol unified symbol of the market to create an order in (only USD markets are supported)
1387
1387
  * @param {string} side 'buy' or 'sell'
1388
1388
  * @param {float} cost how much you want to trade in units of the quote currency
@@ -1399,7 +1399,7 @@ class kraken extends kraken$1 {
1399
1399
  * @method
1400
1400
  * @name kraken#createMarketBuyOrderWithCost
1401
1401
  * @description create a market buy order by providing the symbol, side and cost
1402
- * @see https://docs.kraken.com/rest/#tag/Trading/operation/addOrder
1402
+ * @see https://docs.kraken.com/rest/#tag/Spot-Trading/operation/addOrder
1403
1403
  * @param {string} symbol unified symbol of the market to create an order in
1404
1404
  * @param {float} cost how much you want to trade in units of the quote currency
1405
1405
  * @param {object} [params] extra parameters specific to the exchange API endpoint
@@ -1412,7 +1412,7 @@ class kraken extends kraken$1 {
1412
1412
  /**
1413
1413
  * @method
1414
1414
  * @name kraken#createOrder
1415
- * @see https://docs.kraken.com/rest/#tag/Trading/operation/addOrder
1415
+ * @see https://docs.kraken.com/rest/#tag/Spot-Trading/operation/addOrder
1416
1416
  * @description create a trade order
1417
1417
  * @param {string} symbol unified symbol of the market to create an order in
1418
1418
  * @param {string} type 'market' or 'limit'
@@ -1551,6 +1551,8 @@ class kraken extends kraken$1 {
1551
1551
  // "status": "ok",
1552
1552
  // "txid": "OAW2BO-7RWEK-PZY5UO",
1553
1553
  // "originaltxid": "OXL6SS-UPNMC-26WBE7",
1554
+ // "newuserref": 1234,
1555
+ // "olduserref": 123,
1554
1556
  // "volume": "0.00075000",
1555
1557
  // "price": "13500.0",
1556
1558
  // "orders_cancelled": 1,
@@ -1694,7 +1696,7 @@ class kraken extends kraken$1 {
1694
1696
  const txid = this.safeList(order, 'txid');
1695
1697
  id = this.safeString(txid, 0);
1696
1698
  }
1697
- const clientOrderId = this.safeString(order, 'userref');
1699
+ const clientOrderId = this.safeString2(order, 'userref', 'newuserref');
1698
1700
  const rawTrades = this.safeValue(order, 'trades', []);
1699
1701
  const trades = [];
1700
1702
  for (let i = 0; i < rawTrades.length; i++) {
@@ -1850,7 +1852,7 @@ class kraken extends kraken$1 {
1850
1852
  const extendedPostFlags = (flags !== undefined) ? flags + ',post' : 'post';
1851
1853
  request['oflags'] = extendedPostFlags;
1852
1854
  }
1853
- if ((flags !== undefined) && (request['oflags'] === undefined)) {
1855
+ if ((flags !== undefined) && !('oflags' in request)) {
1854
1856
  request['oflags'] = flags;
1855
1857
  }
1856
1858
  params = this.omit(params, ['timeInForce', 'reduceOnly', 'stopLossPrice', 'takeProfitPrice', 'trailingAmount', 'trailingLimitAmount', 'offset']);
@@ -1861,7 +1863,7 @@ class kraken extends kraken$1 {
1861
1863
  * @method
1862
1864
  * @name kraken#editOrder
1863
1865
  * @description edit a trade order
1864
- * @see https://docs.kraken.com/rest/#tag/Trading/operation/editOrder
1866
+ * @see https://docs.kraken.com/rest/#tag/Spot-Trading/operation/editOrder
1865
1867
  * @param {string} id order id
1866
1868
  * @param {string} symbol unified symbol of the market to create an order in
1867
1869
  * @param {string} type 'market' or 'limit'
@@ -1923,8 +1925,8 @@ class kraken extends kraken$1 {
1923
1925
  await this.loadMarkets();
1924
1926
  const clientOrderId = this.safeValue2(params, 'userref', 'clientOrderId');
1925
1927
  const request = {
1926
- 'trades': true, // whether or not to include trades in output (optional, default false)
1927
- // 'txid': id, // do not comma separate a list of ids - use fetchOrdersByIds instead
1928
+ 'trades': true,
1929
+ 'txid': id, // do not comma separate a list of ids - use fetchOrdersByIds instead
1928
1930
  // 'userref': 'optional', // restrict results to given user reference id (optional)
1929
1931
  };
1930
1932
  let query = params;
@@ -1932,9 +1934,6 @@ class kraken extends kraken$1 {
1932
1934
  request['userref'] = clientOrderId;
1933
1935
  query = this.omit(params, ['userref', 'clientOrderId']);
1934
1936
  }
1935
- else {
1936
- request['txid'] = id;
1937
- }
1938
1937
  const response = await this.privatePostQueryOrders(this.extend(request, query));
1939
1938
  //
1940
1939
  // {
@@ -885,7 +885,6 @@ class kuna extends kuna$1 {
885
885
  'fee': {
886
886
  'cost': this.safeString(trade, 'fee'),
887
887
  'currency': this.safeCurrencyCode(this.safeString(trade, 'feeCurrency')),
888
- 'rate': undefined,
889
888
  },
890
889
  }, market);
891
890
  }
@@ -203,7 +203,7 @@ class binance extends binance$1 {
203
203
  * @param {object} [params] exchange specific parameters for the bitmex api endpoint
204
204
  * @returns {object} an array of [liquidation structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure}
205
205
  */
206
- return this.watchLiquidationsForSymbols([symbol], since, limit, params);
206
+ return await this.watchLiquidationsForSymbols([symbol], since, limit, params);
207
207
  }
208
208
  async watchLiquidationsForSymbols(symbols = undefined, since = undefined, limit = undefined, params = {}) {
209
209
  /**
@@ -114,6 +114,7 @@ class paradex extends paradex$1 {
114
114
  * @param {object} [params] extra parameters specific to the exchange API endpoint
115
115
  * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols
116
116
  */
117
+ await this.loadMarkets();
117
118
  const market = this.market(symbol);
118
119
  const messageHash = 'order_book.' + market['id'] + '.snapshot@15@100ms';
119
120
  const url = this.urls['api']['ws'];
@@ -223,6 +224,7 @@ class paradex extends paradex$1 {
223
224
  * @param {object} [params] extra parameters specific to the exchange API endpoint
224
225
  * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
225
226
  */
227
+ await this.loadMarkets();
226
228
  symbols = this.marketSymbols(symbols);
227
229
  const channel = 'markets_summary';
228
230
  const url = this.urls['api']['ws'];
@@ -665,6 +665,13 @@ class vertex extends vertex$1 {
665
665
  let amount = undefined;
666
666
  let side = undefined;
667
667
  let fee = undefined;
668
+ const feeCost = this.convertFromX18(this.safeString(trade, 'fee'));
669
+ if (feeCost !== undefined) {
670
+ fee = {
671
+ 'cost': feeCost,
672
+ 'currency': undefined,
673
+ };
674
+ }
668
675
  const id = this.safeString2(trade, 'trade_id', 'submission_idx');
669
676
  const order = this.safeString(trade, 'digest');
670
677
  const timestamp = this.safeTimestamp(trade, 'timestamp');
@@ -682,10 +689,6 @@ class vertex extends vertex$1 {
682
689
  const subOrder = this.safeDict(trade, 'order', {});
683
690
  price = this.convertFromX18(this.safeString(subOrder, 'priceX18'));
684
691
  amount = this.convertFromX18(this.safeString(trade, 'base_filled'));
685
- fee = {
686
- 'cost': this.convertFromX18(this.safeString(trade, 'fee')),
687
- 'currency': undefined,
688
- };
689
692
  if (Precise["default"].stringLt(amount, '0')) {
690
693
  side = 'sell';
691
694
  }
@@ -607,6 +607,10 @@ class woo extends woo$1 {
607
607
  const amount = this.safeString(trade, 'executed_quantity');
608
608
  const order_id = this.safeString(trade, 'order_id');
609
609
  const fee = this.parseTokenAndFeeTemp(trade, 'fee_asset', 'fee');
610
+ const feeCost = this.safeString(fee, 'cost');
611
+ if (feeCost !== undefined) {
612
+ fee['cost'] = feeCost;
613
+ }
610
614
  const cost = Precise["default"].stringMul(price, amount);
611
615
  const side = this.safeStringLower(trade, 'side');
612
616
  const id = this.safeString(trade, 'id');
@@ -680,6 +680,10 @@ class woofipro extends woofipro$1 {
680
680
  const amount = this.safeString(trade, 'executed_quantity');
681
681
  const order_id = this.safeString(trade, 'order_id');
682
682
  const fee = this.parseTokenAndFeeTemp(trade, 'fee_asset', 'fee');
683
+ const feeCost = this.safeString(fee, 'cost');
684
+ if (feeCost !== undefined) {
685
+ fee['cost'] = feeCost;
686
+ }
683
687
  const cost = Precise["default"].stringMul(price, amount);
684
688
  const side = this.safeStringLower(trade, 'side');
685
689
  const id = this.safeString(trade, 'id');
@@ -2106,7 +2106,6 @@ class xt extends xt$1 {
2106
2106
  'fee': {
2107
2107
  'currency': this.safeCurrencyCode(this.safeString2(trade, 'feeCurrency', 'feeCoin')),
2108
2108
  'cost': this.safeString(trade, 'fee'),
2109
- 'rate': undefined,
2110
2109
  },
2111
2110
  }, market);
2112
2111
  }
package/js/ccxt.d.ts CHANGED
@@ -4,7 +4,7 @@ import * as functions from './src/base/functions.js';
4
4
  import * as errors from './src/base/errors.js';
5
5
  import type { Int, int, Str, Strings, Num, Bool, IndexType, OrderSide, OrderType, MarketType, SubType, Dict, NullableDict, List, NullableList, Fee, OHLCV, OHLCVC, implicitReturnType, Market, Currency, Dictionary, MinMax, FeeInterface, TradingFeeInterface, MarketInterface, Trade, Order, OrderBook, Ticker, Transaction, Tickers, CurrencyInterface, Balance, BalanceAccount, Account, PartialBalances, Balances, DepositAddress, WithdrawalResponse, DepositAddressResponse, FundingRate, FundingRates, Position, BorrowInterest, LeverageTier, LedgerEntry, DepositWithdrawFeeNetwork, DepositWithdrawFee, TransferEntry, CrossBorrowRate, IsolatedBorrowRate, FundingRateHistory, OpenInterest, Liquidation, OrderRequest, CancellationRequest, FundingHistory, MarginMode, Greeks, Conversion, Option, LastPrice, Leverage, MarginModification, Leverages, LastPrices, Currencies, TradingFees, MarginModes, OptionChain, IsolatedBorrowRates, CrossBorrowRates, LeverageTiers } from './src/base/types.js';
6
6
  import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, 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 } from './src/base/errors.js';
7
- declare const version = "4.3.76";
7
+ declare const version = "4.3.77";
8
8
  import ace from './src/ace.js';
9
9
  import alpaca from './src/alpaca.js';
10
10
  import ascendex from './src/ascendex.js';
package/js/ccxt.js CHANGED
@@ -38,7 +38,7 @@ import * as errors from './src/base/errors.js';
38
38
  import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, 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 } from './src/base/errors.js';
39
39
  //-----------------------------------------------------------------------------
40
40
  // this is updated by vss.js when building
41
- const version = '4.3.77';
41
+ const version = '4.3.78';
42
42
  Exchange.ccxtVersion = version;
43
43
  //-----------------------------------------------------------------------------
44
44
  import ace from './src/ace.js';
@@ -844,6 +844,8 @@ export default class Exchange {
844
844
  };
845
845
  safeLiquidation(liquidation: Dict, market?: Market): Liquidation;
846
846
  safeTrade(trade: Dict, market?: Market): Trade;
847
+ parsedFeeAndFees(container: any): Dictionary<any>[];
848
+ parseFeeNumeric(fee: any): any;
847
849
  findNearestCeiling(arr: number[], providedValue: number): number;
848
850
  invertFlatStringDictionary(dict: any): {};
849
851
  reduceFeesByCurrency(fees: any): any[];
@@ -2970,48 +2970,61 @@ export default class Exchange {
2970
2970
  }
2971
2971
  cost = Precise.stringMul(multiplyPrice, amount);
2972
2972
  }
2973
- const parseFee = this.safeValue(trade, 'fee') === undefined;
2974
- const parseFees = this.safeValue(trade, 'fees') === undefined;
2975
- const shouldParseFees = parseFee || parseFees;
2976
- const fees = [];
2977
- const fee = this.safeValue(trade, 'fee');
2973
+ const [resultFee, resultFees] = this.parsedFeeAndFees(trade);
2974
+ trade['fee'] = resultFee;
2975
+ trade['fees'] = resultFees;
2976
+ trade['amount'] = this.parseNumber(amount);
2977
+ trade['price'] = this.parseNumber(price);
2978
+ trade['cost'] = this.parseNumber(cost);
2979
+ return trade;
2980
+ }
2981
+ parsedFeeAndFees(container) {
2982
+ let fee = this.safeDict(container, 'fee');
2983
+ let fees = this.safeList(container, 'fees');
2984
+ const feeDefined = fee !== undefined;
2985
+ const feesDefined = fees !== undefined;
2986
+ // parsing only if at least one of them is defined
2987
+ const shouldParseFees = (feeDefined || feesDefined);
2978
2988
  if (shouldParseFees) {
2989
+ if (feeDefined) {
2990
+ fee = this.parseFeeNumeric(fee);
2991
+ }
2992
+ if (!feesDefined) {
2993
+ // just set it directly, no further processing needed
2994
+ fees = [fee];
2995
+ }
2996
+ // 'fees' were set, so reparse them
2979
2997
  const reducedFees = this.reduceFees ? this.reduceFeesByCurrency(fees) : fees;
2980
2998
  const reducedLength = reducedFees.length;
2981
2999
  for (let i = 0; i < reducedLength; i++) {
2982
- reducedFees[i]['cost'] = this.safeNumber(reducedFees[i], 'cost');
2983
- if ('rate' in reducedFees[i]) {
2984
- reducedFees[i]['rate'] = this.safeNumber(reducedFees[i], 'rate');
2985
- }
3000
+ reducedFees[i] = this.parseFeeNumeric(reducedFees[i]);
2986
3001
  }
2987
- if (!parseFee && (reducedLength === 0)) {
2988
- // copy fee to avoid modification by reference
2989
- const feeCopy = this.deepExtend(fee);
2990
- feeCopy['cost'] = this.safeNumber(feeCopy, 'cost');
2991
- if ('rate' in feeCopy) {
2992
- feeCopy['rate'] = this.safeNumber(feeCopy, 'rate');
2993
- }
2994
- reducedFees.push(feeCopy);
2995
- }
2996
- if (parseFees) {
2997
- trade['fees'] = reducedFees;
3002
+ fees = reducedFees;
3003
+ if (reducedLength === 1) {
3004
+ fee = reducedFees[0];
2998
3005
  }
2999
- if (parseFee && (reducedLength === 1)) {
3000
- trade['fee'] = reducedFees[0];
3001
- }
3002
- const tradeFee = this.safeValue(trade, 'fee');
3003
- if (tradeFee !== undefined) {
3004
- tradeFee['cost'] = this.safeNumber(tradeFee, 'cost');
3005
- if ('rate' in tradeFee) {
3006
- tradeFee['rate'] = this.safeNumber(tradeFee, 'rate');
3007
- }
3008
- trade['fee'] = tradeFee;
3006
+ else if (reducedLength === 0) {
3007
+ fee = undefined;
3009
3008
  }
3010
3009
  }
3011
- trade['amount'] = this.parseNumber(amount);
3012
- trade['price'] = this.parseNumber(price);
3013
- trade['cost'] = this.parseNumber(cost);
3014
- return trade;
3010
+ // in case `fee & fees` are undefined, set `fees` as empty array
3011
+ if (fee === undefined) {
3012
+ fee = {
3013
+ 'cost': undefined,
3014
+ 'currency': undefined,
3015
+ };
3016
+ }
3017
+ if (fees === undefined) {
3018
+ fees = [];
3019
+ }
3020
+ return [fee, fees];
3021
+ }
3022
+ parseFeeNumeric(fee) {
3023
+ fee['cost'] = this.safeNumber(fee, 'cost'); // ensure numeric
3024
+ if ('rate' in fee) {
3025
+ fee['rate'] = this.safeNumber(fee, 'rate');
3026
+ }
3027
+ return fee;
3015
3028
  }
3016
3029
  findNearestCeiling(arr, providedValue) {
3017
3030
  // i.e. findNearestCeiling ([ 10, 30, 50], 23) returns 30
@@ -3085,12 +3098,13 @@ export default class Exchange {
3085
3098
  const reduced = {};
3086
3099
  for (let i = 0; i < fees.length; i++) {
3087
3100
  const fee = fees[i];
3088
- const feeCurrencyCode = this.safeString(fee, 'currency');
3101
+ const code = this.safeString(fee, 'currency');
3102
+ const feeCurrencyCode = code !== undefined ? code : i.toString();
3089
3103
  if (feeCurrencyCode !== undefined) {
3090
3104
  const rate = this.safeString(fee, 'rate');
3091
- const cost = this.safeValue(fee, 'cost');
3092
- if (Precise.stringEq(cost, '0')) {
3093
- // omit zero cost fees
3105
+ const cost = this.safeString(fee, 'cost');
3106
+ if (cost === undefined) {
3107
+ // omit undefined cost, as it does not make sense, however, don't omit '0' costs, as they still make sense
3094
3108
  continue;
3095
3109
  }
3096
3110
  if (!(feeCurrencyCode in reduced)) {
@@ -3102,7 +3116,7 @@ export default class Exchange {
3102
3116
  }
3103
3117
  else {
3104
3118
  reduced[feeCurrencyCode][rateKey] = {
3105
- 'currency': feeCurrencyCode,
3119
+ 'currency': code,
3106
3120
  'cost': cost,
3107
3121
  };
3108
3122
  if (rate !== undefined) {
@@ -3143,7 +3157,15 @@ export default class Exchange {
3143
3157
  change = Precise.stringSub(last, open);
3144
3158
  }
3145
3159
  if (average === undefined) {
3146
- average = Precise.stringDiv(Precise.stringAdd(last, open), '2');
3160
+ let precision = 18;
3161
+ if (market !== undefined && this.isTickPrecision()) {
3162
+ const marketPrecision = this.safeDict(market, 'precision');
3163
+ const precisionPrice = this.safeString(marketPrecision, 'price');
3164
+ if (precisionPrice !== undefined) {
3165
+ precision = this.precisionFromString(precisionPrice);
3166
+ }
3167
+ }
3168
+ average = Precise.stringDiv(Precise.stringAdd(last, open), '2', precision);
3147
3169
  }
3148
3170
  }
3149
3171
  if ((percentage === undefined) && (change !== undefined) && (open !== undefined) && Precise.stringGt(open, '0')) {
package/js/src/bingx.js CHANGED
@@ -1212,7 +1212,6 @@ export default class bingx extends Exchange {
1212
1212
  'fee': {
1213
1213
  'cost': this.parseNumber(Precise.stringAbs(this.safeString2(trade, 'commission', 'n'))),
1214
1214
  'currency': currencyCode,
1215
- 'rate': undefined,
1216
1215
  },
1217
1216
  }, market);
1218
1217
  }
package/js/src/bitget.js CHANGED
@@ -1312,6 +1312,7 @@ export default class bitget extends Exchange {
1312
1312
  'JADE': 'Jade Protocol',
1313
1313
  'DEGEN': 'DegenReborn',
1314
1314
  'TONCOIN': 'TON',
1315
+ 'OMNI': 'omni', // conflict with Omni Network
1315
1316
  },
1316
1317
  'options': {
1317
1318
  'timeframes': {
package/js/src/bitteam.js CHANGED
@@ -1940,7 +1940,6 @@ export default class bitteam extends Exchange {
1940
1940
  const fee = {
1941
1941
  'currency': this.safeCurrencyCode(feeCurrencyId),
1942
1942
  'cost': feeCost,
1943
- 'rate': undefined,
1944
1943
  };
1945
1944
  const intTs = this.parseToInt(timestamp);
1946
1945
  return this.safeTrade({
package/js/src/gate.js CHANGED
@@ -3470,8 +3470,8 @@ export default class gate extends Exchange {
3470
3470
  const side = this.safeString2(trade, 'side', 'type', contractSide);
3471
3471
  const orderId = this.safeString(trade, 'order_id');
3472
3472
  const feeAmount = this.safeString(trade, 'fee');
3473
- const gtFee = this.safeString(trade, 'gt_fee');
3474
- const pointFee = this.safeString(trade, 'point_fee');
3473
+ const gtFee = this.omitZero(this.safeString(trade, 'gt_fee'));
3474
+ const pointFee = this.omitZero(this.safeString(trade, 'point_fee'));
3475
3475
  const fees = [];
3476
3476
  if (feeAmount !== undefined) {
3477
3477
  const feeCurrencyId = this.safeString(trade, 'fee_currency');