ccxt 4.4.25__py2.py3-none-any.whl → 4.4.27__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 (123) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/alpaca.py +3 -0
  3. ccxt/abstract/bingx.py +1 -0
  4. ccxt/abstract/hyperliquid.py +1 -1
  5. ccxt/abstract/okx.py +1 -0
  6. ccxt/abstract/phemex.py +1 -0
  7. ccxt/ace.py +1 -1
  8. ccxt/alpaca.py +426 -17
  9. ccxt/ascendex.py +1 -1
  10. ccxt/async_support/__init__.py +1 -1
  11. ccxt/async_support/ace.py +1 -1
  12. ccxt/async_support/alpaca.py +426 -17
  13. ccxt/async_support/ascendex.py +1 -1
  14. ccxt/async_support/base/exchange.py +24 -6
  15. ccxt/async_support/bequant.py +1 -1
  16. ccxt/async_support/bigone.py +1 -1
  17. ccxt/async_support/binance.py +6 -7
  18. ccxt/async_support/binancecoinm.py +1 -1
  19. ccxt/async_support/binanceus.py +1 -1
  20. ccxt/async_support/binanceusdm.py +1 -1
  21. ccxt/async_support/bingx.py +29 -29
  22. ccxt/async_support/bit2c.py +1 -1
  23. ccxt/async_support/bitbank.py +1 -1
  24. ccxt/async_support/bitbns.py +1 -1
  25. ccxt/async_support/bitfinex.py +1 -1
  26. ccxt/async_support/bitfinex2.py +1 -1
  27. ccxt/async_support/bitflyer.py +1 -1
  28. ccxt/async_support/bitget.py +6 -6
  29. ccxt/async_support/bithumb.py +1 -1
  30. ccxt/async_support/bitmart.py +7 -7
  31. ccxt/async_support/bitmex.py +1 -1
  32. ccxt/async_support/bitopro.py +1 -1
  33. ccxt/async_support/bitrue.py +1 -1
  34. ccxt/async_support/bitso.py +1 -1
  35. ccxt/async_support/bitstamp.py +1 -1
  36. ccxt/async_support/bitteam.py +1 -1
  37. ccxt/async_support/bitvavo.py +1 -1
  38. ccxt/async_support/bl3p.py +1 -1
  39. ccxt/async_support/blockchaincom.py +1 -1
  40. ccxt/async_support/blofin.py +1 -1
  41. ccxt/async_support/btcalpha.py +1 -1
  42. ccxt/async_support/btcbox.py +1 -1
  43. ccxt/async_support/btcmarkets.py +1 -1
  44. ccxt/async_support/btcturk.py +1 -1
  45. ccxt/async_support/bybit.py +10 -16
  46. ccxt/async_support/cex.py +36 -0
  47. ccxt/async_support/coinbase.py +89 -11
  48. ccxt/async_support/coinex.py +6 -8
  49. ccxt/async_support/digifinex.py +5 -5
  50. ccxt/async_support/exmo.py +1 -0
  51. ccxt/async_support/gate.py +26 -22
  52. ccxt/async_support/htx.py +5 -6
  53. ccxt/async_support/hyperliquid.py +31 -5
  54. ccxt/async_support/kucoin.py +5 -5
  55. ccxt/async_support/lbank.py +97 -2
  56. ccxt/async_support/okx.py +6 -5
  57. ccxt/async_support/phemex.py +4 -2
  58. ccxt/async_support/wavesexchange.py +13 -2
  59. ccxt/async_support/whitebit.py +5 -5
  60. ccxt/async_support/woo.py +1 -1
  61. ccxt/async_support/xt.py +32 -24
  62. ccxt/base/exchange.py +29 -6
  63. ccxt/base/types.py +12 -0
  64. ccxt/bequant.py +1 -1
  65. ccxt/bigone.py +1 -1
  66. ccxt/binance.py +6 -7
  67. ccxt/binancecoinm.py +1 -1
  68. ccxt/binanceus.py +1 -1
  69. ccxt/binanceusdm.py +1 -1
  70. ccxt/bingx.py +29 -29
  71. ccxt/bit2c.py +1 -1
  72. ccxt/bitbank.py +1 -1
  73. ccxt/bitbns.py +1 -1
  74. ccxt/bitfinex.py +1 -1
  75. ccxt/bitfinex2.py +1 -1
  76. ccxt/bitflyer.py +1 -1
  77. ccxt/bitget.py +6 -6
  78. ccxt/bithumb.py +1 -1
  79. ccxt/bitmart.py +7 -7
  80. ccxt/bitmex.py +1 -1
  81. ccxt/bitopro.py +1 -1
  82. ccxt/bitrue.py +1 -1
  83. ccxt/bitso.py +1 -1
  84. ccxt/bitstamp.py +1 -1
  85. ccxt/bitteam.py +1 -1
  86. ccxt/bitvavo.py +1 -1
  87. ccxt/bl3p.py +1 -1
  88. ccxt/blockchaincom.py +1 -1
  89. ccxt/blofin.py +1 -1
  90. ccxt/btcalpha.py +1 -1
  91. ccxt/btcbox.py +1 -1
  92. ccxt/btcmarkets.py +1 -1
  93. ccxt/btcturk.py +1 -1
  94. ccxt/bybit.py +10 -16
  95. ccxt/cex.py +36 -0
  96. ccxt/coinbase.py +89 -11
  97. ccxt/coinex.py +6 -8
  98. ccxt/digifinex.py +5 -5
  99. ccxt/exmo.py +1 -0
  100. ccxt/gate.py +26 -22
  101. ccxt/htx.py +5 -6
  102. ccxt/hyperliquid.py +31 -5
  103. ccxt/kucoin.py +5 -5
  104. ccxt/lbank.py +97 -2
  105. ccxt/okx.py +6 -5
  106. ccxt/phemex.py +4 -2
  107. ccxt/pro/__init__.py +1 -1
  108. ccxt/pro/binance.py +2 -2
  109. ccxt/pro/bybit.py +1 -1
  110. ccxt/pro/exmo.py +204 -4
  111. ccxt/pro/lbank.py +7 -4
  112. ccxt/pro/okx.py +1 -1
  113. ccxt/test/tests_helpers.py +3 -1
  114. ccxt/wavesexchange.py +13 -2
  115. ccxt/whitebit.py +5 -5
  116. ccxt/woo.py +1 -1
  117. ccxt/xt.py +32 -24
  118. ccxt-4.4.27.dist-info/METADATA +637 -0
  119. {ccxt-4.4.25.dist-info → ccxt-4.4.27.dist-info}/RECORD +122 -122
  120. ccxt-4.4.25.dist-info/METADATA +0 -636
  121. {ccxt-4.4.25.dist-info → ccxt-4.4.27.dist-info}/LICENSE.txt +0 -0
  122. {ccxt-4.4.25.dist-info → ccxt-4.4.27.dist-info}/WHEEL +0 -0
  123. {ccxt-4.4.25.dist-info → ccxt-4.4.27.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.bybit import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
- from ccxt.base.types import LongShortRatio, Balances, Conversion, CrossBorrowRate, Currencies, Currency, DepositAddress, Greeks, Int, LedgerEntry, Leverage, LeverageTier, LeverageTiers, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
10
+ from ccxt.base.types import Balances, BorrowInterest, Conversion, CrossBorrowRate, Currencies, Currency, DepositAddress, Greeks, Int, LedgerEntry, Leverage, LeverageTier, LeverageTiers, LongShortRatio, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
@@ -174,7 +174,7 @@ class bybit(Exchange, ImplicitAPI):
174
174
  'public': 'https://api-testnet.{hostname}',
175
175
  'private': 'https://api-testnet.{hostname}',
176
176
  },
177
- 'logo': 'https://user-images.githubusercontent.com/51840849/76547799-daff5b80-649e-11ea-87fb-3be9bac08954.jpg',
177
+ 'logo': 'https://github.com/user-attachments/assets/97a5d0b3-de10-423d-90e1-6620960025ed',
178
178
  'api': {
179
179
  'spot': 'https://api.{hostname}',
180
180
  'futures': 'https://api.{hostname}',
@@ -1019,7 +1019,6 @@ class bybit(Exchange, ImplicitAPI):
1019
1019
  'precisionMode': TICK_SIZE,
1020
1020
  'options': {
1021
1021
  'usePrivateInstrumentsInfo': False,
1022
- 'sandboxMode': False,
1023
1022
  'enableDemoTrading': False,
1024
1023
  'fetchMarkets': ['spot', 'linear', 'inverse', 'option'],
1025
1024
  'createOrder': {
@@ -1105,21 +1104,13 @@ class bybit(Exchange, ImplicitAPI):
1105
1104
  },
1106
1105
  })
1107
1106
 
1108
- def set_sandbox_mode(self, enable: bool):
1109
- """
1110
- enables or disables sandbox mode
1111
- :param boolean [enable]: True if demo trading should be enabled, False otherwise
1112
- """
1113
- super(bybit, self).set_sandbox_mode(enable)
1114
- self.options['sandboxMode'] = enable
1115
-
1116
1107
  def enable_demo_trading(self, enable: bool):
1117
1108
  """
1118
1109
  enables or disables demo trading mode
1119
1110
  :see: https://bybit-exchange.github.io/docs/v5/demo
1120
1111
  :param boolean [enable]: True if demo trading should be enabled, False otherwise
1121
1112
  """
1122
- if self.options['sandboxMode']:
1113
+ if self.isSandboxModeEnabled:
1123
1114
  raise NotSupported(self.id + ' demo trading does not support in sandbox environment')
1124
1115
  # enable demo trading in bybit, see: https://bybit-exchange.github.io/docs/v5/demo
1125
1116
  if enable:
@@ -2497,6 +2488,9 @@ class bybit(Exchange, ImplicitAPI):
2497
2488
  #
2498
2489
  data = self.safe_dict(response, 'result', {})
2499
2490
  tickerList = self.safe_list(data, 'list', [])
2491
+ timestamp = self.safe_integer(response, 'time')
2492
+ for i in range(0, len(tickerList)):
2493
+ tickerList[i]['timestamp'] = timestamp # will be removed inside the parser
2500
2494
  result = self.parse_funding_rates(tickerList)
2501
2495
  return self.filter_by_array(result, 'symbol', symbols)
2502
2496
 
@@ -6833,7 +6827,7 @@ class bybit(Exchange, ImplicitAPI):
6833
6827
  'info': info,
6834
6828
  }
6835
6829
 
6836
- async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
6830
+ async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
6837
6831
  """
6838
6832
  fetch the interest owed by the user for borrowing currency for margin trading
6839
6833
  :see: https://bybit-exchange.github.io/docs/zh-TW/v5/spot-margin-normal/account-info
@@ -6924,7 +6918,7 @@ class bybit(Exchange, ImplicitAPI):
6924
6918
  rows = self.safe_list(data, 'list', [])
6925
6919
  return self.parse_borrow_rate_history(rows, code, since, limit)
6926
6920
 
6927
- def parse_borrow_interest(self, info: dict, market: Market = None):
6921
+ def parse_borrow_interest(self, info: dict, market: Market = None) -> BorrowInterest:
6928
6922
  #
6929
6923
  # {
6930
6924
  # "tokenId": "BTC",
@@ -6936,15 +6930,15 @@ class bybit(Exchange, ImplicitAPI):
6936
6930
  # },
6937
6931
  #
6938
6932
  return {
6933
+ 'info': info,
6939
6934
  'symbol': None,
6940
- 'marginMode': 'cross',
6941
6935
  'currency': self.safe_currency_code(self.safe_string(info, 'tokenId')),
6942
6936
  'interest': self.safe_number(info, 'interest'),
6943
6937
  'interestRate': None,
6944
6938
  'amountBorrowed': self.safe_number(info, 'loan'),
6939
+ 'marginMode': 'cross',
6945
6940
  'timestamp': None,
6946
6941
  'datetime': None,
6947
- 'info': info,
6948
6942
  }
6949
6943
 
6950
6944
  async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
ccxt/async_support/cex.py CHANGED
@@ -40,6 +40,7 @@ class cex(Exchange, ImplicitAPI):
40
40
  'createOrder': True,
41
41
  'fetchAccounts': True,
42
42
  'fetchBalance': True,
43
+ 'fetchClosedOrder': True,
43
44
  'fetchClosedOrders': True,
44
45
  'fetchCurrencies': True,
45
46
  'fetchDepositAddress': True,
@@ -51,6 +52,7 @@ class cex(Exchange, ImplicitAPI):
51
52
  'fetchLedger': True,
52
53
  'fetchMarkets': True,
53
54
  'fetchOHLCV': True,
55
+ 'fetchOpenOrder': True,
54
56
  'fetchOpenOrders': True,
55
57
  'fetchOrderBook': True,
56
58
  'fetchTicker': True,
@@ -899,6 +901,7 @@ class cex(Exchange, ImplicitAPI):
899
901
 
900
902
  async def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
901
903
  """
904
+ :see: https://trade.cex.io/docs/#rest-private-api-calls-orders
902
905
  fetches information on multiple canceled orders made by the user
903
906
  :param str symbol: unified market symbol of the market orders were made in
904
907
  :param int [since]: timestamp in ms of the earliest order, default is None
@@ -910,6 +913,7 @@ class cex(Exchange, ImplicitAPI):
910
913
 
911
914
  async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
912
915
  """
916
+ :see: https://trade.cex.io/docs/#rest-private-api-calls-orders
913
917
  fetches information on multiple canceled orders made by the user
914
918
  :param str symbol: unified market symbol of the market orders were made in
915
919
  :param int [since]: timestamp in ms of the earliest order, default is None
@@ -919,6 +923,38 @@ class cex(Exchange, ImplicitAPI):
919
923
  """
920
924
  return await self.fetch_orders_by_status('open', symbol, since, limit, params)
921
925
 
926
+ async def fetch_open_order(self, id: str, symbol: Str = None, params={}):
927
+ """
928
+ fetches information on an open order made by the user
929
+ :see: https://trade.cex.io/docs/#rest-private-api-calls-orders
930
+ :param str id: order id
931
+ :param str [symbol]: unified symbol of the market the order was made in
932
+ :param dict [params]: extra parameters specific to the exchange API endpoint
933
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
934
+ """
935
+ await self.load_markets()
936
+ request: dict = {
937
+ 'orderId': int(id),
938
+ }
939
+ result = await self.fetch_open_orders(symbol, None, None, self.extend(request, params))
940
+ return result[0]
941
+
942
+ async def fetch_closed_order(self, id: str, symbol: Str = None, params={}):
943
+ """
944
+ fetches information on an closed order made by the user
945
+ :see: https://trade.cex.io/docs/#rest-private-api-calls-orders
946
+ :param str id: order id
947
+ :param str [symbol]: unified symbol of the market the order was made in
948
+ :param dict [params]: extra parameters specific to the exchange API endpoint
949
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
950
+ """
951
+ await self.load_markets()
952
+ request: dict = {
953
+ 'orderId': int(id),
954
+ }
955
+ result = await self.fetch_closed_orders(symbol, None, None, self.extend(request, params))
956
+ return result[0]
957
+
922
958
  def parse_order_status(self, status: Str):
923
959
  statuses: dict = {
924
960
  'FILLED': 'closed',
@@ -90,6 +90,7 @@ class coinbase(Exchange, ImplicitAPI):
90
90
  'fetchDepositAddresses': False,
91
91
  'fetchDepositAddressesByNetwork': True,
92
92
  'fetchDeposits': True,
93
+ 'fetchDepositsWithdrawals': True,
93
94
  'fetchFundingHistory': False,
94
95
  'fetchFundingRate': False,
95
96
  'fetchFundingRateHistory': False,
@@ -758,8 +759,14 @@ class coinbase(Exchange, ImplicitAPI):
758
759
  :param int [since]: the earliest time in ms to fetch withdrawals for
759
760
  :param int [limit]: the maximum number of withdrawals structures to retrieve
760
761
  :param dict [params]: extra parameters specific to the exchange API endpoint
762
+ :param str [params.currencyType]: "fiat" or "crypto"
761
763
  :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
762
764
  """
765
+ currencyType = None
766
+ currencyType, params = self.handle_option_and_params(params, 'fetchWithdrawals', 'currencyType')
767
+ if currencyType == 'crypto':
768
+ results = await self.fetch_transactions_with_method('v2PrivateGetAccountsAccountIdTransactions', code, since, limit, params)
769
+ return self.filter_by_array(results, 'type', 'withdrawal', False)
763
770
  return await self.fetch_transactions_with_method('v2PrivateGetAccountsAccountIdWithdrawals', code, since, limit, params)
764
771
 
765
772
  async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
@@ -770,10 +777,30 @@ class coinbase(Exchange, ImplicitAPI):
770
777
  :param int [since]: the earliest time in ms to fetch deposits for
771
778
  :param int [limit]: the maximum number of deposits structures to retrieve
772
779
  :param dict [params]: extra parameters specific to the exchange API endpoint
780
+ :param str [params.currencyType]: "fiat" or "crypto"
773
781
  :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
774
782
  """
783
+ currencyType = None
784
+ currencyType, params = self.handle_option_and_params(params, 'fetchWithdrawals', 'currencyType')
785
+ if currencyType == 'crypto':
786
+ results = await self.fetch_transactions_with_method('v2PrivateGetAccountsAccountIdTransactions', code, since, limit, params)
787
+ return self.filter_by_array(results, 'type', 'deposit', False)
775
788
  return await self.fetch_transactions_with_method('v2PrivateGetAccountsAccountIdDeposits', code, since, limit, params)
776
789
 
790
+ async def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
791
+ """
792
+ fetch history of deposits and withdrawals
793
+ :see: https://docs.cdp.coinbase.com/coinbase-app/docs/api-transactions
794
+ :param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
795
+ :param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
796
+ :param int [limit]: max number of deposit/withdrawals to return, default = 50, Min: 1, Max: 100
797
+ :param dict [params]: extra parameters specific to the exchange API endpoint
798
+ :returns dict: a list of `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
799
+ """
800
+ await self.load_markets()
801
+ results = await self.fetch_transactions_with_method('v2PrivateGetAccountsAccountIdTransactions', code, since, limit, params)
802
+ return self.filter_by_array(results, 'type', ['deposit', 'withdrawal'], False)
803
+
777
804
  def parse_transaction_status(self, status: Str):
778
805
  statuses: dict = {
779
806
  'created': 'pending',
@@ -897,16 +924,59 @@ class coinbase(Exchange, ImplicitAPI):
897
924
  # "hide_native_amount": False
898
925
  # }
899
926
  #
927
+ #
928
+ # crypto deposit & withdrawal(using `/transactions` endpoint)
929
+ # {
930
+ # "amount": {
931
+ # "amount": "0.00014200",(negative for withdrawal)
932
+ # "currency": "BTC"
933
+ # },
934
+ # "created_at": "2024-03-29T15:48:30Z",
935
+ # "id": "0031a605-241d-514d-a97b-d4b99f3225d3",
936
+ # "idem": "092a979b-017e-4403-940a-2ca57811f442", # field present only in case of withdrawal
937
+ # "native_amount": {
938
+ # "amount": "9.85",(negative for withdrawal)
939
+ # "currency": "USD"
940
+ # },
941
+ # "network": {
942
+ # "status": "pending", # if status is `off_blockchain` then no more other fields are hasattr(self, present) object
943
+ # "hash": "5jYuvrNsvX2DZoMnzGYzVpYxJLfYu4GSK3xetG1H5LHrSovsuFCFYdFMwNRoiht3s6fBk92MM8QLLnz65xuEFTrE",
944
+ # "network_name": "solana",
945
+ # "transaction_fee": {
946
+ # "amount": "0.000100000",
947
+ # "currency": "SOL"
948
+ # }
949
+ # },
950
+ # "resource": "transaction",
951
+ # "resource_path": "/v2/accounts/dc504b1c-248e-5b68-a3b0-b991f7fa84e6/transactions/0031a605-241d-514d-a97b-d4b99f3225d3",
952
+ # "status": "completed",
953
+ # "type": "send",
954
+ # "from": { # in some cases, field might be present for deposit
955
+ # "id": "7fd10cd7-b091-5cee-ba41-c29e49a7cccf",
956
+ # "name": "Coinbase",
957
+ # "resource": "user"
958
+ # },
959
+ # "to": { # field only present for withdrawal
960
+ # "address": "5HA12BNthAvBwNYARYf9y5MqqCpB4qhCNFCs1Qw48ACE",
961
+ # "resource": "address"
962
+ # },
963
+ # "description": "C3 - One Time BTC Credit . Reference Case # 123.", # in some cases, field might be present for deposit
964
+ # }
965
+ #
900
966
  transactionType = self.safe_string(transaction, 'type')
901
967
  amountAndCurrencyObject = None
902
968
  feeObject = None
969
+ network = self.safe_dict(transaction, 'network', {})
903
970
  if transactionType == 'send':
904
- network = self.safe_dict(transaction, 'network', {})
905
- amountAndCurrencyObject = self.safe_dict(network, 'transaction_amount', {})
971
+ amountAndCurrencyObject = self.safe_dict(network, 'transaction_amount')
906
972
  feeObject = self.safe_dict(network, 'transaction_fee', {})
907
973
  else:
908
- amountAndCurrencyObject = self.safe_dict(transaction, 'subtotal', {})
974
+ amountAndCurrencyObject = self.safe_dict(transaction, 'subtotal')
909
975
  feeObject = self.safe_dict(transaction, 'fee', {})
976
+ if amountAndCurrencyObject is None:
977
+ amountAndCurrencyObject = self.safe_dict(transaction, 'amount')
978
+ amountString = self.safe_string(amountAndCurrencyObject, 'amount')
979
+ amountStringAbs = Precise.string_abs(amountString)
910
980
  status = self.parse_transaction_status(self.safe_string(transaction, 'status'))
911
981
  if status is None:
912
982
  committed = self.safe_bool(transaction, 'committed')
@@ -915,23 +985,31 @@ class coinbase(Exchange, ImplicitAPI):
915
985
  currencyId = self.safe_string(amountAndCurrencyObject, 'currency')
916
986
  feeCurrencyId = self.safe_string(feeObject, 'currency')
917
987
  datetime = self.safe_string(transaction, 'created_at')
918
- toObject = self.safe_dict(transaction, 'to', {})
919
- toAddress = self.safe_string(toObject, 'address')
988
+ resource = self.safe_string(transaction, 'resource')
989
+ type = resource
990
+ if not self.in_array(type, ['deposit', 'withdrawal']):
991
+ if Precise.string_gt(amountString, '0'):
992
+ type = 'deposit'
993
+ elif Precise.string_lt(amountString, '0'):
994
+ type = 'withdrawal'
995
+ toObject = self.safe_dict(transaction, 'to')
996
+ addressTo = self.safe_string(toObject, 'address')
997
+ networkId = self.safe_string(network, 'network_name')
920
998
  return {
921
999
  'info': transaction,
922
1000
  'id': id,
923
- 'txid': id,
1001
+ 'txid': self.safe_string(network, 'hash', id),
924
1002
  'timestamp': self.parse8601(datetime),
925
1003
  'datetime': datetime,
926
- 'network': None,
927
- 'address': toAddress,
928
- 'addressTo': toAddress,
1004
+ 'network': self.network_id_to_code(networkId),
1005
+ 'address': addressTo,
1006
+ 'addressTo': addressTo,
929
1007
  'addressFrom': None,
930
1008
  'tag': None,
931
1009
  'tagTo': None,
932
1010
  'tagFrom': None,
933
- 'type': self.safe_string(transaction, 'resource'),
934
- 'amount': self.safe_number(amountAndCurrencyObject, 'amount'),
1011
+ 'type': type,
1012
+ 'amount': self.parse_number(amountStringAbs),
935
1013
  'currency': self.safe_currency_code(currencyId, currency),
936
1014
  'status': status,
937
1015
  'updated': self.parse8601(self.safe_string(transaction, 'updated_at')),
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.coinex import ImplicitAPI
8
8
  import asyncio
9
- from ccxt.base.types import Balances, Currencies, Currency, DepositAddress, Int, IsolatedBorrowRate, Leverage, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
9
+ from ccxt.base.types import Balances, BorrowInterest, Currencies, Currency, DepositAddress, Int, IsolatedBorrowRate, Leverage, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -4673,7 +4673,7 @@ class coinex(Exchange, ImplicitAPI):
4673
4673
  await self.load_markets()
4674
4674
  currency = self.currency(code)
4675
4675
  amountToPrecision = self.currency_to_precision(code, amount)
4676
- accountsByType = self.safe_dict(self.options, 'accountsById', {})
4676
+ accountsByType = self.safe_dict(self.options, 'accountsByType', {})
4677
4677
  fromId = self.safe_string(accountsByType, fromAccount, fromAccount)
4678
4678
  toId = self.safe_string(accountsByType, toAccount, toAccount)
4679
4679
  request: dict = {
@@ -4960,7 +4960,7 @@ class coinex(Exchange, ImplicitAPI):
4960
4960
  data = self.safe_dict(response, 'data', {})
4961
4961
  return self.parse_isolated_borrow_rate(data, market)
4962
4962
 
4963
- async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
4963
+ async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
4964
4964
  """
4965
4965
  fetch the interest owed by the user for borrowing currency for margin trading
4966
4966
  :see: https://docs.coinex.com/api/v2/assets/loan-flat/http/list-margin-borrow-history
@@ -5008,7 +5008,7 @@ class coinex(Exchange, ImplicitAPI):
5008
5008
  interest = self.parse_borrow_interests(rows, market)
5009
5009
  return self.filter_by_currency_since_limit(interest, code, since, limit)
5010
5010
 
5011
- def parse_borrow_interest(self, info: dict, market: Market = None):
5011
+ def parse_borrow_interest(self, info: dict, market: Market = None) -> BorrowInterest:
5012
5012
  #
5013
5013
  # {
5014
5014
  # "borrow_id": 2642934,
@@ -5027,17 +5027,15 @@ class coinex(Exchange, ImplicitAPI):
5027
5027
  market = self.safe_market(marketId, market, None, 'spot')
5028
5028
  timestamp = self.safe_integer(info, 'expired_at')
5029
5029
  return {
5030
- 'account': None, # deprecated
5030
+ 'info': info,
5031
5031
  'symbol': market['symbol'],
5032
- 'marginMode': 'isolated',
5033
- 'marginType': None, # deprecated
5034
5032
  'currency': self.safe_currency_code(self.safe_string(info, 'ccy')),
5035
5033
  'interest': self.safe_number(info, 'to_repaied_amount'),
5036
5034
  'interestRate': self.safe_number(info, 'daily_interest_rate'),
5037
5035
  'amountBorrowed': self.safe_number(info, 'borrow_amount'),
5036
+ 'marginMode': 'isolated',
5038
5037
  'timestamp': timestamp, # expiry time
5039
5038
  'datetime': self.iso8601(timestamp),
5040
- 'info': info,
5041
5039
  }
5042
5040
 
5043
5041
  async def borrow_isolated_margin(self, symbol: str, code: str, amount: float, params={}):
@@ -8,7 +8,7 @@ from ccxt.abstract.digifinex import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
10
  import json
11
- from ccxt.base.types import Balances, CrossBorrowRate, CrossBorrowRates, Currencies, Currency, DepositAddress, Int, LedgerEntry, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, Transaction, TransferEntry
11
+ from ccxt.base.types import Balances, BorrowInterest, CrossBorrowRate, CrossBorrowRates, Currencies, Currency, DepositAddress, Int, LedgerEntry, LeverageTier, LeverageTiers, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, Transaction, TransferEntry
12
12
  from typing import List
13
13
  from ccxt.base.errors import ExchangeError
14
14
  from ccxt.base.errors import AuthenticationError
@@ -2817,7 +2817,7 @@ class digifinex(Exchange, ImplicitAPI):
2817
2817
  #
2818
2818
  return self.parse_transaction(response, currency)
2819
2819
 
2820
- async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2820
+ async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
2821
2821
  await self.load_markets()
2822
2822
  request: dict = {}
2823
2823
  market = None
@@ -2850,7 +2850,7 @@ class digifinex(Exchange, ImplicitAPI):
2850
2850
  interest = self.parse_borrow_interests(rows, market)
2851
2851
  return self.filter_by_currency_since_limit(interest, code, since, limit)
2852
2852
 
2853
- def parse_borrow_interest(self, info: dict, market: Market = None):
2853
+ def parse_borrow_interest(self, info: dict, market: Market = None) -> BorrowInterest:
2854
2854
  #
2855
2855
  # {
2856
2856
  # "amount": 0.0006103,
@@ -2872,15 +2872,15 @@ class digifinex(Exchange, ImplicitAPI):
2872
2872
  currency = None if (market is None) else market['base']
2873
2873
  symbol = self.safe_symbol(marketId, market)
2874
2874
  return {
2875
- 'account': symbol,
2875
+ 'info': info,
2876
2876
  'symbol': symbol,
2877
2877
  'currency': currency,
2878
2878
  'interest': None,
2879
2879
  'interestRate': 0.001, # all interest rates on digifinex are 0.1%
2880
2880
  'amountBorrowed': self.parse_number(amountBorrowed),
2881
+ 'marginMode': None,
2881
2882
  'timestamp': None,
2882
2883
  'datetime': None,
2883
- 'info': info,
2884
2884
  }
2885
2885
 
2886
2886
  async def fetch_cross_borrow_rate(self, code: str, params={}) -> CrossBorrowRate:
@@ -223,6 +223,7 @@ class exmo(Exchange, ImplicitAPI):
223
223
  'precisionMode': TICK_SIZE,
224
224
  'exceptions': {
225
225
  'exact': {
226
+ '140333': InvalidOrder, # {"error":{"code":140333,"msg":"The number of characters after the point in the price exceeds the maximum number '8\u003e6'"}}
226
227
  '140434': BadRequest,
227
228
  '40005': AuthenticationError, # Authorization error, incorrect signature
228
229
  '40009': InvalidNonce, #
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.gate import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
- from ccxt.base.types import Balances, Bool, Currencies, Currency, DepositAddress, FundingHistory, Greeks, Int, LedgerEntry, Leverage, Leverages, LeverageTier, LeverageTiers, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
10
+ from ccxt.base.types import Balances, BorrowInterest, Bool, Currencies, Currency, DepositAddress, FundingHistory, Greeks, Int, LedgerEntry, Leverage, Leverages, LeverageTier, LeverageTiers, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
@@ -923,22 +923,26 @@ class gate(Exchange, ImplicitAPI):
923
923
  """
924
924
  unifiedAccount = self.safe_bool(self.options, 'unifiedAccount')
925
925
  if unifiedAccount is None:
926
- response = await self.privateAccountGetDetail(params)
927
- #
928
- # {
929
- # "user_id": 10406147,
930
- # "ip_whitelist": [],
931
- # "currency_pairs": [],
932
- # "key": {
933
- # "mode": 1
934
- # },
935
- # "tier": 0,
936
- # "tier_expire_time": "0001-01-01T00:00:00Z",
937
- # "copy_trading_role": 0
938
- # }
939
- #
940
- result = self.safe_dict(response, 'key', {})
941
- self.options['unifiedAccount'] = self.safe_integer(result, 'mode') == 2
926
+ try:
927
+ #
928
+ # {
929
+ # "user_id": 10406147,
930
+ # "ip_whitelist": [],
931
+ # "currency_pairs": [],
932
+ # "key": {
933
+ # "mode": 1
934
+ # },
935
+ # "tier": 0,
936
+ # "tier_expire_time": "0001-01-01T00:00:00Z",
937
+ # "copy_trading_role": 0
938
+ # }
939
+ #
940
+ response = await self.privateAccountGetDetail(params)
941
+ result = self.safe_dict(response, 'key', {})
942
+ self.options['unifiedAccount'] = self.safe_integer(result, 'mode') == 2
943
+ except Exception as e:
944
+ # if the request fails, the unifiedAccount is disabled
945
+ self.options['unifiedAccount'] = False
942
946
 
943
947
  async def upgrade_unified_trade_account(self, params={}):
944
948
  return await self.privateUnifiedPutUnifiedMode(params)
@@ -5969,7 +5973,7 @@ class gate(Exchange, ImplicitAPI):
5969
5973
  'info': info,
5970
5974
  }
5971
5975
 
5972
- async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
5976
+ async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
5973
5977
  """
5974
5978
  fetch the interest owed by the user for borrowing currency for margin trading
5975
5979
  :see: https://www.gate.io/docs/developers/apiv4/en/#list-interest-records
@@ -6014,21 +6018,21 @@ class gate(Exchange, ImplicitAPI):
6014
6018
  interest = self.parse_borrow_interests(response, market)
6015
6019
  return self.filter_by_currency_since_limit(interest, code, since, limit)
6016
6020
 
6017
- def parse_borrow_interest(self, info: dict, market: Market = None):
6021
+ def parse_borrow_interest(self, info: dict, market: Market = None) -> BorrowInterest:
6018
6022
  marketId = self.safe_string(info, 'currency_pair')
6019
6023
  market = self.safe_market(marketId, market)
6020
6024
  marginMode = 'isolated' if (marketId is not None) else 'cross'
6021
6025
  timestamp = self.safe_integer(info, 'create_time')
6022
6026
  return {
6023
6027
  'info': info,
6024
- 'timestamp': timestamp,
6025
- 'datetime': self.iso8601(timestamp),
6026
6028
  'symbol': self.safe_string(market, 'symbol'),
6027
6029
  'currency': self.safe_currency_code(self.safe_string(info, 'currency')),
6028
- 'marginMode': marginMode,
6029
6030
  'interest': self.safe_number(info, 'interest'),
6030
6031
  'interestRate': self.safe_number(info, 'actual_rate'),
6031
6032
  'amountBorrowed': None,
6033
+ 'marginMode': marginMode,
6034
+ 'timestamp': timestamp,
6035
+ 'datetime': self.iso8601(timestamp),
6032
6036
  }
6033
6037
 
6034
6038
  def sign(self, path, api=[], method='GET', params={}, headers=None, body=None):
ccxt/async_support/htx.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.htx import ImplicitAPI
8
8
  import asyncio
9
9
  import hashlib
10
- from ccxt.base.types import Account, Balances, Currencies, Currency, DepositAddress, Int, IsolatedBorrowRate, IsolatedBorrowRates, LedgerEntry, LeverageTier, LeverageTiers, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, Transaction, TransferEntry
10
+ from ccxt.base.types import Account, Balances, BorrowInterest, Currencies, Currency, DepositAddress, Int, IsolatedBorrowRate, IsolatedBorrowRates, LedgerEntry, LeverageTier, LeverageTiers, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, 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 AuthenticationError
@@ -6575,7 +6575,7 @@ class htx(Exchange, ImplicitAPI):
6575
6575
  result = self.parse_funding_rates(data)
6576
6576
  return self.filter_by_array(result, 'symbol', symbols)
6577
6577
 
6578
- async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
6578
+ async def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
6579
6579
  """
6580
6580
  fetch the interest owed by the user for borrowing currency for margin trading
6581
6581
  :see: https://huobiapi.github.io/docs/spot/v1/en/#search-past-margin-orders-cross
@@ -6634,7 +6634,7 @@ class htx(Exchange, ImplicitAPI):
6634
6634
  interest = self.parse_borrow_interests(data, market)
6635
6635
  return self.filter_by_currency_since_limit(interest, code, since, limit)
6636
6636
 
6637
- def parse_borrow_interest(self, info: dict, market: Market = None):
6637
+ def parse_borrow_interest(self, info: dict, market: Market = None) -> BorrowInterest:
6638
6638
  # isolated
6639
6639
  # {
6640
6640
  # "interest-rate":"0.000040830000000000",
@@ -6682,16 +6682,15 @@ class htx(Exchange, ImplicitAPI):
6682
6682
  symbol = self.safe_string(market, 'symbol')
6683
6683
  timestamp = self.safe_integer(info, 'accrued-at')
6684
6684
  return {
6685
- 'account': symbol if (marginMode == 'isolated') else 'cross', # deprecated
6685
+ 'info': info,
6686
6686
  'symbol': symbol,
6687
- 'marginMode': marginMode,
6688
6687
  'currency': self.safe_currency_code(self.safe_string(info, 'currency')),
6689
6688
  'interest': self.safe_number(info, 'interest-amount'),
6690
6689
  'interestRate': self.safe_number(info, 'interest-rate'),
6691
6690
  'amountBorrowed': self.safe_number(info, 'loan-amount'),
6691
+ 'marginMode': marginMode,
6692
6692
  'timestamp': timestamp, # Interest accrued time
6693
6693
  'datetime': self.iso8601(timestamp),
6694
- 'info': info,
6695
6694
  }
6696
6695
 
6697
6696
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
@@ -157,7 +157,17 @@ class hyperliquid(Exchange, ImplicitAPI):
157
157
  'api': {
158
158
  'public': {
159
159
  'post': {
160
- 'info': 1,
160
+ 'info': {
161
+ 'cost': 20,
162
+ 'byType': {
163
+ 'l2Book': 2,
164
+ 'allMids': 2,
165
+ 'clearinghouseState': 2,
166
+ 'orderStatus': 2,
167
+ 'spotClearinghouseState': 2,
168
+ 'exchangeStatus': 2,
169
+ },
170
+ },
161
171
  },
162
172
  },
163
173
  'private': {
@@ -770,9 +780,16 @@ class hyperliquid(Exchange, ImplicitAPI):
770
780
  await self.load_markets()
771
781
  market = self.market(symbol)
772
782
  until = self.safe_integer(params, 'until', self.milliseconds())
773
- useTail = (since is None)
783
+ useTail = since is None
784
+ originalSince = since
774
785
  if since is None:
775
- since = 0
786
+ if limit is not None:
787
+ # optimization if limit is provided
788
+ timeframeInMilliseconds = self.parse_timeframe(timeframe) * 1000
789
+ since = self.sum(until, timeframeInMilliseconds * limit * -1)
790
+ useTail = False
791
+ else:
792
+ since = 0
776
793
  params = self.omit(params, ['until'])
777
794
  request: dict = {
778
795
  'type': 'candleSnapshot',
@@ -800,7 +817,7 @@ class hyperliquid(Exchange, ImplicitAPI):
800
817
  # }
801
818
  # ]
802
819
  #
803
- return self.parse_ohlcvs(response, market, timeframe, since, limit, useTail)
820
+ return self.parse_ohlcvs(response, market, timeframe, originalSince, limit, useTail)
804
821
 
805
822
  def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
806
823
  #
@@ -1534,7 +1551,8 @@ class hyperliquid(Exchange, ImplicitAPI):
1534
1551
  if since is not None:
1535
1552
  request['startTime'] = since
1536
1553
  else:
1537
- request['startTime'] = self.milliseconds() - 100 * 60 * 60 * 1000
1554
+ maxLimit = 500 if (limit is None) else limit
1555
+ request['startTime'] = self.milliseconds() - maxLimit * 60 * 60 * 1000
1538
1556
  until = self.safe_integer(params, 'until')
1539
1557
  params = self.omit(params, 'until')
1540
1558
  if until is not None:
@@ -2844,6 +2862,14 @@ class hyperliquid(Exchange, ImplicitAPI):
2844
2862
  body = self.json(params)
2845
2863
  return {'url': url, 'method': method, 'body': body, 'headers': headers}
2846
2864
 
2865
+ def calculate_rate_limiter_cost(self, api, method, path, params, config={}):
2866
+ if ('byType' in config) and ('type' in params):
2867
+ type = params['type']
2868
+ byType = config['byType']
2869
+ if type in byType:
2870
+ return byType[type]
2871
+ return self.safe_value(config, 'cost', 1)
2872
+
2847
2873
  def parse_create_order_args(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
2848
2874
  market = self.market(symbol)
2849
2875
  vaultAddress = self.safe_string(params, 'vaultAddress')