ccxt 4.2.88__py2.py3-none-any.whl → 4.2.90__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.

Potentially problematic release.


This version of ccxt might be problematic. Click here for more details.

Files changed (156) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/bingx.py +2 -0
  3. ccxt/abstract/bybit.py +2 -0
  4. ccxt/ascendex.py +6 -3
  5. ccxt/async_support/__init__.py +1 -1
  6. ccxt/async_support/ascendex.py +6 -3
  7. ccxt/async_support/base/exchange.py +15 -2
  8. ccxt/async_support/bigone.py +2 -2
  9. ccxt/async_support/binance.py +88 -14
  10. ccxt/async_support/bingx.py +96 -3
  11. ccxt/async_support/bit2c.py +2 -2
  12. ccxt/async_support/bitbank.py +2 -2
  13. ccxt/async_support/bitfinex.py +2 -2
  14. ccxt/async_support/bitfinex2.py +4 -3
  15. ccxt/async_support/bitflyer.py +4 -2
  16. ccxt/async_support/bitget.py +12 -5
  17. ccxt/async_support/bitmart.py +6 -4
  18. ccxt/async_support/bitmex.py +3 -2
  19. ccxt/async_support/bitopro.py +3 -3
  20. ccxt/async_support/bitrue.py +3 -2
  21. ccxt/async_support/bitso.py +2 -2
  22. ccxt/async_support/bitstamp.py +89 -97
  23. ccxt/async_support/bitteam.py +2 -2
  24. ccxt/async_support/bitvavo.py +3 -3
  25. ccxt/async_support/bl3p.py +2 -2
  26. ccxt/async_support/blockchaincom.py +2 -2
  27. ccxt/async_support/blofin.py +4 -2
  28. ccxt/async_support/bybit.py +57 -5
  29. ccxt/async_support/cex.py +3 -3
  30. ccxt/async_support/coinbase.py +42 -22
  31. ccxt/async_support/coinbaseinternational.py +3 -2
  32. ccxt/async_support/coinbasepro.py +3 -3
  33. ccxt/async_support/coincheck.py +2 -2
  34. ccxt/async_support/coinex.py +101 -13
  35. ccxt/async_support/coinlist.py +3 -3
  36. ccxt/async_support/coinmate.py +2 -2
  37. ccxt/async_support/coinmetro.py +2 -2
  38. ccxt/async_support/coinone.py +2 -2
  39. ccxt/async_support/coinsph.py +6 -4
  40. ccxt/async_support/cryptocom.py +1 -0
  41. ccxt/async_support/currencycom.py +3 -3
  42. ccxt/async_support/delta.py +3 -2
  43. ccxt/async_support/deribit.py +3 -3
  44. ccxt/async_support/digifinex.py +7 -4
  45. ccxt/async_support/exmo.py +4 -3
  46. ccxt/async_support/gate.py +8 -4
  47. ccxt/async_support/gemini.py +13 -12
  48. ccxt/async_support/hitbtc.py +8 -5
  49. ccxt/async_support/hollaex.py +3 -3
  50. ccxt/async_support/htx.py +7 -4
  51. ccxt/async_support/huobijp.py +2 -2
  52. ccxt/async_support/hyperliquid.py +3 -2
  53. ccxt/async_support/idex.py +3 -3
  54. ccxt/async_support/independentreserve.py +2 -2
  55. ccxt/async_support/kraken.py +3 -3
  56. ccxt/async_support/kucoin.py +43 -18
  57. ccxt/async_support/kucoinfutures.py +32 -4
  58. ccxt/async_support/kuna.py +2 -2
  59. ccxt/async_support/latoken.py +7 -3
  60. ccxt/async_support/lbank.py +7 -5
  61. ccxt/async_support/luno.py +4 -2
  62. ccxt/async_support/lykke.py +2 -2
  63. ccxt/async_support/mexc.py +57 -9
  64. ccxt/async_support/ndax.py +2 -2
  65. ccxt/async_support/oceanex.py +2 -2
  66. ccxt/async_support/okcoin.py +2 -2
  67. ccxt/async_support/okx.py +149 -12
  68. ccxt/async_support/onetrading.py +3 -3
  69. ccxt/async_support/phemex.py +3 -2
  70. ccxt/async_support/poloniex.py +3 -3
  71. ccxt/async_support/probit.py +2 -2
  72. ccxt/async_support/timex.py +6 -4
  73. ccxt/async_support/upbit.py +2 -2
  74. ccxt/async_support/wazirx.py +2 -2
  75. ccxt/async_support/whitebit.py +3 -3
  76. ccxt/async_support/woo.py +4 -3
  77. ccxt/async_support/yobit.py +2 -2
  78. ccxt/base/exchange.py +65 -12
  79. ccxt/base/types.py +33 -0
  80. ccxt/bigone.py +2 -2
  81. ccxt/binance.py +88 -14
  82. ccxt/bingx.py +96 -3
  83. ccxt/bit2c.py +2 -2
  84. ccxt/bitbank.py +2 -2
  85. ccxt/bitfinex.py +2 -2
  86. ccxt/bitfinex2.py +4 -3
  87. ccxt/bitflyer.py +4 -2
  88. ccxt/bitget.py +12 -5
  89. ccxt/bitmart.py +6 -4
  90. ccxt/bitmex.py +3 -2
  91. ccxt/bitopro.py +3 -3
  92. ccxt/bitrue.py +3 -2
  93. ccxt/bitso.py +2 -2
  94. ccxt/bitstamp.py +89 -97
  95. ccxt/bitteam.py +2 -2
  96. ccxt/bitvavo.py +3 -3
  97. ccxt/bl3p.py +2 -2
  98. ccxt/blockchaincom.py +2 -2
  99. ccxt/blofin.py +4 -2
  100. ccxt/bybit.py +57 -5
  101. ccxt/cex.py +3 -3
  102. ccxt/coinbase.py +42 -22
  103. ccxt/coinbaseinternational.py +3 -2
  104. ccxt/coinbasepro.py +3 -3
  105. ccxt/coincheck.py +2 -2
  106. ccxt/coinex.py +101 -13
  107. ccxt/coinlist.py +3 -3
  108. ccxt/coinmate.py +2 -2
  109. ccxt/coinmetro.py +2 -2
  110. ccxt/coinone.py +2 -2
  111. ccxt/coinsph.py +6 -4
  112. ccxt/cryptocom.py +1 -0
  113. ccxt/currencycom.py +3 -3
  114. ccxt/delta.py +3 -2
  115. ccxt/deribit.py +3 -3
  116. ccxt/digifinex.py +7 -4
  117. ccxt/exmo.py +4 -3
  118. ccxt/gate.py +8 -4
  119. ccxt/gemini.py +13 -12
  120. ccxt/hitbtc.py +8 -5
  121. ccxt/hollaex.py +3 -3
  122. ccxt/htx.py +7 -4
  123. ccxt/huobijp.py +2 -2
  124. ccxt/hyperliquid.py +3 -2
  125. ccxt/idex.py +3 -3
  126. ccxt/independentreserve.py +2 -2
  127. ccxt/kraken.py +3 -3
  128. ccxt/kucoin.py +43 -18
  129. ccxt/kucoinfutures.py +32 -4
  130. ccxt/kuna.py +2 -2
  131. ccxt/latoken.py +7 -3
  132. ccxt/lbank.py +7 -5
  133. ccxt/luno.py +4 -2
  134. ccxt/lykke.py +2 -2
  135. ccxt/mexc.py +57 -9
  136. ccxt/ndax.py +2 -2
  137. ccxt/oceanex.py +2 -2
  138. ccxt/okcoin.py +2 -2
  139. ccxt/okx.py +149 -12
  140. ccxt/onetrading.py +3 -3
  141. ccxt/phemex.py +3 -2
  142. ccxt/poloniex.py +3 -3
  143. ccxt/pro/__init__.py +1 -1
  144. ccxt/pro/bitget.py +2 -0
  145. ccxt/pro/bitvavo.py +2 -2
  146. ccxt/probit.py +2 -2
  147. ccxt/timex.py +6 -4
  148. ccxt/upbit.py +2 -2
  149. ccxt/wazirx.py +2 -2
  150. ccxt/whitebit.py +3 -3
  151. ccxt/woo.py +4 -3
  152. ccxt/yobit.py +2 -2
  153. {ccxt-4.2.88.dist-info → ccxt-4.2.90.dist-info}/METADATA +4 -4
  154. {ccxt-4.2.88.dist-info → ccxt-4.2.90.dist-info}/RECORD +156 -156
  155. {ccxt-4.2.88.dist-info → ccxt-4.2.90.dist-info}/WHEEL +0 -0
  156. {ccxt-4.2.88.dist-info → ccxt-4.2.90.dist-info}/top_level.txt +0 -0
ccxt/async_support/okx.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.okx import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
- from ccxt.base.types import Account, Balances, Currency, Greeks, Int, Leverage, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
+ from ccxt.base.types import Account, Balances, Currencies, Currency, Greeks, Int, Leverage, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import PermissionDenied
@@ -107,6 +107,7 @@ class okx(Exchange, ImplicitAPI):
107
107
  'fetchLedgerEntry': None,
108
108
  'fetchLeverage': True,
109
109
  'fetchLeverageTiers': False,
110
+ 'fetchMarginAdjustmentHistory': True,
110
111
  'fetchMarketLeverageTiers': True,
111
112
  'fetchMarkets': True,
112
113
  'fetchMarkOHLCV': True,
@@ -1543,7 +1544,7 @@ class okx(Exchange, ImplicitAPI):
1543
1544
  }
1544
1545
  return self.safe_string(networksById, networkId, networkId)
1545
1546
 
1546
- async def fetch_currencies(self, params={}):
1547
+ async def fetch_currencies(self, params={}) -> Currencies:
1547
1548
  """
1548
1549
  fetches all available currencies on an exchange
1549
1550
  :see: https://www.okx.com/docs-v5/en/#rest-api-funding-get-currencies
@@ -2267,7 +2268,7 @@ class okx(Exchange, ImplicitAPI):
2267
2268
  result[code] = account
2268
2269
  return self.safe_balance(result)
2269
2270
 
2270
- def parse_trading_fee(self, fee, market: Market = None):
2271
+ def parse_trading_fee(self, fee, market: Market = None) -> TradingFeeInterface:
2271
2272
  # https://www.okx.com/docs-v5/en/#rest-api-account-get-fee-rates
2272
2273
  #
2273
2274
  # {
@@ -2287,9 +2288,11 @@ class okx(Exchange, ImplicitAPI):
2287
2288
  # OKX returns the fees values opposed to other exchanges, so the sign needs to be flipped
2288
2289
  'maker': self.parse_number(Precise.string_neg(self.safe_string_2(fee, 'maker', 'makerU'))),
2289
2290
  'taker': self.parse_number(Precise.string_neg(self.safe_string_2(fee, 'taker', 'takerU'))),
2291
+ 'percentage': None,
2292
+ 'tierBased': None,
2290
2293
  }
2291
2294
 
2292
- async def fetch_trading_fee(self, symbol: str, params={}):
2295
+ async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
2293
2296
  """
2294
2297
  fetch the trading fees for a market
2295
2298
  :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-fee-rates
@@ -6034,9 +6037,9 @@ class okx(Exchange, ImplicitAPI):
6034
6037
  # }
6035
6038
  #
6036
6039
  data = self.safe_list(response, 'data', [])
6040
+ entry = self.safe_dict(data, 0, {})
6037
6041
  errorCode = self.safe_string(response, 'code')
6038
- item = self.safe_dict(data, 0, {})
6039
- return self.extend(self.parse_margin_modification(item, market), {
6042
+ return self.extend(self.parse_margin_modification(entry, market), {
6040
6043
  'status': 'ok' if (errorCode == '0') else 'failed',
6041
6044
  })
6042
6045
 
@@ -6051,22 +6054,66 @@ class okx(Exchange, ImplicitAPI):
6051
6054
  # "type": "reduce"
6052
6055
  # }
6053
6056
  #
6054
- amountRaw = self.safe_number(data, 'amt')
6057
+ # fetchMarginAdjustmentHistory
6058
+ #
6059
+ # {
6060
+ # bal: '67621.4325135010619812',
6061
+ # balChg: '-10.0000000000000000',
6062
+ # billId: '691293628710342659',
6063
+ # ccy: 'USDT',
6064
+ # clOrdId: '',
6065
+ # execType: '',
6066
+ # fee: '0',
6067
+ # fillFwdPx: '',
6068
+ # fillIdxPx: '',
6069
+ # fillMarkPx: '',
6070
+ # fillMarkVol: '',
6071
+ # fillPxUsd: '',
6072
+ # fillPxVol: '',
6073
+ # fillTime: '1711089244850',
6074
+ # from: '',
6075
+ # instId: 'XRP-USDT-SWAP',
6076
+ # instType: 'SWAP',
6077
+ # interest: '0',
6078
+ # mgnMode: 'isolated',
6079
+ # notes: '',
6080
+ # ordId: '',
6081
+ # pnl: '0',
6082
+ # posBal: '73.12',
6083
+ # posBalChg: '10.00',
6084
+ # px: '',
6085
+ # subType: '160',
6086
+ # sz: '10',
6087
+ # tag: '',
6088
+ # to: '',
6089
+ # tradeId: '0',
6090
+ # ts: '1711089244699',
6091
+ # type: '6'
6092
+ # }
6093
+ #
6094
+ amountRaw = self.safe_string_2(data, 'amt', 'posBalChg')
6055
6095
  typeRaw = self.safe_string(data, 'type')
6056
- type = 'reduce' if (typeRaw == 'reduce') else 'add'
6096
+ type = None
6097
+ if typeRaw == '6':
6098
+ type = 'add' if Precise.string_gt(amountRaw, '0') else 'reduce'
6099
+ else:
6100
+ type = typeRaw
6101
+ amount = Precise.string_abs(amountRaw)
6057
6102
  marketId = self.safe_string(data, 'instId')
6058
6103
  responseMarket = self.safe_market(marketId, market)
6059
6104
  code = responseMarket['base'] if responseMarket['inverse'] else responseMarket['quote']
6105
+ timestamp = self.safe_integer(data, 'ts')
6060
6106
  return {
6061
6107
  'info': data,
6062
6108
  'symbol': responseMarket['symbol'],
6063
6109
  'type': type,
6064
- 'amount': amountRaw,
6065
- 'total': None,
6110
+ 'marginMode': 'isolated',
6111
+ 'amount': self.parse_number(amount),
6066
6112
  'code': code,
6113
+ 'total': None,
6067
6114
  'status': None,
6068
- 'timestamp': None,
6069
- 'datetime': None,
6115
+ 'timestamp': timestamp,
6116
+ 'datetime': self.iso8601(timestamp),
6070
6117
  }
6071
6118
 
6072
6119
  async def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
@@ -7087,3 +7134,93 @@ class okx(Exchange, ImplicitAPI):
7087
7134
  self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
7088
7135
  raise ExchangeError(feedback) # unknown message
7089
7136
  return None
7137
+
7138
+ async def fetch_margin_adjustment_history(self, symbol: Str = None, type: Str = None, since: Num = None, limit: Num = None, params={}) -> List[MarginModification]:
7139
+ """
7140
+ fetches the history of margin added or reduced from contract isolated positions
7141
+ :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-bills-details-last-7-days
7142
+ :see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-bills-details-last-3-months
7143
+ :param str [symbol]: not used by okx fetchMarginAdjustmentHistory
7144
+ :param str [type]: "add" or "reduce"
7145
+ :param dict params: extra parameters specific to the exchange api endpoint
7146
+ :param boolean [params.auto]: True if fetching auto margin increases
7147
+ :returns dict[]: a list of `margin structures <https://docs.ccxt.com/#/?id=margin-loan-structure>`
7148
+ """
7149
+ await self.load_markets()
7150
+ auto = self.safe_bool(params, 'auto')
7151
+ if type is None:
7152
+ raise ArgumentsRequired(self.id + ' fetchMarginAdjustmentHistory() requires a type argument')
7153
+ isAdd = type == 'add'
7154
+ subType = '160' if isAdd else '161'
7155
+ if auto:
7156
+ if isAdd:
7157
+ subType = '162'
7158
+ else:
7159
+ raise BadRequest(self.id + ' cannot fetch margin adjustments for type ' + type)
7160
+ request = {
7161
+ 'subType': subType,
7162
+ 'mgnMode': 'isolated',
7163
+ }
7164
+ until = self.safe_integer(params, 'until')
7165
+ params = self.omit(params, 'until')
7166
+ if since is not None:
7167
+ request['startTime'] = since
7168
+ if limit is not None:
7169
+ request['limit'] = limit
7170
+ if until is not None:
7171
+ request['endTime'] = until
7172
+ response = None
7173
+ now = self.milliseconds()
7174
+ oneWeekAgo = now - 604800000
7175
+ threeMonthsAgo = now - 7776000000
7176
+ if (since is None) or (since > oneWeekAgo):
7177
+ response = await self.privateGetAccountBills(self.extend(request, params))
7178
+ elif since > threeMonthsAgo:
7179
+ response = await self.privateGetAccountBillsArchive(self.extend(request, params))
7180
+ else:
7181
+ raise BadRequest(self.id + ' fetchMarginAdjustmentHistory() cannot fetch margin adjustments older than 3 months')
7182
+ #
7183
+ # {
7184
+ # code: '0',
7185
+ # data: [
7186
+ # {
7187
+ # bal: '67621.4325135010619812',
7188
+ # balChg: '-10.0000000000000000',
7189
+ # billId: '691293628710342659',
7190
+ # ccy: 'USDT',
7191
+ # clOrdId: '',
7192
+ # execType: '',
7193
+ # fee: '0',
7194
+ # fillFwdPx: '',
7195
+ # fillIdxPx: '',
7196
+ # fillMarkPx: '',
7197
+ # fillMarkVol: '',
7198
+ # fillPxUsd: '',
7199
+ # fillPxVol: '',
7200
+ # fillTime: '1711089244850',
7201
+ # from: '',
7202
+ # instId: 'XRP-USDT-SWAP',
7203
+ # instType: 'SWAP',
7204
+ # interest: '0',
7205
+ # mgnMode: 'isolated',
7206
+ # notes: '',
7207
+ # ordId: '',
7208
+ # pnl: '0',
7209
+ # posBal: '73.12',
7210
+ # posBalChg: '10.00',
7211
+ # px: '',
7212
+ # subType: '160',
7213
+ # sz: '10',
7214
+ # tag: '',
7215
+ # to: '',
7216
+ # tradeId: '0',
7217
+ # ts: '1711089244699',
7218
+ # type: '6'
7219
+ # }
7220
+ # ],
7221
+ # msg: ''
7222
+ # }
7223
+ #
7224
+ data = self.safe_list(response, 'data')
7225
+ modifications = self.parse_margin_modifications(data)
7226
+ return self.filter_by_symbol_since_limit(modifications, symbol, since, limit)
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.onetrading import ImplicitAPI
8
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
8
+ from ccxt.base.types import Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction
9
9
  from typing import List
10
10
  from ccxt.base.errors import ExchangeError
11
11
  from ccxt.base.errors import PermissionDenied
@@ -325,7 +325,7 @@ class onetrading(Exchange, ImplicitAPI):
325
325
  #
326
326
  return self.safe_integer(response, 'epoch_millis')
327
327
 
328
- async def fetch_currencies(self, params={}):
328
+ async def fetch_currencies(self, params={}) -> Currencies:
329
329
  """
330
330
  fetches all available currencies on an exchange
331
331
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -443,7 +443,7 @@ class onetrading(Exchange, ImplicitAPI):
443
443
  'info': market,
444
444
  }
445
445
 
446
- async def fetch_trading_fees(self, params={}):
446
+ async def fetch_trading_fees(self, params={}) -> TradingFees:
447
447
  """
448
448
  fetch the trading fees for multiple markets
449
449
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.phemex import ImplicitAPI
8
8
  import hashlib
9
9
  import numbers
10
- from ccxt.base.types import Balances, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
+ from ccxt.base.types import Balances, Currencies, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import PermissionDenied
@@ -971,7 +971,7 @@ class phemex(Exchange, ImplicitAPI):
971
971
  result.append(market)
972
972
  return result
973
973
 
974
- async def fetch_currencies(self, params={}):
974
+ async def fetch_currencies(self, params={}) -> Currencies:
975
975
  """
976
976
  fetches all available currencies on an exchange
977
977
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -3792,6 +3792,7 @@ class phemex(Exchange, ImplicitAPI):
3792
3792
  'info': data,
3793
3793
  'symbol': self.safe_symbol(None, market),
3794
3794
  'type': 'set',
3795
+ 'marginMode': 'isolated',
3795
3796
  'amount': None,
3796
3797
  'total': None,
3797
3798
  'code': market[codeCurrency],
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.poloniex import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
+ from ccxt.base.types import Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import PermissionDenied
@@ -671,7 +671,7 @@ class poloniex(Exchange, ImplicitAPI):
671
671
  #
672
672
  return self.parse_tickers(response, symbols)
673
673
 
674
- async def fetch_currencies(self, params={}):
674
+ async def fetch_currencies(self, params={}) -> Currencies:
675
675
  """
676
676
  fetches all available currencies on an exchange
677
677
  :see: https://docs.poloniex.com/#public-endpoints-reference-data-currency-information
@@ -1570,7 +1570,7 @@ class poloniex(Exchange, ImplicitAPI):
1570
1570
  #
1571
1571
  return self.parse_balance(response)
1572
1572
 
1573
- async def fetch_trading_fees(self, params={}):
1573
+ async def fetch_trading_fees(self, params={}) -> TradingFees:
1574
1574
  """
1575
1575
  fetch the trading fees for multiple markets
1576
1576
  :see: https://docs.poloniex.com/#authenticated-endpoints-accounts-fee-info
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.probit import ImplicitAPI
8
8
  import math
9
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
9
+ from ccxt.base.types import Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import ArgumentsRequired
@@ -355,7 +355,7 @@ class probit(Exchange, ImplicitAPI):
355
355
  'info': market,
356
356
  }
357
357
 
358
- async def fetch_currencies(self, params={}):
358
+ async def fetch_currencies(self, params={}) -> Currencies:
359
359
  """
360
360
  :see: https://docs-en.probit.com/reference/currency
361
361
  fetches all available currencies on an exchange
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.timex import ImplicitAPI
8
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
8
+ from ccxt.base.types import Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction
9
9
  from typing import List
10
10
  from ccxt.base.errors import ExchangeError
11
11
  from ccxt.base.errors import PermissionDenied
@@ -323,7 +323,7 @@ class timex(Exchange, ImplicitAPI):
323
323
  #
324
324
  return self.parse_markets(response)
325
325
 
326
- async def fetch_currencies(self, params={}):
326
+ async def fetch_currencies(self, params={}) -> Currencies:
327
327
  """
328
328
  fetches all available currencies on an exchange
329
329
  :see: https://plasma-relay-backend.timex.io/swagger-ui/index.html?urls.primaryName=Relay#/Public/listCurrencies
@@ -1096,7 +1096,7 @@ class timex(Exchange, ImplicitAPI):
1096
1096
  trades = self.safe_list(response, 'trades', [])
1097
1097
  return self.parse_trades(trades, market, since, limit)
1098
1098
 
1099
- def parse_trading_fee(self, fee, market: Market = None):
1099
+ def parse_trading_fee(self, fee, market: Market = None) -> TradingFeeInterface:
1100
1100
  #
1101
1101
  # {
1102
1102
  # "fee": 0.0075,
@@ -1110,9 +1110,11 @@ class timex(Exchange, ImplicitAPI):
1110
1110
  'symbol': self.safe_symbol(marketId, market),
1111
1111
  'maker': rate,
1112
1112
  'taker': rate,
1113
+ 'percentage': None,
1114
+ 'tierBased': None,
1113
1115
  }
1114
1116
 
1115
- async def fetch_trading_fee(self, symbol: str, params={}):
1117
+ async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
1116
1118
  """
1117
1119
  fetch the trading fees for a market
1118
1120
  :see: https://plasma-relay-backend.timex.io/swagger-ui/index.html?urls.primaryName=Relay#/Trading/getFees
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.upbit import ImplicitAPI
8
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
8
+ from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction
9
9
  from typing import List
10
10
  from ccxt.base.errors import ExchangeError
11
11
  from ccxt.base.errors import PermissionDenied
@@ -836,7 +836,7 @@ class upbit(Exchange, ImplicitAPI):
836
836
  #
837
837
  return self.parse_trades(response, market, since, limit)
838
838
 
839
- async def fetch_trading_fee(self, symbol: str, params={}):
839
+ async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
840
840
  """
841
841
  :see: https://docs.upbit.com/reference/%EC%A3%BC%EB%AC%B8-%EA%B0%80%EB%8A%A5-%EC%A0%95%EB%B3%B4
842
842
  fetch the trading fees for a market
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.wazirx import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
9
+ from ccxt.base.types import Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import PermissionDenied
@@ -882,7 +882,7 @@ class wazirx(Exchange, ImplicitAPI):
882
882
  }
883
883
  return self.safe_string(statuses, status, status)
884
884
 
885
- async def fetch_currencies(self, params={}):
885
+ async def fetch_currencies(self, params={}) -> Currencies:
886
886
  """
887
887
  fetches all available currencies on an exchange
888
888
  :see: https://docs.wazirx.com/#all-coins-39-information-user_data
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.whitebit import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Bool, Currency, Int, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
+ from ccxt.base.types import Balances, Bool, Currencies, Currency, Int, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import PermissionDenied
@@ -401,7 +401,7 @@ class whitebit(Exchange, ImplicitAPI):
401
401
  'info': market,
402
402
  }
403
403
 
404
- async def fetch_currencies(self, params={}):
404
+ async def fetch_currencies(self, params={}) -> Currencies:
405
405
  """
406
406
  fetches all available currencies on an exchange
407
407
  :see: https://docs.whitebit.com/public/http-v4/#asset-status-list
@@ -652,7 +652,7 @@ class whitebit(Exchange, ImplicitAPI):
652
652
  depositWithdrawFees[code] = self.assign_default_deposit_withdraw_fees(depositWithdrawFees[code], currency)
653
653
  return depositWithdrawFees
654
654
 
655
- async def fetch_trading_fees(self, params={}):
655
+ async def fetch_trading_fees(self, params={}) -> TradingFees:
656
656
  """
657
657
  fetch the trading fees for multiple markets
658
658
  :see: https://docs.whitebit.com/public/http-v4/#asset-status-list
ccxt/async_support/woo.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.woo import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Account, Balances, Bool, Currency, Int, Leverage, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Trade, Transaction, TransferEntry
9
+ from ccxt.base.types import Account, Balances, Bool, Currencies, Currency, Int, Leverage, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Trade, TradingFees, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import ArgumentsRequired
@@ -77,6 +77,7 @@ class woo(Exchange, ImplicitAPI):
77
77
  'fetchIndexOHLCV': False,
78
78
  'fetchLedger': True,
79
79
  'fetchLeverage': True,
80
+ 'fetchMarginAdjustmentHistory': False,
80
81
  'fetchMarginMode': False,
81
82
  'fetchMarkets': True,
82
83
  'fetchMarkOHLCV': False,
@@ -620,7 +621,7 @@ class woo(Exchange, ImplicitAPI):
620
621
  }
621
622
  return fee
622
623
 
623
- async def fetch_trading_fees(self, params={}):
624
+ async def fetch_trading_fees(self, params={}) -> TradingFees:
624
625
  """
625
626
  fetch the trading fees for multiple markets
626
627
  :see: https://docs.woo.org/#get-account-information-new
@@ -673,7 +674,7 @@ class woo(Exchange, ImplicitAPI):
673
674
  }
674
675
  return result
675
676
 
676
- async def fetch_currencies(self, params={}):
677
+ async def fetch_currencies(self, params={}) -> Currencies:
677
678
  """
678
679
  fetches all available currencies on an exchange
679
680
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.yobit import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade
9
+ from ccxt.base.types import Balances, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import ArgumentsRequired
@@ -700,7 +700,7 @@ class yobit(Exchange, ImplicitAPI):
700
700
  result = self.safe_list(response, market['id'], [])
701
701
  return self.parse_trades(result, market, since, limit)
702
702
 
703
- async def fetch_trading_fees(self, params={}):
703
+ async def fetch_trading_fees(self, params={}) -> TradingFees:
704
704
  """
705
705
  :see: https://yobit.net/en/api
706
706
  fetch the trading fees for multiple markets
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.2.88'
7
+ __version__ = '4.2.90'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -39,6 +39,7 @@ from ccxt.base.types import BalanceAccount, Currency, IndexType, OrderSide, Orde
39
39
  from cryptography.hazmat import backends
40
40
  from cryptography.hazmat.primitives import hashes
41
41
  from cryptography.hazmat.primitives.asymmetric import padding
42
+ # from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature
42
43
  from cryptography.hazmat.primitives.serialization import load_pem_private_key
43
44
 
44
45
  # -----------------------------------------------------------------------------
@@ -1314,22 +1315,33 @@ class Exchange(object):
1314
1315
  return Exchange.decode(base64.b64decode(s))
1315
1316
 
1316
1317
  @staticmethod
1317
- def jwt(request, secret, algorithm='sha256', is_rsa=False):
1318
+ def jwt(request, secret, algorithm='sha256', is_rsa=False, opts={}):
1318
1319
  algos = {
1319
1320
  'sha256': hashlib.sha256,
1320
1321
  'sha384': hashlib.sha384,
1321
1322
  'sha512': hashlib.sha512,
1322
1323
  }
1323
1324
  alg = ('RS' if is_rsa else 'HS') + algorithm[3:]
1324
- header = Exchange.encode(Exchange.json({
1325
+ if 'alg' in opts and opts['alg'] is not None:
1326
+ alg = opts['alg']
1327
+ header_opts = {
1325
1328
  'alg': alg,
1326
1329
  'typ': 'JWT',
1327
- }))
1330
+ }
1331
+ if 'kid' in opts and opts['kid'] is not None:
1332
+ header_opts['kid'] = opts['kid']
1333
+ if 'nonce' in opts and opts['nonce'] is not None:
1334
+ header_opts['nonce'] = opts['nonce']
1335
+ header = Exchange.encode(Exchange.json(header_opts))
1328
1336
  encoded_header = Exchange.base64urlencode(header)
1329
1337
  encoded_data = Exchange.base64urlencode(Exchange.encode(Exchange.json(request)))
1330
1338
  token = encoded_header + '.' + encoded_data
1331
- if is_rsa:
1339
+ algoType = alg[0:2]
1340
+ if is_rsa or algoType == 'RS':
1332
1341
  signature = Exchange.base64_to_binary(Exchange.rsa(token, Exchange.decode(secret), algorithm))
1342
+ elif algoType == 'ES':
1343
+ rawSignature = Exchange.ecdsa(token, secret, 'p256', algorithm)
1344
+ signature = Exchange.base16_to_binary(rawSignature['r'] + rawSignature['s'])
1333
1345
  else:
1334
1346
  signature = Exchange.hmac(Exchange.encode(token), secret, algos[algorithm], 'binary')
1335
1347
  return token + '.' + Exchange.base64urlencode(signature)
@@ -1362,6 +1374,10 @@ class Exchange(object):
1362
1374
  def int_to_base16(num):
1363
1375
  return "%0.2X" % num
1364
1376
 
1377
+ @staticmethod
1378
+ def random_bytes(length):
1379
+ return format(random.getrandbits(length * 8), 'x')
1380
+
1365
1381
  @staticmethod
1366
1382
  def ecdsa(request, secret, algorithm='p256', hash=None, fixed_length=False):
1367
1383
  # your welcome - frosty00
@@ -1382,7 +1398,12 @@ class Exchange(object):
1382
1398
  digest = Exchange.hash(encoded_request, hash, 'binary')
1383
1399
  else:
1384
1400
  digest = base64.b16decode(encoded_request, casefold=True)
1385
- key = ecdsa.SigningKey.from_string(base64.b16decode(Exchange.encode(secret),
1401
+ if isinstance(secret, str):
1402
+ secret = Exchange.encode(secret)
1403
+ if secret.find(b'-----BEGIN EC PRIVATE KEY-----') > -1:
1404
+ key = ecdsa.SigningKey.from_pem(secret, hash_function)
1405
+ else:
1406
+ key = ecdsa.SigningKey.from_string(base64.b16decode(secret,
1386
1407
  casefold=True), curve=curve_info[0])
1387
1408
  r_binary, s_binary, v = key.sign_digest_deterministic(digest, hashfunc=hash_function,
1388
1409
  sigencode=ecdsa.util.sigencode_strings_canonize)
@@ -2249,6 +2270,18 @@ class Exchange(object):
2249
2270
  def set_margin(self, symbol: str, amount: float, params={}):
2250
2271
  raise NotSupported(self.id + ' setMargin() is not supported yet')
2251
2272
 
2273
+ def fetch_margin_adjustment_history(self, symbol: Str = None, type: Str = None, since: Num = None, limit: Num = None, params={}):
2274
+ """
2275
+ fetches the history of margin added or reduced from contract isolated positions
2276
+ :param str [symbol]: unified market symbol
2277
+ :param str [type]: "add" or "reduce"
2278
+ :param int [since]: timestamp in ms of the earliest change to fetch
2279
+ :param int [limit]: the maximum amount of changes to fetch
2280
+ :param dict params: extra parameters specific to the exchange api endpoint
2281
+ :returns dict[]: a list of `margin structures <https://docs.ccxt.com/#/?id=margin-loan-structure>`
2282
+ """
2283
+ raise NotSupported(self.id + ' fetchMarginAdjustmentHistory() is not supported yet')
2284
+
2252
2285
  def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
2253
2286
  raise NotSupported(self.id + ' setMarginMode() is not supported yet')
2254
2287
 
@@ -3732,11 +3765,11 @@ class Exchange(object):
3732
3765
  code = currencyId
3733
3766
  if currencyId is not None:
3734
3767
  code = self.common_currency_code(currencyId.upper())
3735
- return {
3768
+ return self.safe_currency_structure({
3736
3769
  'id': currencyId,
3737
3770
  'code': code,
3738
3771
  'precision': None,
3739
- }
3772
+ })
3740
3773
 
3741
3774
  def safe_market(self, marketId: Str, market: Market = None, delimiter: Str = None, marketType: Str = None):
3742
3775
  result = self.safe_market_structure({
@@ -4390,10 +4423,16 @@ class Exchange(object):
4390
4423
  'total': None,
4391
4424
  }
4392
4425
 
4393
- def common_currency_code(self, currency: str):
4426
+ def common_currency_code(self, code: str):
4394
4427
  if not self.substituteCommonCurrencyCodes:
4395
- return currency
4396
- return self.safe_string(self.commonCurrencies, currency, currency)
4428
+ return code
4429
+ # if the provided code already exists value in commonCurrencies dict, then we should not again transform it
4430
+ # more details at: https://github.com/ccxt/ccxt/issues/21112#issuecomment-2031293691
4431
+ commonCurrencies = list(self.commonCurrencies.values())
4432
+ exists = self.in_array(code, commonCurrencies)
4433
+ if exists:
4434
+ return code
4435
+ return self.safe_string(self.commonCurrencies, code, code)
4397
4436
 
4398
4437
  def currency(self, code: str):
4399
4438
  if self.currencies is None:
@@ -4791,7 +4830,8 @@ class Exchange(object):
4791
4830
  def fetch_trading_fee(self, symbol: str, params={}):
4792
4831
  if not self.has['fetchTradingFees']:
4793
4832
  raise NotSupported(self.id + ' fetchTradingFee() is not supported yet')
4794
- return self.fetch_trading_fees(params)
4833
+ fees = self.fetch_trading_fees(params)
4834
+ return self.safe_dict(fees, symbol)
4795
4835
 
4796
4836
  def parse_open_interest(self, interest, market: Market = None):
4797
4837
  raise NotSupported(self.id + ' parseOpenInterest() is not supported yet')
@@ -5440,3 +5480,16 @@ class Exchange(object):
5440
5480
  day = date[5:7]
5441
5481
  reconstructedDate = day + month + year
5442
5482
  return reconstructedDate
5483
+
5484
+ def parse_margin_modification(self, data, market: Market = None):
5485
+ raise NotSupported(self.id + ' parseMarginModification() is not supported yet')
5486
+
5487
+ def parse_margin_modifications(self, response: List[object], symbols: List[str] = None, symbolKey: Str = None, marketType: MarketType = None):
5488
+ marginModifications = []
5489
+ for i in range(0, len(response)):
5490
+ info = response[i]
5491
+ marketId = self.safe_string(info, symbolKey)
5492
+ market = self.safe_market(marketId, None, None, marketType)
5493
+ if (symbols is None) or self.in_array(market['symbol'], symbols):
5494
+ marginModifications.append(self.parse_margin_modification(info, market))
5495
+ return marginModifications