ccxt 4.3.17__py2.py3-none-any.whl → 4.3.19__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 (195) hide show
  1. ccxt/__init__.py +3 -1
  2. ccxt/abstract/bybit.py +1 -0
  3. ccxt/abstract/okx.py +1 -0
  4. ccxt/abstract/woofipro.py +119 -0
  5. ccxt/ace.py +1 -1
  6. ccxt/ascendex.py +7 -8
  7. ccxt/async_support/__init__.py +3 -1
  8. ccxt/async_support/ace.py +1 -1
  9. ccxt/async_support/ascendex.py +7 -8
  10. ccxt/async_support/base/exchange.py +23 -2
  11. ccxt/async_support/bigone.py +4 -4
  12. ccxt/async_support/binance.py +34 -17
  13. ccxt/async_support/bingx.py +4 -4
  14. ccxt/async_support/bit2c.py +1 -1
  15. ccxt/async_support/bitbank.py +1 -1
  16. ccxt/async_support/bitbns.py +1 -1
  17. ccxt/async_support/bitfinex.py +28 -4
  18. ccxt/async_support/bitfinex2.py +62 -54
  19. ccxt/async_support/bitflyer.py +1 -1
  20. ccxt/async_support/bitget.py +8 -11
  21. ccxt/async_support/bithumb.py +1 -1
  22. ccxt/async_support/bitmart.py +8 -8
  23. ccxt/async_support/bitmex.py +2 -2
  24. ccxt/async_support/bitopro.py +1 -1
  25. ccxt/async_support/bitrue.py +3 -3
  26. ccxt/async_support/bitso.py +1 -1
  27. ccxt/async_support/bitstamp.py +3 -5
  28. ccxt/async_support/bitteam.py +1 -1
  29. ccxt/async_support/bitvavo.py +1 -1
  30. ccxt/async_support/bl3p.py +1 -1
  31. ccxt/async_support/blockchaincom.py +1 -1
  32. ccxt/async_support/blofin.py +3 -3
  33. ccxt/async_support/btcalpha.py +1 -1
  34. ccxt/async_support/btcbox.py +1 -1
  35. ccxt/async_support/btcmarkets.py +1 -1
  36. ccxt/async_support/btcturk.py +1 -1
  37. ccxt/async_support/bybit.py +9 -8
  38. ccxt/async_support/cex.py +1 -1
  39. ccxt/async_support/coinbase.py +2 -2
  40. ccxt/async_support/coinbasepro.py +1 -1
  41. ccxt/async_support/coincheck.py +1 -1
  42. ccxt/async_support/coinex.py +320 -520
  43. ccxt/async_support/coinlist.py +6 -7
  44. ccxt/async_support/coinmate.py +1 -1
  45. ccxt/async_support/coinmetro.py +1 -1
  46. ccxt/async_support/coinone.py +1 -1
  47. ccxt/async_support/coinsph.py +1 -1
  48. ccxt/async_support/coinspot.py +1 -1
  49. ccxt/async_support/cryptocom.py +1 -1
  50. ccxt/async_support/currencycom.py +2 -2
  51. ccxt/async_support/delta.py +4 -4
  52. ccxt/async_support/deribit.py +8 -8
  53. ccxt/async_support/digifinex.py +5 -5
  54. ccxt/async_support/exmo.py +1 -1
  55. ccxt/async_support/gate.py +5 -5
  56. ccxt/async_support/gemini.py +1 -1
  57. ccxt/async_support/hitbtc.py +3 -3
  58. ccxt/async_support/hollaex.py +4 -4
  59. ccxt/async_support/htx.py +4 -4
  60. ccxt/async_support/huobijp.py +1 -1
  61. ccxt/async_support/idex.py +1 -1
  62. ccxt/async_support/independentreserve.py +1 -1
  63. ccxt/async_support/indodax.py +2 -2
  64. ccxt/async_support/kraken.py +2 -2
  65. ccxt/async_support/krakenfutures.py +3 -3
  66. ccxt/async_support/kucoin.py +3 -3
  67. ccxt/async_support/kucoinfutures.py +3 -3
  68. ccxt/async_support/kuna.py +1 -1
  69. ccxt/async_support/latoken.py +6 -6
  70. ccxt/async_support/lbank.py +1 -1
  71. ccxt/async_support/luno.py +1 -1
  72. ccxt/async_support/lykke.py +1 -1
  73. ccxt/async_support/mercado.py +1 -1
  74. ccxt/async_support/mexc.py +7 -7
  75. ccxt/async_support/ndax.py +1 -1
  76. ccxt/async_support/novadax.py +3 -4
  77. ccxt/async_support/okcoin.py +3 -3
  78. ccxt/async_support/okx.py +27 -10
  79. ccxt/async_support/onetrading.py +1 -1
  80. ccxt/async_support/paymium.py +3 -3
  81. ccxt/async_support/phemex.py +5 -5
  82. ccxt/async_support/poloniex.py +3 -4
  83. ccxt/async_support/poloniexfutures.py +1 -1
  84. ccxt/async_support/probit.py +1 -1
  85. ccxt/async_support/timex.py +1 -1
  86. ccxt/async_support/tokocrypto.py +1 -1
  87. ccxt/async_support/upbit.py +1 -1
  88. ccxt/async_support/wavesexchange.py +3 -3
  89. ccxt/async_support/wazirx.py +1 -1
  90. ccxt/async_support/whitebit.py +2 -2
  91. ccxt/async_support/woo.py +25 -10
  92. ccxt/async_support/woofipro.py +2524 -0
  93. ccxt/async_support/yobit.py +1 -1
  94. ccxt/async_support/zaif.py +1 -1
  95. ccxt/async_support/zonda.py +3 -3
  96. ccxt/base/exchange.py +63 -17
  97. ccxt/base/types.py +20 -0
  98. ccxt/bigone.py +4 -4
  99. ccxt/binance.py +34 -17
  100. ccxt/bingx.py +4 -4
  101. ccxt/bit2c.py +1 -1
  102. ccxt/bitbank.py +1 -1
  103. ccxt/bitbns.py +1 -1
  104. ccxt/bitfinex.py +28 -4
  105. ccxt/bitfinex2.py +62 -54
  106. ccxt/bitflyer.py +1 -1
  107. ccxt/bitget.py +8 -11
  108. ccxt/bithumb.py +1 -1
  109. ccxt/bitmart.py +8 -8
  110. ccxt/bitmex.py +2 -2
  111. ccxt/bitopro.py +1 -1
  112. ccxt/bitrue.py +3 -3
  113. ccxt/bitso.py +1 -1
  114. ccxt/bitstamp.py +3 -5
  115. ccxt/bitteam.py +1 -1
  116. ccxt/bitvavo.py +1 -1
  117. ccxt/bl3p.py +1 -1
  118. ccxt/blockchaincom.py +1 -1
  119. ccxt/blofin.py +3 -3
  120. ccxt/btcalpha.py +1 -1
  121. ccxt/btcbox.py +1 -1
  122. ccxt/btcmarkets.py +1 -1
  123. ccxt/btcturk.py +1 -1
  124. ccxt/bybit.py +9 -8
  125. ccxt/cex.py +1 -1
  126. ccxt/coinbase.py +2 -2
  127. ccxt/coinbasepro.py +1 -1
  128. ccxt/coincheck.py +1 -1
  129. ccxt/coinex.py +320 -520
  130. ccxt/coinlist.py +6 -7
  131. ccxt/coinmate.py +1 -1
  132. ccxt/coinmetro.py +1 -1
  133. ccxt/coinone.py +1 -1
  134. ccxt/coinsph.py +1 -1
  135. ccxt/coinspot.py +1 -1
  136. ccxt/cryptocom.py +1 -1
  137. ccxt/currencycom.py +2 -2
  138. ccxt/delta.py +4 -4
  139. ccxt/deribit.py +8 -8
  140. ccxt/digifinex.py +5 -5
  141. ccxt/exmo.py +1 -1
  142. ccxt/gate.py +5 -5
  143. ccxt/gemini.py +1 -1
  144. ccxt/hitbtc.py +3 -3
  145. ccxt/hollaex.py +4 -4
  146. ccxt/htx.py +4 -4
  147. ccxt/huobijp.py +1 -1
  148. ccxt/idex.py +1 -1
  149. ccxt/independentreserve.py +1 -1
  150. ccxt/indodax.py +2 -2
  151. ccxt/kraken.py +2 -2
  152. ccxt/krakenfutures.py +3 -3
  153. ccxt/kucoin.py +3 -3
  154. ccxt/kucoinfutures.py +3 -3
  155. ccxt/kuna.py +1 -1
  156. ccxt/latoken.py +6 -6
  157. ccxt/lbank.py +1 -1
  158. ccxt/luno.py +1 -1
  159. ccxt/lykke.py +1 -1
  160. ccxt/mercado.py +1 -1
  161. ccxt/mexc.py +7 -7
  162. ccxt/ndax.py +1 -1
  163. ccxt/novadax.py +3 -4
  164. ccxt/okcoin.py +3 -3
  165. ccxt/okx.py +27 -10
  166. ccxt/onetrading.py +1 -1
  167. ccxt/paymium.py +3 -3
  168. ccxt/phemex.py +5 -5
  169. ccxt/poloniex.py +3 -4
  170. ccxt/poloniexfutures.py +1 -1
  171. ccxt/pro/__init__.py +3 -1
  172. ccxt/pro/bitget.py +127 -190
  173. ccxt/pro/bitvavo.py +1 -1
  174. ccxt/pro/bybit.py +4 -3
  175. ccxt/pro/coinbaseinternational.py +11 -4
  176. ccxt/pro/okx.py +79 -1
  177. ccxt/pro/woofipro.py +1183 -0
  178. ccxt/probit.py +1 -1
  179. ccxt/test/test_async.py +31 -1
  180. ccxt/test/test_sync.py +31 -1
  181. ccxt/timex.py +1 -1
  182. ccxt/tokocrypto.py +1 -1
  183. ccxt/upbit.py +1 -1
  184. ccxt/wavesexchange.py +3 -3
  185. ccxt/wazirx.py +1 -1
  186. ccxt/whitebit.py +2 -2
  187. ccxt/woo.py +25 -10
  188. ccxt/woofipro.py +2524 -0
  189. ccxt/yobit.py +1 -1
  190. ccxt/zaif.py +1 -1
  191. ccxt/zonda.py +3 -3
  192. {ccxt-4.3.17.dist-info → ccxt-4.3.19.dist-info}/METADATA +8 -6
  193. {ccxt-4.3.17.dist-info → ccxt-4.3.19.dist-info}/RECORD +195 -191
  194. {ccxt-4.3.17.dist-info → ccxt-4.3.19.dist-info}/WHEEL +0 -0
  195. {ccxt-4.3.17.dist-info → ccxt-4.3.19.dist-info}/top_level.txt +0 -0
@@ -502,7 +502,7 @@ class yobit(Exchange, ImplicitAPI):
502
502
  result[symbol] = self.parse_order_book(response[id], symbol)
503
503
  return result
504
504
 
505
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
505
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
506
506
  #
507
507
  # {
508
508
  # "high": 0.03497582,
@@ -282,7 +282,7 @@ class zaif(Exchange, ImplicitAPI):
282
282
  response = await self.publicGetDepthPair(self.extend(request, params))
283
283
  return self.parse_order_book(response, market['symbol'])
284
284
 
285
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
285
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
286
286
  #
287
287
  # {
288
288
  # "last": 9e-08,
@@ -588,7 +588,7 @@ class zonda(Exchange, ImplicitAPI):
588
588
  'nonce': self.safe_integer(response, 'seqNo'),
589
589
  }
590
590
 
591
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
591
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
592
592
  #
593
593
  # version 1
594
594
  #
@@ -1595,7 +1595,7 @@ class zonda(Exchange, ImplicitAPI):
1595
1595
  transfer['amount'] = amount
1596
1596
  return transfer
1597
1597
 
1598
- def parse_transfer(self, transfer, currency: Currency = None):
1598
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
1599
1599
  #
1600
1600
  # {
1601
1601
  # "status": "Ok",
@@ -1642,7 +1642,7 @@ class zonda(Exchange, ImplicitAPI):
1642
1642
  'status': self.parse_transfer_status(status),
1643
1643
  }
1644
1644
 
1645
- def parse_transfer_status(self, status):
1645
+ def parse_transfer_status(self, status: Str) -> Str:
1646
1646
  statuses = {
1647
1647
  'Ok': 'ok',
1648
1648
  'Fail': 'failed',
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.3.17'
7
+ __version__ = '4.3.19'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -38,7 +38,7 @@ from ccxt.base.types import BalanceAccount, Currency, IndexType, OrderSide, Orde
38
38
  # rsa jwt signing
39
39
  from cryptography.hazmat import backends
40
40
  from cryptography.hazmat.primitives import hashes
41
- from cryptography.hazmat.primitives.asymmetric import padding
41
+ from cryptography.hazmat.primitives.asymmetric import padding, ed25519
42
42
  # from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature
43
43
  from cryptography.hazmat.primitives.serialization import load_pem_private_key
44
44
 
@@ -199,6 +199,7 @@ class Exchange(object):
199
199
  secret = ''
200
200
  password = ''
201
201
  uid = ''
202
+ accountId = None
202
203
  privateKey = '' # a "0x"-prefixed hexstring private key for a wallet
203
204
  walletAddress = '' # the wallet address "0x"-prefixed hexstring
204
205
  token = '' # reserved for HTTP auth in some cases
@@ -261,6 +262,7 @@ class Exchange(object):
261
262
  transactions = None
262
263
  ohlcvs = None
263
264
  tickers = None
265
+ fundingRates = None
264
266
  bidsasks = None
265
267
  base_currencies = None
266
268
  quote_currencies = None
@@ -273,6 +275,7 @@ class Exchange(object):
273
275
  'apiKey': True,
274
276
  'secret': True,
275
277
  'uid': False,
278
+ 'accountId': False,
276
279
  'login': False,
277
280
  'password': False,
278
281
  'twofa': False, # 2-factor authentication (one-time password key)
@@ -316,7 +319,15 @@ class Exchange(object):
316
319
  'fetchCanceledOrders': None,
317
320
  'fetchClosedOrder': None,
318
321
  'fetchClosedOrders': None,
322
+ 'fetchClosedOrdersWs': None,
323
+ 'fetchConvertCurrencies': None,
324
+ 'fetchConvertQuote': None,
325
+ 'fetchConvertTrade': None,
326
+ 'fetchConvertTradeHistory': None,
327
+ 'fetchCrossBorrowRate': None,
328
+ 'fetchCrossBorrowRates': None,
319
329
  'fetchCurrencies': 'emulated',
330
+ 'fetchCurrenciesWs': 'emulated',
320
331
  'fetchDeposit': None,
321
332
  'fetchDepositAddress': None,
322
333
  'fetchDepositAddresses': None,
@@ -430,6 +441,7 @@ class Exchange(object):
430
441
  self.headers = dict() if self.headers is None else self.headers
431
442
  self.balance = dict() if self.balance is None else self.balance
432
443
  self.orderbooks = dict() if self.orderbooks is None else self.orderbooks
444
+ self.fundingRates = dict() if self.fundingRates is None else self.fundingRates
433
445
  self.tickers = dict() if self.tickers is None else self.tickers
434
446
  self.bidsasks = dict() if self.bidsasks is None else self.bidsasks
435
447
  self.trades = dict() if self.trades is None else self.trades
@@ -1299,7 +1311,7 @@ class Exchange(object):
1299
1311
  return result
1300
1312
 
1301
1313
  @staticmethod
1302
- def base64urlencode(s):
1314
+ def urlencode_base64(s):
1303
1315
  return Exchange.decode(base64.urlsafe_b64encode(s)).replace('=', '')
1304
1316
 
1305
1317
  @staticmethod
@@ -1337,8 +1349,8 @@ class Exchange(object):
1337
1349
  if 'nonce' in opts and opts['nonce'] is not None:
1338
1350
  header_opts['nonce'] = opts['nonce']
1339
1351
  header = Exchange.encode(Exchange.json(header_opts))
1340
- encoded_header = Exchange.base64urlencode(header)
1341
- encoded_data = Exchange.base64urlencode(Exchange.encode(Exchange.json(request)))
1352
+ encoded_header = Exchange.urlencode_base64(header)
1353
+ encoded_data = Exchange.urlencode_base64(Exchange.encode(Exchange.json(request)))
1342
1354
  token = encoded_header + '.' + encoded_data
1343
1355
  algoType = alg[0:2]
1344
1356
  if is_rsa or algoType == 'RS':
@@ -1348,7 +1360,7 @@ class Exchange(object):
1348
1360
  signature = Exchange.base16_to_binary(rawSignature['r'].rjust(64, "0") + rawSignature['s'].rjust(64, "0"))
1349
1361
  else:
1350
1362
  signature = Exchange.hmac(Exchange.encode(token), secret, algos[algorithm], 'binary')
1351
- return token + '.' + Exchange.base64urlencode(signature)
1363
+ return token + '.' + Exchange.urlencode_base64(signature)
1352
1364
 
1353
1365
  @staticmethod
1354
1366
  def rsa(request, secret, alg='sha256'):
@@ -1430,7 +1442,9 @@ class Exchange(object):
1430
1442
 
1431
1443
  @staticmethod
1432
1444
  def eddsa(request, secret, curve='ed25519'):
1433
- private_key = load_pem_private_key(Exchange.encode(secret), None)
1445
+ if isinstance(secret, str):
1446
+ Exchange.encode(secret)
1447
+ private_key = ed25519.Ed25519PrivateKey.from_private_bytes(secret) if len(secret) == 32 else load_pem_private_key(secret, None)
1434
1448
  return Exchange.binary_to_base64(private_key.sign(request))
1435
1449
 
1436
1450
  @staticmethod
@@ -2171,7 +2185,7 @@ class Exchange(object):
2171
2185
  result.append(self.parse_market(markets[i]))
2172
2186
  return result
2173
2187
 
2174
- def parse_ticker(self, ticker: object, market: Market = None):
2188
+ def parse_ticker(self, ticker: dict, market: Market = None):
2175
2189
  raise NotSupported(self.id + ' parseTicker() is not supported yet')
2176
2190
 
2177
2191
  def parse_deposit_address(self, depositAddress, currency: Currency = None):
@@ -2183,7 +2197,7 @@ class Exchange(object):
2183
2197
  def parse_transaction(self, transaction, currency: Currency = None):
2184
2198
  raise NotSupported(self.id + ' parseTransaction() is not supported yet')
2185
2199
 
2186
- def parse_transfer(self, transfer, currency: Currency = None):
2200
+ def parse_transfer(self, transfer: dict, currency: Currency = None):
2187
2201
  raise NotSupported(self.id + ' parseTransfer() is not supported yet')
2188
2202
 
2189
2203
  def parse_account(self, account):
@@ -2330,6 +2344,12 @@ class Exchange(object):
2330
2344
  res = self.parse_to_numeric((value % 1))
2331
2345
  return res == 0
2332
2346
 
2347
+ def safe_integer_omit_zero(self, obj: object, key: IndexType, defaultValue: Int = None):
2348
+ timestamp = self.safe_integer(obj, key, defaultValue)
2349
+ if timestamp is None or timestamp == 0:
2350
+ return None
2351
+ return timestamp
2352
+
2333
2353
  def after_construct(self):
2334
2354
  self.create_networks_by_id_object()
2335
2355
 
@@ -3362,7 +3382,7 @@ class Exchange(object):
3362
3382
  networkId = networkCode
3363
3383
  return networkId
3364
3384
 
3365
- def network_id_to_code(self, networkId: str, currencyCode: Str = None):
3385
+ def network_id_to_code(self, networkId: Str = None, currencyCode: Str = None):
3366
3386
  """
3367
3387
  * @ignore
3368
3388
  tries to convert the provided exchange-specific networkId to an unified network Code. In order to achieve self, derived class needs to have "options['networksById']" defined.
@@ -3781,7 +3801,7 @@ class Exchange(object):
3781
3801
  def fetch_positions_risk(self, symbols: List[str] = None, params={}):
3782
3802
  raise NotSupported(self.id + ' fetchPositionsRisk() is not supported yet')
3783
3803
 
3784
- def fetch_bids_asks(self, symbols: List[str] = None, params={}):
3804
+ def fetch_bids_asks(self, symbols: Strings = None, params={}):
3785
3805
  raise NotSupported(self.id + ' fetchBidsAsks() is not supported yet')
3786
3806
 
3787
3807
  def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
@@ -4954,10 +4974,11 @@ class Exchange(object):
4954
4974
  symbols = self.market_symbols(symbols)
4955
4975
  return self.filter_by_array(results, 'symbol', symbols)
4956
4976
 
4957
- def parse_tickers(self, tickers, symbols: List[str] = None, params={}):
4977
+ def parse_tickers(self, tickers, symbols: Strings = None, params={}):
4958
4978
  #
4959
4979
  # the value of tickers is either a dict or a list
4960
4980
  #
4981
+ #
4961
4982
  # dict
4962
4983
  #
4963
4984
  # {
@@ -5041,12 +5062,16 @@ class Exchange(object):
5041
5062
  result[parsed['symbol']] = parsed
5042
5063
  return result
5043
5064
 
5044
- def is_trigger_order(self, params):
5065
+ def handle_trigger_and_params(self, params):
5045
5066
  isTrigger = self.safe_bool_2(params, 'trigger', 'stop')
5046
5067
  if isTrigger:
5047
5068
  params = self.omit(params, ['trigger', 'stop'])
5048
5069
  return [isTrigger, params]
5049
5070
 
5071
+ def is_trigger_order(self, params):
5072
+ # for backwards compatibility
5073
+ return self.handleTriggerAndParams(params)
5074
+
5050
5075
  def is_post_only(self, isMarketOrder: bool, exchangeSpecificParam, params={}):
5051
5076
  """
5052
5077
  * @ignore
@@ -5661,10 +5686,10 @@ class Exchange(object):
5661
5686
  symbol = self.safe_string(market, 'symbol')
5662
5687
  return self.filter_by_symbol_since_limit(sorted, symbol, since, limit)
5663
5688
 
5664
- def parse_greeks(self, greeks, market: Market = None):
5689
+ def parse_greeks(self, greeks: dict, market: Market = None):
5665
5690
  raise NotSupported(self.id + ' parseGreeks() is not supported yet')
5666
5691
 
5667
- def parse_option(self, chain, currency: Currency = None, market: Market = None):
5692
+ def parse_option(self, chain: dict, currency: Currency = None, market: Market = None):
5668
5693
  raise NotSupported(self.id + ' parseOption() is not supported yet')
5669
5694
 
5670
5695
  def parse_option_chain(self, response: List[object], currencyKey: Str = None, symbolKey: Str = None):
@@ -5701,7 +5726,7 @@ class Exchange(object):
5701
5726
  leverageStructures[market['symbol']] = self.parse_leverage(info, market)
5702
5727
  return leverageStructures
5703
5728
 
5704
- def parse_leverage(self, leverage, market: Market = None):
5729
+ def parse_leverage(self, leverage: dict, market: Market = None):
5705
5730
  raise NotSupported(self.id + ' parseLeverage() is not supported yet')
5706
5731
 
5707
5732
  def parse_conversions(self, conversions: List[Any], code: Str = None, fromCurrencyKey: Str = None, toCurrencyKey: Str = None, since: Int = None, limit: Int = None, params={}):
@@ -5731,7 +5756,7 @@ class Exchange(object):
5731
5756
  both = self.array_concat(fromConversion, toConversion)
5732
5757
  return self.filter_by_since_limit(both, since, limit)
5733
5758
 
5734
- def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None):
5759
+ def parse_conversion(self, conversion: dict, fromCurrency: Currency = None, toCurrency: Currency = None):
5735
5760
  raise NotSupported(self.id + ' parseConversion() is not supported yet')
5736
5761
 
5737
5762
  def convert_expire_date(self, date: str):
@@ -5839,3 +5864,24 @@ class Exchange(object):
5839
5864
  if (symbols is None) or self.in_array(market['symbol'], symbols):
5840
5865
  marginModifications.append(self.parse_margin_modification(info, market))
5841
5866
  return marginModifications
5867
+
5868
+ def fetch_transfer(self, id: str, code: Str = None, params={}):
5869
+ """
5870
+ fetches a transfer
5871
+ :param str id: transfer id
5872
+ :param [str] code: unified currency code
5873
+ :param dict params: extra parameters specific to the exchange api endpoint
5874
+ :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
5875
+ """
5876
+ raise NotSupported(self.id + ' fetchTransfer() is not supported yet')
5877
+
5878
+ def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
5879
+ """
5880
+ fetches a transfer
5881
+ :param str id: transfer id
5882
+ :param int [since]: timestamp in ms of the earliest transfer to fetch
5883
+ :param int [limit]: the maximum amount of transfers to fetch
5884
+ :param dict params: extra parameters specific to the exchange api endpoint
5885
+ :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
5886
+ """
5887
+ raise NotSupported(self.id + ' fetchTransfers() is not supported yet')
ccxt/base/types.py CHANGED
@@ -459,12 +459,32 @@ class IsolatedBorrowRate(TypedDict):
459
459
  timestamp: Int
460
460
  datetime: Str
461
461
 
462
+ class FundingRate(TypedDict):
463
+ symbol: Str
464
+ timestamp: Int
465
+ fundingRate: Num
466
+ datetime: Str
467
+ markPrice: Num
468
+ indexPrice: Num
469
+ interestRate: Num
470
+ estimatedSettlePrice: Num
471
+ fundingTimestamp: Int
472
+ fundingDatetime: Str
473
+ nextFundingTimestamp: Int
474
+ nextFundingDatetime: Str
475
+ nextFundingRate: Num
476
+ previousFundingTimestamp: Int
477
+ previousFundingDatetime: Str
478
+ previousFundingRate: Num
479
+ info: Dict[str, Any]
462
480
 
481
+ FundingRates = Dict[Str, FundingRate]
463
482
  LastPrices = Dict[Str, LastPrice]
464
483
  Currencies = Dict[Str, CurrencyInterface]
465
484
  TradingFees = Dict[Str, TradingFeeInterface]
466
485
  IsolatedBorrowRates = Dict[Str, IsolatedBorrowRate]
467
486
  CrossBorrowRates = Dict[Str, CrossBorrowRate]
487
+ TransferEntries = Dict[Str, TransferEntry]
468
488
 
469
489
  Market = Optional[MarketInterface]
470
490
  Currency = Optional[CurrencyInterface]
ccxt/bigone.py CHANGED
@@ -701,7 +701,7 @@ class bigone(Exchange, ImplicitAPI):
701
701
  }))
702
702
  return result
703
703
 
704
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
704
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
705
705
  #
706
706
  # spot
707
707
  #
@@ -2017,14 +2017,14 @@ class bigone(Exchange, ImplicitAPI):
2017
2017
  transfer['id'] = guid
2018
2018
  return transfer
2019
2019
 
2020
- def parse_transfer(self, transfer, currency: Currency = None):
2020
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
2021
2021
  #
2022
2022
  # {
2023
2023
  # "code": 0,
2024
2024
  # "data": null
2025
2025
  # }
2026
2026
  #
2027
- code = self.safe_number(transfer, 'code')
2027
+ code = self.safe_string(transfer, 'code')
2028
2028
  return {
2029
2029
  'info': transfer,
2030
2030
  'id': None,
@@ -2037,7 +2037,7 @@ class bigone(Exchange, ImplicitAPI):
2037
2037
  'status': self.parse_transfer_status(code),
2038
2038
  }
2039
2039
 
2040
- def parse_transfer_status(self, status):
2040
+ def parse_transfer_status(self, status: Str) -> Str:
2041
2041
  statuses = {
2042
2042
  '0': 'ok',
2043
2043
  }
ccxt/binance.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.binance import ImplicitAPI
8
8
  import hashlib
9
9
  import json
10
- from ccxt.base.types import Balances, Conversion, CrossBorrowRate, Currencies, Currency, Greeks, Int, IsolatedBorrowRate, IsolatedBorrowRates, Leverage, Leverages, MarginMode, MarginModes, MarginModification, Market, MarketInterface, Num, Option, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
10
+ from ccxt.base.types import Balances, Conversion, CrossBorrowRate, Currencies, Currency, Greeks, Int, IsolatedBorrowRate, IsolatedBorrowRates, Leverage, Leverages, MarginMode, MarginModes, MarginModification, Market, MarketInterface, Num, Option, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry, TransferEntries
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
@@ -3646,7 +3646,7 @@ class binance(Exchange, ImplicitAPI):
3646
3646
  orderbook['nonce'] = self.safe_integer_2(response, 'lastUpdateId', 'u')
3647
3647
  return orderbook
3648
3648
 
3649
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
3649
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
3650
3650
  #
3651
3651
  # {
3652
3652
  # "symbol": "ETHBTC",
@@ -5515,6 +5515,7 @@ class binance(Exchange, ImplicitAPI):
5515
5515
  :param float [params.stopLossPrice]: the price that a stop loss order is triggered at
5516
5516
  :param float [params.takeProfitPrice]: the price that a take profit order is triggered at
5517
5517
  :param boolean [params.portfolioMargin]: set to True if you would like to create an order in a portfolio margin account
5518
+ :param str [params.stopLossOrTakeProfit]: 'stopLoss' or 'takeProfit', required for spot trailing orders
5518
5519
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
5519
5520
  """
5520
5521
  self.load_markets()
@@ -5613,8 +5614,8 @@ class binance(Exchange, ImplicitAPI):
5613
5614
  stopLossPrice = self.safe_string(params, 'stopLossPrice', triggerPrice) # fallback to stopLoss
5614
5615
  takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
5615
5616
  trailingDelta = self.safe_string(params, 'trailingDelta')
5616
- trailingTriggerPrice = self.safe_string_2(params, 'trailingTriggerPrice', 'activationPrice', self.number_to_string(price))
5617
- trailingPercent = self.safe_string_2(params, 'trailingPercent', 'callbackRate')
5617
+ trailingTriggerPrice = self.safe_string_2(params, 'trailingTriggerPrice', 'activationPrice')
5618
+ trailingPercent = self.safe_string_n(params, ['trailingPercent', 'callbackRate', 'trailingDelta'])
5618
5619
  priceMatch = self.safe_string(params, 'priceMatch')
5619
5620
  isTrailingPercentOrder = trailingPercent is not None
5620
5621
  isStopLoss = stopLossPrice is not None or trailingDelta is not None
@@ -5626,10 +5627,26 @@ class binance(Exchange, ImplicitAPI):
5626
5627
  uppercaseType = type.upper()
5627
5628
  stopPrice = None
5628
5629
  if isTrailingPercentOrder:
5629
- uppercaseType = 'TRAILING_STOP_MARKET'
5630
- request['callbackRate'] = trailingPercent
5631
- if trailingTriggerPrice is not None:
5632
- request['activationPrice'] = self.price_to_precision(symbol, trailingTriggerPrice)
5630
+ if market['swap']:
5631
+ uppercaseType = 'TRAILING_STOP_MARKET'
5632
+ request['callbackRate'] = trailingPercent
5633
+ if trailingTriggerPrice is not None:
5634
+ request['activationPrice'] = self.price_to_precision(symbol, trailingTriggerPrice)
5635
+ else:
5636
+ if isMarketOrder:
5637
+ raise InvalidOrder(self.id + ' trailingPercent orders are not supported for ' + symbol + ' ' + type + ' orders')
5638
+ stopLossOrTakeProfit = self.safe_string(params, 'stopLossOrTakeProfit')
5639
+ params = self.omit(params, 'stopLossOrTakeProfit')
5640
+ if stopLossOrTakeProfit != 'stopLoss' and stopLossOrTakeProfit != 'takeProfit':
5641
+ raise InvalidOrder(self.id + symbol + ' trailingPercent orders require a stopLossOrTakeProfit parameter of either stopLoss or takeProfit')
5642
+ if stopLossOrTakeProfit == 'stopLoss':
5643
+ uppercaseType = 'STOP_LOSS_LIMIT'
5644
+ elif stopLossOrTakeProfit == 'takeProfit':
5645
+ uppercaseType = 'TAKE_PROFIT_LIMIT'
5646
+ if trailingTriggerPrice is not None:
5647
+ stopPrice = self.price_to_precision(symbol, trailingTriggerPrice)
5648
+ trailingPercentConverted = Precise.string_mul(trailingPercent, '100')
5649
+ request['trailingDelta'] = trailingPercentConverted
5633
5650
  elif isStopLoss:
5634
5651
  stopPrice = stopLossPrice
5635
5652
  if isMarketOrder:
@@ -5769,8 +5786,8 @@ class binance(Exchange, ImplicitAPI):
5769
5786
  raise InvalidOrder(self.id + ' createOrder() requires a stopPrice extra param for a ' + type + ' order')
5770
5787
  else:
5771
5788
  # check for delta price
5772
- if trailingDelta is None and stopPrice is None:
5773
- raise InvalidOrder(self.id + ' createOrder() requires a stopPrice or trailingDelta param for a ' + type + ' order')
5789
+ if trailingDelta is None and stopPrice is None and trailingPercent is None:
5790
+ raise InvalidOrder(self.id + ' createOrder() requires a stopPrice, trailingDelta or trailingPercent param for a ' + type + ' order')
5774
5791
  if stopPrice is not None:
5775
5792
  request['stopPrice'] = self.price_to_precision(symbol, stopPrice)
5776
5793
  if timeInForceIsRequired and (self.safe_string(params, 'timeInForce') is None):
@@ -7494,13 +7511,13 @@ class binance(Exchange, ImplicitAPI):
7494
7511
  'fee': fee,
7495
7512
  }
7496
7513
 
7497
- def parse_transfer_status(self, status):
7514
+ def parse_transfer_status(self, status: Str) -> Str:
7498
7515
  statuses = {
7499
7516
  'CONFIRMED': 'ok',
7500
7517
  }
7501
7518
  return self.safe_string(statuses, status, status)
7502
7519
 
7503
- def parse_transfer(self, transfer, currency: Currency = None):
7520
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
7504
7521
  #
7505
7522
  # transfer
7506
7523
  #
@@ -7658,7 +7675,7 @@ class binance(Exchange, ImplicitAPI):
7658
7675
  #
7659
7676
  return self.parse_transfer(response, currency)
7660
7677
 
7661
- def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
7678
+ def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> TransferEntries:
7662
7679
  """
7663
7680
  fetch a history of internal transfers made on an account
7664
7681
  :see: https://binance-docs.github.io/apidocs/spot/en/#query-user-universal-transfer-history-user_data
@@ -9729,7 +9746,7 @@ class binance(Exchange, ImplicitAPI):
9729
9746
  leverages = self.safe_list(response, 'positions', [])
9730
9747
  return self.parse_leverages(leverages, symbols, 'symbol')
9731
9748
 
9732
- def parse_leverage(self, leverage, market=None) -> Leverage:
9749
+ def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
9733
9750
  marketId = self.safe_string(leverage, 'symbol')
9734
9751
  marginModeRaw = self.safe_bool(leverage, 'isolated')
9735
9752
  marginMode = None
@@ -11323,7 +11340,7 @@ class binance(Exchange, ImplicitAPI):
11323
11340
  #
11324
11341
  return self.parse_greeks(response[0], market)
11325
11342
 
11326
- def parse_greeks(self, greeks, market: Market = None):
11343
+ def parse_greeks(self, greeks: dict, market: Market = None) -> Greeks:
11327
11344
  #
11328
11345
  # {
11329
11346
  # "symbol": "BTC-231229-40000-C",
@@ -11594,7 +11611,7 @@ class binance(Exchange, ImplicitAPI):
11594
11611
  chain = self.safe_dict(response, 0, {})
11595
11612
  return self.parse_option(chain, None, market)
11596
11613
 
11597
- def parse_option(self, chain, currency: Currency = None, market: Market = None):
11614
+ def parse_option(self, chain: dict, currency: Currency = None, market: Market = None) -> Option:
11598
11615
  #
11599
11616
  # {
11600
11617
  # "symbol": "BTC-241227-80000-C",
@@ -11983,7 +12000,7 @@ class binance(Exchange, ImplicitAPI):
11983
12000
  rows = self.safe_list(response, responseQuery, [])
11984
12001
  return self.parse_conversions(rows, code, fromCurrencyKey, toCurrencyKey, since, limit)
11985
12002
 
11986
- def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
12003
+ def parse_conversion(self, conversion: dict, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
11987
12004
  #
11988
12005
  # fetchConvertQuote
11989
12006
  #
ccxt/bingx.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.bingx import ImplicitAPI
8
8
  import hashlib
9
9
  import numbers
10
- from ccxt.base.types import Balances, Currencies, Currency, Int, Leverage, MarginMode, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
+ from ccxt.base.types import Balances, Currencies, Currency, Int, Leverage, MarginMode, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry, TransferEntries
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
@@ -3009,7 +3009,7 @@ class bingx(Exchange, ImplicitAPI):
3009
3009
  'status': None,
3010
3010
  }
3011
3011
 
3012
- def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
3012
+ def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> TransferEntries:
3013
3013
  """
3014
3014
  fetch a history of internal transfers made on an account
3015
3015
  :see: https://bingx-api.github.io/docs/#/spot/account-api.html#Query%20User%20Universal%20Transfer%20History%20(USER_DATA)
@@ -3056,7 +3056,7 @@ class bingx(Exchange, ImplicitAPI):
3056
3056
  rows = self.safe_list(response, 'rows', [])
3057
3057
  return self.parse_transfers(rows, currency, since, limit)
3058
3058
 
3059
- def parse_transfer(self, transfer, currency: Currency = None):
3059
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
3060
3060
  tranId = self.safe_string(transfer, 'tranId')
3061
3061
  timestamp = self.safe_integer(transfer, 'timestamp')
3062
3062
  currencyCode = self.safe_currency_code(None, currency)
@@ -3486,7 +3486,7 @@ class bingx(Exchange, ImplicitAPI):
3486
3486
  data = self.safe_dict(response, 'data', {})
3487
3487
  return self.parse_leverage(data, market)
3488
3488
 
3489
- def parse_leverage(self, leverage, market=None) -> Leverage:
3489
+ def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
3490
3490
  marketId = self.safe_string(leverage, 'symbol')
3491
3491
  return {
3492
3492
  'info': leverage,
ccxt/bit2c.py CHANGED
@@ -279,7 +279,7 @@ class bit2c(Exchange, ImplicitAPI):
279
279
  orderbook = self.publicGetExchangesPairOrderbook(self.extend(request, params))
280
280
  return self.parse_order_book(orderbook, symbol)
281
281
 
282
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
282
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
283
283
  symbol = self.safe_symbol(None, market)
284
284
  averagePrice = self.safe_string(ticker, 'av')
285
285
  baseVolume = self.safe_string(ticker, 'a')
ccxt/bitbank.py CHANGED
@@ -266,7 +266,7 @@ class bitbank(Exchange, ImplicitAPI):
266
266
  'info': entry,
267
267
  }
268
268
 
269
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
269
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
270
270
  symbol = self.safe_symbol(None, market)
271
271
  timestamp = self.safe_integer(ticker, 'timestamp')
272
272
  last = self.safe_string(ticker, 'last')
ccxt/bitbns.py CHANGED
@@ -320,7 +320,7 @@ class bitbns(Exchange, ImplicitAPI):
320
320
  timestamp = self.safe_integer(response, 'timestamp')
321
321
  return self.parse_order_book(response, market['symbol'], timestamp)
322
322
 
323
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
323
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
324
324
  #
325
325
  # {
326
326
  # "symbol":"BTC/INR",
ccxt/bitfinex.py CHANGED
@@ -775,7 +775,7 @@ class bitfinex(Exchange, ImplicitAPI):
775
775
  'amount': self.parse_number(requestedAmount),
776
776
  })
777
777
 
778
- def parse_transfer(self, transfer, currency: Currency = None):
778
+ def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
779
779
  #
780
780
  # {
781
781
  # "status": "success",
@@ -794,7 +794,7 @@ class bitfinex(Exchange, ImplicitAPI):
794
794
  'status': self.parse_transfer_status(self.safe_string(transfer, 'status')),
795
795
  }
796
796
 
797
- def parse_transfer_status(self, status):
797
+ def parse_transfer_status(self, status: Str) -> Str:
798
798
  statuses = {
799
799
  'SUCCESS': 'ok',
800
800
  }
@@ -841,7 +841,7 @@ class bitfinex(Exchange, ImplicitAPI):
841
841
  response = self.publicGetTickers(params)
842
842
  result = {}
843
843
  for i in range(0, len(response)):
844
- ticker = self.parse_ticker(response[i])
844
+ ticker = self.parse_ticker({'result': response[i]})
845
845
  symbol = ticker['symbol']
846
846
  result[symbol] = ticker
847
847
  return self.filter_by_array_tickers(result, 'symbol', symbols)
@@ -860,9 +860,33 @@ class bitfinex(Exchange, ImplicitAPI):
860
860
  'symbol': market['id'],
861
861
  }
862
862
  ticker = self.publicGetPubtickerSymbol(self.extend(request, params))
863
+ #
864
+ # {
865
+ # mid: '63560.5',
866
+ # bid: '63560.0',
867
+ # ask: '63561.0',
868
+ # last_price: '63547.0',
869
+ # low: '62812.0',
870
+ # high: '64480.0',
871
+ # volume: '517.25634977',
872
+ # timestamp: '1715102384.9849467'
873
+ # }
874
+ #
863
875
  return self.parse_ticker(ticker, market)
864
876
 
865
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
877
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
878
+ #
879
+ # {
880
+ # mid: '63560.5',
881
+ # bid: '63560.0',
882
+ # ask: '63561.0',
883
+ # last_price: '63547.0',
884
+ # low: '62812.0',
885
+ # high: '64480.0',
886
+ # volume: '517.25634977',
887
+ # timestamp: '1715102384.9849467'
888
+ # }
889
+ #
866
890
  timestamp = self.safe_timestamp(ticker, 'timestamp')
867
891
  marketId = self.safe_string(ticker, 'pair')
868
892
  market = self.safe_market(marketId, market)