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