ccxt 4.4.88__py2.py3-none-any.whl → 4.4.91__py2.py3-none-any.whl

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 (101) hide show
  1. ccxt/__init__.py +1 -3
  2. ccxt/abstract/bitget.py +58 -0
  3. ccxt/abstract/bitrue.py +65 -65
  4. ccxt/abstract/cryptocom.py +2 -0
  5. ccxt/abstract/luno.py +1 -0
  6. ccxt/async_support/__init__.py +1 -3
  7. ccxt/async_support/base/exchange.py +6 -3
  8. ccxt/async_support/base/ws/client.py +173 -64
  9. ccxt/async_support/base/ws/future.py +23 -50
  10. ccxt/async_support/binance.py +2 -2
  11. ccxt/async_support/bingx.py +55 -29
  12. ccxt/async_support/bitget.py +469 -147
  13. ccxt/async_support/bitmex.py +2 -1
  14. ccxt/async_support/bitrue.py +72 -66
  15. ccxt/async_support/bitvavo.py +34 -0
  16. ccxt/async_support/btcalpha.py +35 -0
  17. ccxt/async_support/btcbox.py +35 -0
  18. ccxt/async_support/btcmarkets.py +35 -0
  19. ccxt/async_support/btcturk.py +35 -0
  20. ccxt/async_support/bybit.py +9 -3
  21. ccxt/async_support/cex.py +61 -0
  22. ccxt/async_support/coinbase.py +1 -3
  23. ccxt/async_support/cryptocom.py +66 -2
  24. ccxt/async_support/cryptomus.py +1 -1
  25. ccxt/async_support/delta.py +2 -2
  26. ccxt/async_support/digifinex.py +39 -99
  27. ccxt/async_support/exmo.py +14 -7
  28. ccxt/async_support/gate.py +14 -7
  29. ccxt/async_support/hashkey.py +15 -28
  30. ccxt/async_support/hollaex.py +27 -22
  31. ccxt/async_support/hyperliquid.py +104 -53
  32. ccxt/async_support/kraken.py +54 -50
  33. ccxt/async_support/luno.py +87 -1
  34. ccxt/async_support/mexc.py +1 -0
  35. ccxt/async_support/modetrade.py +2 -2
  36. ccxt/async_support/okx.py +2 -1
  37. ccxt/async_support/paradex.py +1 -1
  38. ccxt/async_support/phemex.py +16 -8
  39. ccxt/async_support/tradeogre.py +3 -3
  40. ccxt/async_support/xt.py +1 -1
  41. ccxt/base/exchange.py +20 -8
  42. ccxt/binance.py +2 -2
  43. ccxt/bingx.py +55 -29
  44. ccxt/bitget.py +469 -147
  45. ccxt/bitmex.py +2 -1
  46. ccxt/bitrue.py +72 -66
  47. ccxt/bitvavo.py +34 -0
  48. ccxt/btcalpha.py +35 -0
  49. ccxt/btcbox.py +35 -0
  50. ccxt/btcmarkets.py +35 -0
  51. ccxt/btcturk.py +35 -0
  52. ccxt/bybit.py +9 -3
  53. ccxt/cex.py +61 -0
  54. ccxt/coinbase.py +1 -3
  55. ccxt/cryptocom.py +66 -2
  56. ccxt/cryptomus.py +1 -1
  57. ccxt/delta.py +2 -2
  58. ccxt/digifinex.py +39 -99
  59. ccxt/exmo.py +13 -7
  60. ccxt/gate.py +14 -7
  61. ccxt/hashkey.py +15 -28
  62. ccxt/hollaex.py +27 -22
  63. ccxt/hyperliquid.py +104 -53
  64. ccxt/kraken.py +53 -50
  65. ccxt/luno.py +87 -1
  66. ccxt/mexc.py +1 -0
  67. ccxt/modetrade.py +2 -2
  68. ccxt/okx.py +2 -1
  69. ccxt/paradex.py +1 -1
  70. ccxt/phemex.py +16 -8
  71. ccxt/pro/__init__.py +1 -127
  72. ccxt/pro/bitstamp.py +1 -1
  73. ccxt/pro/bybit.py +6 -136
  74. ccxt/pro/coinbase.py +2 -0
  75. ccxt/pro/cryptocom.py +27 -0
  76. ccxt/pro/kraken.py +249 -267
  77. ccxt/pro/mexc.py +0 -1
  78. ccxt/tradeogre.py +3 -3
  79. ccxt/xt.py +1 -1
  80. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/METADATA +64 -23
  81. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/RECORD +84 -101
  82. ccxt/abstract/coinlist.py +0 -57
  83. ccxt/async_support/base/ws/aiohttp_client.py +0 -147
  84. ccxt/async_support/bitcoincom.py +0 -18
  85. ccxt/async_support/bitfinex1.py +0 -1711
  86. ccxt/async_support/bitpanda.py +0 -17
  87. ccxt/async_support/coinlist.py +0 -2542
  88. ccxt/async_support/poloniexfutures.py +0 -1875
  89. ccxt/bitcoincom.py +0 -18
  90. ccxt/bitfinex1.py +0 -1710
  91. ccxt/bitpanda.py +0 -17
  92. ccxt/coinlist.py +0 -2542
  93. ccxt/poloniexfutures.py +0 -1875
  94. ccxt/pro/bitcoincom.py +0 -35
  95. ccxt/pro/bitfinex1.py +0 -635
  96. ccxt/pro/bitpanda.py +0 -16
  97. ccxt/pro/poloniexfutures.py +0 -1004
  98. ccxt/pro/wazirx.py +0 -766
  99. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/LICENSE.txt +0 -0
  100. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/WHEEL +0 -0
  101. {ccxt-4.4.88.dist-info → ccxt-4.4.91.dist-info}/top_level.txt +0 -0
@@ -34,35 +34,64 @@ class btcturk(Exchange, ImplicitAPI):
34
34
  'future': False,
35
35
  'option': False,
36
36
  'addMargin': False,
37
+ 'borrowCrossMargin': False,
38
+ 'borrowIsolatedMargin': False,
39
+ 'borrowMargin': False,
37
40
  'cancelOrder': True,
38
41
  'closeAllPositions': False,
39
42
  'closePosition': False,
40
43
  'createDepositAddress': False,
41
44
  'createOrder': True,
45
+ 'createOrderWithTakeProfitAndStopLoss': False,
46
+ 'createOrderWithTakeProfitAndStopLossWs': False,
47
+ 'createPostOnlyOrder': False,
42
48
  'createReduceOnlyOrder': False,
43
49
  'fetchBalance': True,
50
+ 'fetchBorrowInterest': False,
51
+ 'fetchBorrowRate': False,
44
52
  'fetchBorrowRateHistories': False,
45
53
  'fetchBorrowRateHistory': False,
54
+ 'fetchBorrowRates': False,
55
+ 'fetchBorrowRatesPerSymbol': False,
46
56
  'fetchCrossBorrowRate': False,
47
57
  'fetchCrossBorrowRates': False,
48
58
  'fetchDepositAddress': False,
49
59
  'fetchDepositAddresses': False,
50
60
  'fetchDepositAddressesByNetwork': False,
51
61
  'fetchFundingHistory': False,
62
+ 'fetchFundingInterval': False,
63
+ 'fetchFundingIntervals': False,
52
64
  'fetchFundingRate': False,
53
65
  'fetchFundingRateHistory': False,
54
66
  'fetchFundingRates': False,
67
+ 'fetchGreeks': False,
55
68
  'fetchIndexOHLCV': False,
56
69
  'fetchIsolatedBorrowRate': False,
57
70
  'fetchIsolatedBorrowRates': False,
71
+ 'fetchIsolatedPositions': False,
58
72
  'fetchLeverage': False,
73
+ 'fetchLeverages': False,
74
+ 'fetchLeverageTiers': False,
75
+ 'fetchLiquidations': False,
76
+ 'fetchLongShortRatio': False,
77
+ 'fetchLongShortRatioHistory': False,
78
+ 'fetchMarginAdjustmentHistory': False,
59
79
  'fetchMarginMode': False,
80
+ 'fetchMarginModes': False,
81
+ 'fetchMarketLeverageTiers': False,
60
82
  'fetchMarkets': True,
61
83
  'fetchMarkOHLCV': False,
84
+ 'fetchMarkPrices': False,
85
+ 'fetchMyLiquidations': False,
86
+ 'fetchMySettlementHistory': False,
62
87
  'fetchMyTrades': True,
63
88
  'fetchOHLCV': True,
89
+ 'fetchOpenInterest': False,
64
90
  'fetchOpenInterestHistory': False,
91
+ 'fetchOpenInterests': False,
65
92
  'fetchOpenOrders': True,
93
+ 'fetchOption': False,
94
+ 'fetchOptionChain': False,
66
95
  'fetchOrderBook': True,
67
96
  'fetchOrders': True,
68
97
  'fetchPosition': False,
@@ -73,11 +102,17 @@ class btcturk(Exchange, ImplicitAPI):
73
102
  'fetchPositionsHistory': False,
74
103
  'fetchPositionsRisk': False,
75
104
  'fetchPremiumIndexOHLCV': False,
105
+ 'fetchSettlementHistory': False,
76
106
  'fetchTicker': True,
77
107
  'fetchTickers': True,
78
108
  'fetchTrades': True,
109
+ 'fetchVolatilityHistory': False,
79
110
  'reduceMargin': False,
111
+ 'repayCrossMargin': False,
112
+ 'repayIsolatedMargin': False,
113
+ 'repayMargin': False,
80
114
  'setLeverage': False,
115
+ 'setMargin': False,
81
116
  'setMarginMode': False,
82
117
  'setPositionMode': False,
83
118
  'ws': False,
@@ -3676,7 +3676,10 @@ class bybit(Exchange, ImplicitAPI):
3676
3676
  market = self.market(symbol)
3677
3677
  if not market['spot']:
3678
3678
  raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot orders only')
3679
- return await self.create_order(symbol, 'market', 'buy', cost, 1, params)
3679
+ req = {
3680
+ 'cost': cost,
3681
+ }
3682
+ return await self.create_order(symbol, 'market', 'buy', -1, None, self.extend(req, params))
3680
3683
 
3681
3684
  async def create_market_sell_order_with_cost(self, symbol: str, cost: float, params={}) -> Order:
3682
3685
  """
@@ -3697,7 +3700,10 @@ class bybit(Exchange, ImplicitAPI):
3697
3700
  market = self.market(symbol)
3698
3701
  if not market['spot']:
3699
3702
  raise NotSupported(self.id + ' createMarketSellOrderWithCost() supports spot orders only')
3700
- return await self.create_order(symbol, 'market', 'sell', cost, 1, params)
3703
+ req = {
3704
+ 'cost': cost,
3705
+ }
3706
+ return await self.create_order(symbol, 'market', 'sell', -1, None, self.extend(req, params))
3701
3707
 
3702
3708
  async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
3703
3709
  """
@@ -3905,7 +3911,7 @@ class bybit(Exchange, ImplicitAPI):
3905
3911
  if (price is None) and (cost is None):
3906
3912
  raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend in the amount argument')
3907
3913
  else:
3908
- quoteAmount = Precise.string_mul(amountString, priceString)
3914
+ quoteAmount = Precise.string_mul(self.number_to_string(amount), priceString)
3909
3915
  costRequest = cost if (cost is not None) else quoteAmount
3910
3916
  request['qty'] = self.get_cost(symbol, costRequest)
3911
3917
  else:
ccxt/async_support/cex.py CHANGED
@@ -36,34 +36,95 @@ class cex(Exchange, ImplicitAPI):
36
36
  'swap': False,
37
37
  'future': False,
38
38
  'option': False,
39
+ 'addMargin': False,
40
+ 'borrowCrossMargin': False,
41
+ 'borrowIsolatedMargin': False,
42
+ 'borrowMargin': False,
39
43
  'cancelAllOrders': True,
40
44
  'cancelOrder': True,
45
+ 'closeAllPositions': False,
46
+ 'closePosition': False,
41
47
  'createOrder': True,
48
+ 'createOrderWithTakeProfitAndStopLoss': False,
49
+ 'createOrderWithTakeProfitAndStopLossWs': False,
50
+ 'createPostOnlyOrder': False,
42
51
  'createReduceOnlyOrder': False,
43
52
  'createStopOrder': True,
44
53
  'createTriggerOrder': True,
45
54
  'fetchAccounts': True,
46
55
  'fetchBalance': True,
56
+ 'fetchBorrowInterest': False,
57
+ 'fetchBorrowRate': False,
58
+ 'fetchBorrowRateHistories': False,
59
+ 'fetchBorrowRateHistory': False,
60
+ 'fetchBorrowRates': False,
61
+ 'fetchBorrowRatesPerSymbol': False,
47
62
  'fetchClosedOrder': True,
48
63
  'fetchClosedOrders': True,
64
+ 'fetchCrossBorrowRate': False,
65
+ 'fetchCrossBorrowRates': False,
49
66
  'fetchCurrencies': True,
50
67
  'fetchDepositAddress': True,
51
68
  'fetchDepositsWithdrawals': True,
52
69
  'fetchFundingHistory': False,
70
+ 'fetchFundingInterval': False,
71
+ 'fetchFundingIntervals': False,
53
72
  'fetchFundingRate': False,
54
73
  'fetchFundingRateHistory': False,
55
74
  'fetchFundingRates': False,
75
+ 'fetchGreeks': False,
76
+ 'fetchIndexOHLCV': False,
77
+ 'fetchIsolatedBorrowRate': False,
78
+ 'fetchIsolatedBorrowRates': False,
79
+ 'fetchIsolatedPositions': False,
56
80
  'fetchLedger': True,
81
+ 'fetchLeverage': False,
82
+ 'fetchLeverages': False,
83
+ 'fetchLeverageTiers': False,
84
+ 'fetchLiquidations': False,
85
+ 'fetchLongShortRatio': False,
86
+ 'fetchLongShortRatioHistory': False,
87
+ 'fetchMarginAdjustmentHistory': False,
88
+ 'fetchMarginMode': False,
89
+ 'fetchMarginModes': False,
90
+ 'fetchMarketLeverageTiers': False,
57
91
  'fetchMarkets': True,
92
+ 'fetchMarkOHLCV': False,
93
+ 'fetchMarkPrices': False,
94
+ 'fetchMyLiquidations': False,
95
+ 'fetchMySettlementHistory': False,
58
96
  'fetchOHLCV': True,
97
+ 'fetchOpenInterest': False,
98
+ 'fetchOpenInterestHistory': False,
99
+ 'fetchOpenInterests': False,
59
100
  'fetchOpenOrder': True,
60
101
  'fetchOpenOrders': True,
102
+ 'fetchOption': False,
103
+ 'fetchOptionChain': False,
61
104
  'fetchOrderBook': True,
105
+ 'fetchPosition': False,
106
+ 'fetchPositionHistory': False,
107
+ 'fetchPositionMode': False,
108
+ 'fetchPositions': False,
109
+ 'fetchPositionsForSymbol': False,
110
+ 'fetchPositionsHistory': False,
111
+ 'fetchPositionsRisk': False,
112
+ 'fetchPremiumIndexOHLCV': False,
113
+ 'fetchSettlementHistory': False,
62
114
  'fetchTicker': True,
63
115
  'fetchTickers': True,
64
116
  'fetchTime': True,
65
117
  'fetchTrades': True,
66
118
  'fetchTradingFees': True,
119
+ 'fetchVolatilityHistory': False,
120
+ 'reduceMargin': False,
121
+ 'repayCrossMargin': False,
122
+ 'repayIsolatedMargin': False,
123
+ 'repayMargin': False,
124
+ 'setLeverage': False,
125
+ 'setMargin': False,
126
+ 'setMarginMode': False,
127
+ 'setPositionMode': False,
67
128
  'transfer': True,
68
129
  },
69
130
  'urls': {
@@ -4409,7 +4409,7 @@ class coinbase(Exchange, ImplicitAPI):
4409
4409
  """
4410
4410
  *futures only* closes open positions for a market
4411
4411
 
4412
- https://coinbase-api.github.io/docs/#/en-us/swapV2/trade-api.html#One-Click%20Close%20All%20Positions
4412
+ https://docs.cdp.coinbase.com/coinbase-app/trade/reference/retailbrokerageapi_closeposition
4413
4413
 
4414
4414
  :param str symbol: Unified CCXT market symbol
4415
4415
  :param str [side]: not used by coinbase
@@ -4420,8 +4420,6 @@ class coinbase(Exchange, ImplicitAPI):
4420
4420
  """
4421
4421
  await self.load_markets()
4422
4422
  market = self.market(symbol)
4423
- if not market['future']:
4424
- raise NotSupported(self.id + ' closePosition() only supported for futures markets')
4425
4423
  clientOrderId = self.safe_string_2(params, 'client_order_id', 'clientOrderId')
4426
4424
  params = self.omit(params, 'clientOrderId')
4427
4425
  request: dict = {
@@ -60,6 +60,7 @@ class cryptocom(Exchange, ImplicitAPI):
60
60
  'createOrders': True,
61
61
  'createStopOrder': True,
62
62
  'createTriggerOrder': True,
63
+ 'editOrder': True,
63
64
  'fetchAccounts': True,
64
65
  'fetchBalance': True,
65
66
  'fetchBidsAsks': False,
@@ -152,6 +153,7 @@ class cryptocom(Exchange, ImplicitAPI):
152
153
  'derivatives': 'https://uat-api.3ona.co/v2',
153
154
  },
154
155
  'api': {
156
+ 'base': 'https://api.crypto.com',
155
157
  'v1': 'https://api.crypto.com/exchange/v1',
156
158
  'v2': 'https://api.crypto.com/v2',
157
159
  'derivatives': 'https://deriv-api.crypto.com/v1',
@@ -169,6 +171,13 @@ class cryptocom(Exchange, ImplicitAPI):
169
171
  'fees': 'https://crypto.com/exchange/document/fees-limits',
170
172
  },
171
173
  'api': {
174
+ 'base': {
175
+ 'public': {
176
+ 'get': {
177
+ 'v1/public/get-announcements': 1, # no description of rate limit
178
+ },
179
+ },
180
+ },
172
181
  'v1': {
173
182
  'public': {
174
183
  'get': {
@@ -195,6 +204,7 @@ class cryptocom(Exchange, ImplicitAPI):
195
204
  'private/user-balance-history': 10 / 3,
196
205
  'private/get-positions': 10 / 3,
197
206
  'private/create-order': 2 / 3,
207
+ 'private/amend-order': 4 / 3, # no description of rate limit
198
208
  'private/create-order-list': 10 / 3,
199
209
  'private/cancel-order': 2 / 3,
200
210
  'private/cancel-order-list': 10 / 3,
@@ -538,7 +548,22 @@ class cryptocom(Exchange, ImplicitAPI):
538
548
  # self endpoint requires authentication
539
549
  if not self.check_required_credentials(False):
540
550
  return None
541
- response = await self.v1PrivatePostPrivateGetCurrencyNetworks(params)
551
+ skipFetchCurrencies = False
552
+ skipFetchCurrencies, params = self.handle_option_and_params(params, 'fetchCurrencies', 'skipFetchCurrencies', False)
553
+ if skipFetchCurrencies:
554
+ # sub-accounts can't access self endpoint
555
+ return None
556
+ response = {}
557
+ try:
558
+ response = await self.v1PrivatePostPrivateGetCurrencyNetworks(params)
559
+ except Exception as e:
560
+ if isinstance(e, ExchangeError):
561
+ # sub-accounts can't access self endpoint
562
+ # {"code":"10001","msg":"SYS_ERROR"}
563
+ return None
564
+ raise e
565
+ # do nothing
566
+ # sub-accounts can't access self endpoint
542
567
  #
543
568
  # {
544
569
  # "id": "1747502328559",
@@ -563,7 +588,7 @@ class cryptocom(Exchange, ImplicitAPI):
563
588
  # "network_id": "CRONOS",
564
589
  # "withdrawal_fee": "0.18000000",
565
590
  # "withdraw_enabled": True,
566
- # "min_withdrawal_amount": "0.36",
591
+ # "min_withdrawal_amount": "0.35",
567
592
  # "deposit_enabled": True,
568
593
  # "confirmation_required": "15"
569
594
  # },
@@ -1551,6 +1576,45 @@ class cryptocom(Exchange, ImplicitAPI):
1551
1576
  params = self.omit(params, ['postOnly', 'clientOrderId', 'timeInForce', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
1552
1577
  return self.extend(request, params)
1553
1578
 
1579
+ async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
1580
+ """
1581
+ edit a trade order
1582
+
1583
+ https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-amend-order
1584
+
1585
+ :param str id: order id
1586
+ :param str symbol: unified market symbol of the order to edit
1587
+ :param str [type]: not used by cryptocom editOrder
1588
+ :param str [side]: not used by cryptocom editOrder
1589
+ :param float amount:(mandatory) how much of the currency you want to trade in units of the base currency
1590
+ :param float price:(mandatory) the price for the order, in units of the quote currency, ignored in market orders
1591
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1592
+ :param str [params.clientOrderId]: the original client order id of the order to edit, required if id is not provided
1593
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1594
+ """
1595
+ await self.load_markets()
1596
+ request = self.edit_order_request(id, symbol, amount, price, params)
1597
+ response = await self.v1PrivatePostPrivateAmendOrder(request)
1598
+ result = self.safe_dict(response, 'result', {})
1599
+ return self.parse_order(result)
1600
+
1601
+ def edit_order_request(self, id: str, symbol: str, amount: float, price: Num = None, params={}):
1602
+ request: dict = {}
1603
+ if id is not None:
1604
+ request['order_id'] = id
1605
+ else:
1606
+ originalClientOrderId = self.safe_string_2(params, 'orig_client_oid', 'clientOrderId')
1607
+ if originalClientOrderId is None:
1608
+ raise ArgumentsRequired(self.id + ' editOrder() requires an id argument or orig_client_oid parameter')
1609
+ else:
1610
+ request['orig_client_oid'] = originalClientOrderId
1611
+ params = self.omit(params, ['orig_client_oid', 'clientOrderId'])
1612
+ if (amount is None) or (price is None):
1613
+ raise ArgumentsRequired(self.id + ' editOrder() requires both amount and price arguments. If you do not want to change the amount or price, you should pass the original values')
1614
+ request['new_quantity'] = self.amount_to_precision(symbol, amount)
1615
+ request['new_price'] = self.price_to_precision(symbol, price)
1616
+ return self.extend(request, params)
1617
+
1554
1618
  async def cancel_all_orders(self, symbol: Str = None, params={}):
1555
1619
  """
1556
1620
  cancel all open orders
@@ -461,7 +461,7 @@ class cryptomus(Exchange, ImplicitAPI):
461
461
  #
462
462
  # {
463
463
  # "currency_pair": "XMR_USDT",
464
- # "last_price": "158.04829771",
464
+ # "last_price": "158.04829772",
465
465
  # "base_volume": "0.35185785",
466
466
  # "quote_volume": "55.523761128544"
467
467
  # }
@@ -906,9 +906,9 @@ class delta(Exchange, ImplicitAPI):
906
906
  'inverse': None if spot else not linear,
907
907
  'taker': self.safe_number(market, 'taker_commission_rate'),
908
908
  'maker': self.safe_number(market, 'maker_commission_rate'),
909
- 'contractSize': contractSize,
909
+ 'contractSize': None if spot else contractSize,
910
910
  'expiry': expiry,
911
- 'expiryDatetime': expiryDatetime,
911
+ 'expiryDatetime': self.iso8601(expiry), # do not use raw expiry string
912
912
  'strike': self.parse_number(strike),
913
913
  'optionType': optionType,
914
914
  'precision': {
@@ -467,6 +467,16 @@ class digifinex(Exchange, ImplicitAPI):
467
467
  'TRX': 'TRC20',
468
468
  'VECHAIN': 'Vechain', # VET
469
469
  },
470
+ 'networksById': {
471
+ 'TRC20': 'TRC20',
472
+ 'TRX': 'TRC20',
473
+ 'BEP20': 'BEP20',
474
+ 'BSC': 'BEP20',
475
+ 'ERC20': 'ERC20',
476
+ 'ETH': 'ERC20',
477
+ 'Polygon': 'POLYGON',
478
+ 'Crypto.com': 'CRONOS',
479
+ },
470
480
  },
471
481
  'commonCurrencies': {
472
482
  'BHT': 'Black House Test',
@@ -494,6 +504,7 @@ class digifinex(Exchange, ImplicitAPI):
494
504
  # "min_withdraw_amount":10,
495
505
  # "min_withdraw_fee":5,
496
506
  # "currency":"USDT",
507
+ # "withdraw_fee_currency":"USDT",
497
508
  # "withdraw_status":0,
498
509
  # "chain":"OMNI"
499
510
  # },
@@ -504,6 +515,7 @@ class digifinex(Exchange, ImplicitAPI):
504
515
  # "min_withdraw_amount":10,
505
516
  # "min_withdraw_fee":3,
506
517
  # "currency":"USDT",
518
+ # "withdraw_fee_currency":"USDT",
507
519
  # "withdraw_status":1,
508
520
  # "chain":"ERC20"
509
521
  # },
@@ -514,6 +526,7 @@ class digifinex(Exchange, ImplicitAPI):
514
526
  # "min_withdraw_amount":0,
515
527
  # "min_withdraw_fee":0,
516
528
  # "currency":"DGF13",
529
+ # "withdraw_fee_currency":"DGF13",
517
530
  # "withdraw_status":0,
518
531
  # "chain":""
519
532
  # },
@@ -521,118 +534,45 @@ class digifinex(Exchange, ImplicitAPI):
521
534
  # "code":200
522
535
  # }
523
536
  #
524
- data = self.safe_value(response, 'data', [])
537
+ data = self.safe_list(response, 'data', [])
538
+ groupedById = self.group_by(data, 'currency')
539
+ keys = list(groupedById.keys())
525
540
  result: dict = {}
526
- for i in range(0, len(data)):
527
- currency = data[i]
528
- id = self.safe_string(currency, 'currency')
541
+ for i in range(0, len(keys)):
542
+ id = keys[i]
543
+ networkEntries = groupedById[id]
529
544
  code = self.safe_currency_code(id)
530
- depositStatus = self.safe_integer(currency, 'deposit_status', 1)
531
- withdrawStatus = self.safe_integer(currency, 'withdraw_status', 1)
532
- deposit = depositStatus > 0
533
- withdraw = withdrawStatus > 0
534
- active = deposit and withdraw
535
- feeString = self.safe_string(currency, 'min_withdraw_fee') # withdraw_fee_rate was zero for all currencies, so self was the worst case scenario
536
- minWithdrawString = self.safe_string(currency, 'min_withdraw_amount')
537
- minDepositString = self.safe_string(currency, 'min_deposit_amount')
538
- minDeposit = self.parse_number(minDepositString)
539
- minWithdraw = self.parse_number(minWithdrawString)
540
- fee = self.parse_number(feeString)
541
- # define precision with temporary way
542
- minFoundPrecision = Precise.string_min(feeString, Precise.string_min(minDepositString, minWithdrawString))
543
- precision = self.parse_number(minFoundPrecision)
544
- networkId = self.safe_string(currency, 'chain')
545
- networkCode = None
546
- if networkId is not None:
545
+ networks = {}
546
+ for j in range(0, len(networkEntries)):
547
+ networkEntry = networkEntries[j]
548
+ networkId = self.safe_string(networkEntry, 'chain')
547
549
  networkCode = self.network_id_to_code(networkId)
548
- network: dict = {
549
- 'info': currency,
550
- 'id': networkId,
551
- 'network': networkCode,
552
- 'active': active,
553
- 'fee': fee,
554
- 'precision': precision,
555
- 'deposit': deposit,
556
- 'withdraw': withdraw,
557
- 'limits': {
558
- 'amount': {
559
- 'min': None,
560
- 'max': None,
561
- },
562
- 'withdraw': {
563
- 'min': minWithdraw,
564
- 'max': None,
565
- },
566
- 'deposit': {
567
- 'min': minDeposit,
568
- 'max': None,
569
- },
570
- },
571
- }
572
- if code in result:
573
- resultCodeInfo = result[code]['info']
574
- if isinstance(resultCodeInfo, list):
575
- resultCodeInfo.append(currency)
576
- else:
577
- resultCodeInfo = [resultCodeInfo, currency]
578
- if withdraw:
579
- result[code]['withdraw'] = True
580
- result[code]['limits']['withdraw']['min'] = min(result[code]['limits']['withdraw']['min'], minWithdraw)
581
- if deposit:
582
- result[code]['deposit'] = True
583
- result[code]['limits']['deposit']['min'] = min(result[code]['limits']['deposit']['min'], minDeposit)
584
- if active:
585
- result[code]['active'] = True
586
- else:
587
- result[code] = {
588
- 'id': id,
589
- 'code': code,
590
- 'info': currency,
591
- 'type': None,
592
- 'name': None,
593
- 'active': active,
594
- 'deposit': deposit,
595
- 'withdraw': withdraw,
596
- 'fee': self.parse_number(feeString),
550
+ networks[networkCode] = {
551
+ 'id': networkId,
552
+ 'network': networkCode,
553
+ 'active': None,
554
+ 'deposit': self.safe_integer(networkEntry, 'deposit_status') == 1,
555
+ 'withdraw': self.safe_integer(networkEntry, 'withdraw_status') == 1,
556
+ 'fee': self.safe_number(networkEntry, 'min_withdraw_fee'),
597
557
  'precision': None,
598
558
  'limits': {
599
- 'amount': {
600
- 'min': None,
601
- 'max': None,
602
- },
603
559
  'withdraw': {
604
- 'min': minWithdraw,
560
+ 'min': self.safe_number(networkEntry, 'min_withdraw_amount'),
605
561
  'max': None,
606
562
  },
607
563
  'deposit': {
608
- 'min': minDeposit,
564
+ 'min': self.safe_number(networkEntry, 'min_deposit_amount'),
609
565
  'max': None,
610
566
  },
611
567
  },
612
- 'networks': {},
613
- }
614
- if networkId is not None:
615
- result[code]['networks'][networkId] = network
616
- else:
617
- result[code]['active'] = active
618
- result[code]['fee'] = self.parse_number(feeString)
619
- result[code]['deposit'] = deposit
620
- result[code]['withdraw'] = withdraw
621
- result[code]['limits'] = {
622
- 'amount': {
623
- 'min': None,
624
- 'max': None,
625
- },
626
- 'withdraw': {
627
- 'min': minWithdraw,
628
- 'max': None,
629
- },
630
- 'deposit': {
631
- 'min': minDeposit,
632
- 'max': None,
633
- },
568
+ 'info': networkEntry,
634
569
  }
635
- result[code]['precision'] = precision if (result[code]['precision'] is None) else max(result[code]['precision'], precision)
570
+ result[code] = self.safe_currency_structure({
571
+ 'id': id,
572
+ 'code': code,
573
+ 'info': networkEntries,
574
+ 'networks': networks,
575
+ })
636
576
  return result
637
577
 
638
578
  async def fetch_markets(self, params={}) -> List[Market]:
@@ -5,6 +5,7 @@
5
5
 
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.exmo import ImplicitAPI
8
+ import asyncio
8
9
  import hashlib
9
10
  from ccxt.base.types import Any, Balances, Currencies, Currency, DepositAddress, Int, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, OrderBooks, Trade, TradingFees, Transaction
10
11
  from typing import List
@@ -779,7 +780,8 @@ class exmo(Exchange, ImplicitAPI):
779
780
  :param dict [params]: extra parameters specific to the exchange API endpoint
780
781
  :returns dict[]: an array of objects representing market data
781
782
  """
782
- response = await self.publicGetPairSettings(params)
783
+ promises = []
784
+ promises.append(self.publicGetPairSettings(params))
783
785
  #
784
786
  # {
785
787
  # "BTC_USD":{
@@ -796,8 +798,9 @@ class exmo(Exchange, ImplicitAPI):
796
798
  # }
797
799
  #
798
800
  marginPairsDict: dict = {}
799
- if self.check_required_credentials(False):
800
- marginPairs = await self.privatePostMarginPairList(params)
801
+ fetchMargin = self.check_required_credentials(False)
802
+ if fetchMargin:
803
+ promises.append(self.privatePostMarginPairList(params))
801
804
  #
802
805
  # {
803
806
  # "pairs": [
@@ -827,14 +830,18 @@ class exmo(Exchange, ImplicitAPI):
827
830
  # ]
828
831
  # }
829
832
  #
830
- pairs = self.safe_value(marginPairs, 'pairs')
833
+ responses = await asyncio.gather(*promises)
834
+ spotResponse = responses[0]
835
+ if fetchMargin:
836
+ marginPairs = responses[1]
837
+ pairs = self.safe_list(marginPairs, 'pairs')
831
838
  marginPairsDict = self.index_by(pairs, 'name')
832
- keys = list(response.keys())
839
+ keys = list(spotResponse.keys())
833
840
  result = []
834
841
  for i in range(0, len(keys)):
835
842
  id = keys[i]
836
- market = response[id]
837
- marginMarket = self.safe_value(marginPairsDict, id)
843
+ market = spotResponse[id]
844
+ marginMarket = self.safe_dict(marginPairsDict, id)
838
845
  symbol = id.replace('_', '/')
839
846
  baseId, quoteId = symbol.split('/')
840
847
  base = self.safe_currency_code(baseId)