ccxt 4.4.96__py2.py3-none-any.whl → 4.4.98__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 (67) hide show
  1. ccxt/__init__.py +2 -1
  2. ccxt/abstract/binance.py +3 -0
  3. ccxt/abstract/binancecoinm.py +3 -0
  4. ccxt/abstract/binanceus.py +3 -0
  5. ccxt/abstract/binanceusdm.py +3 -0
  6. ccxt/abstract/phemex.py +1 -0
  7. ccxt/async_support/__init__.py +2 -1
  8. ccxt/async_support/base/exchange.py +6 -3
  9. ccxt/async_support/binance.py +90 -34
  10. ccxt/async_support/binancecoinm.py +5 -1
  11. ccxt/async_support/binanceus.py +3 -1
  12. ccxt/async_support/binanceusdm.py +3 -1
  13. ccxt/async_support/bingx.py +1 -1
  14. ccxt/async_support/bitget.py +14 -2
  15. ccxt/async_support/coinmetro.py +2 -3
  16. ccxt/async_support/cryptocom.py +77 -2
  17. ccxt/async_support/exmo.py +1 -1
  18. ccxt/async_support/foxbit.py +1 -1
  19. ccxt/async_support/gate.py +1 -2
  20. ccxt/async_support/hashkey.py +39 -0
  21. ccxt/async_support/hyperliquid.py +40 -25
  22. ccxt/async_support/independentreserve.py +35 -0
  23. ccxt/async_support/indodax.py +34 -0
  24. ccxt/async_support/kucoin.py +2 -1
  25. ccxt/async_support/latoken.py +42 -0
  26. ccxt/async_support/luno.py +36 -0
  27. ccxt/async_support/mercado.py +34 -0
  28. ccxt/async_support/mexc.py +3 -19
  29. ccxt/async_support/ndax.py +8 -0
  30. ccxt/async_support/okx.py +2 -0
  31. ccxt/async_support/phemex.py +36 -31
  32. ccxt/base/decimal_to_precision.py +14 -10
  33. ccxt/base/errors.py +6 -0
  34. ccxt/base/exchange.py +55 -15
  35. ccxt/binance.py +90 -34
  36. ccxt/binancecoinm.py +5 -1
  37. ccxt/binanceus.py +3 -1
  38. ccxt/binanceusdm.py +3 -1
  39. ccxt/bingx.py +1 -1
  40. ccxt/bitget.py +14 -2
  41. ccxt/coinmetro.py +2 -3
  42. ccxt/cryptocom.py +77 -2
  43. ccxt/exmo.py +1 -1
  44. ccxt/foxbit.py +1 -1
  45. ccxt/gate.py +1 -2
  46. ccxt/hashkey.py +39 -0
  47. ccxt/hyperliquid.py +40 -25
  48. ccxt/independentreserve.py +35 -0
  49. ccxt/indodax.py +34 -0
  50. ccxt/kucoin.py +2 -1
  51. ccxt/latoken.py +42 -0
  52. ccxt/luno.py +36 -0
  53. ccxt/mercado.py +34 -0
  54. ccxt/mexc.py +3 -19
  55. ccxt/ndax.py +8 -0
  56. ccxt/okx.py +2 -0
  57. ccxt/phemex.py +36 -31
  58. ccxt/pro/__init__.py +2 -1
  59. ccxt/pro/binancecoinm.py +3 -1
  60. ccxt/pro/binanceus.py +3 -1
  61. ccxt/pro/binanceusdm.py +3 -1
  62. ccxt/pro/bybit.py +33 -1
  63. {ccxt-4.4.96.dist-info → ccxt-4.4.98.dist-info}/METADATA +16 -16
  64. {ccxt-4.4.96.dist-info → ccxt-4.4.98.dist-info}/RECORD +67 -67
  65. {ccxt-4.4.96.dist-info → ccxt-4.4.98.dist-info}/LICENSE.txt +0 -0
  66. {ccxt-4.4.96.dist-info → ccxt-4.4.98.dist-info}/WHEEL +0 -0
  67. {ccxt-4.4.96.dist-info → ccxt-4.4.98.dist-info}/top_level.txt +0 -0
ccxt/binance.py CHANGED
@@ -505,6 +505,7 @@ class binance(Exchange, ImplicitAPI):
505
505
  'portfolio/balance': 2,
506
506
  'portfolio/negative-balance-exchange-record': 2,
507
507
  'portfolio/pmloan-history': 5,
508
+ 'portfolio/earn-asset-balance': 150, # Weight(IP): 1500 => cost = 0.1 * 1500 = 150
508
509
  # staking
509
510
  'staking/productList': 0.1,
510
511
  'staking/position': 0.1,
@@ -663,6 +664,7 @@ class binance(Exchange, ImplicitAPI):
663
664
  'portfolio/repay-futures-negative-balance': 150, # Weight(IP): 1500 => cost = 0.1 * 1500 = 150
664
665
  'portfolio/mint': 20,
665
666
  'portfolio/redeem': 20,
667
+ 'portfolio/earn-asset-transfer': 150, # Weight(IP): 1500 => cost = 0.1 * 1500 = 150
666
668
  'lending/auto-invest/plan/add': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
667
669
  'lending/auto-invest/plan/edit': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
668
670
  'lending/auto-invest/plan/edit-status': 0.1, # Weight(IP): 1 => cost = 0.1 * 1 = 0.1
@@ -851,6 +853,7 @@ class binance(Exchange, ImplicitAPI):
851
853
  'apiTradingStatus': {'cost': 1, 'noSymbol': 10},
852
854
  'lvtKlines': 1,
853
855
  'convert/exchangeInfo': 4,
856
+ 'insuranceBalance': 1,
854
857
  },
855
858
  },
856
859
  'fapiData': {
@@ -1288,12 +1291,14 @@ class binance(Exchange, ImplicitAPI):
1288
1291
  'options': {
1289
1292
  'sandboxMode': False,
1290
1293
  'fetchMargins': True,
1291
- 'fetchMarkets': [
1292
- 'spot', # allows CORS in browsers
1293
- 'linear', # allows CORS in browsers
1294
- 'inverse', # allows CORS in browsers
1295
- # 'option', # does not allow CORS, enable outside of the browser only
1296
- ],
1294
+ 'fetchMarkets': {
1295
+ 'types': [
1296
+ 'spot', # allows CORS in browsers
1297
+ 'linear', # allows CORS in browsers
1298
+ 'inverse', # allows CORS in browsers
1299
+ # 'option', # does not allow CORS, enable outside of the browser only
1300
+ ],
1301
+ },
1297
1302
  'loadAllOptions': False,
1298
1303
  'fetchCurrencies': True, # self is a private call and it requires API keys
1299
1304
  # 'fetchTradesMethod': 'publicGetAggTrades', # publicGetTrades, publicGetHistoricalTrades, eapiPublicGetTrades
@@ -3021,7 +3026,14 @@ class binance(Exchange, ImplicitAPI):
3021
3026
  :returns dict[]: an array of objects representing market data
3022
3027
  """
3023
3028
  promisesRaw = []
3024
- rawFetchMarkets = self.safe_list(self.options, 'fetchMarkets', ['spot', 'linear', 'inverse'])
3029
+ rawFetchMarkets = None
3030
+ defaultTypes = ['spot', 'linear', 'inverse']
3031
+ fetchMarketsOptions = self.safe_dict(self.options, 'fetchMarkets')
3032
+ if fetchMarketsOptions is not None:
3033
+ rawFetchMarkets = self.safe_list(fetchMarketsOptions, 'types', defaultTypes)
3034
+ else:
3035
+ # for backward-compatibility
3036
+ rawFetchMarkets = self.safe_list(self.options, 'fetchMarkets', defaultTypes)
3025
3037
  # handle loadAllOptions option
3026
3038
  loadAllOptions = self.safe_bool(self.options, 'loadAllOptions', False)
3027
3039
  if loadAllOptions:
@@ -3913,29 +3925,52 @@ class binance(Exchange, ImplicitAPI):
3913
3925
  # "time": 1597370495002
3914
3926
  # }
3915
3927
  #
3916
- # {
3917
- # "symbol": "ETHBTC",
3918
- # "priceChange": "0.00068700",
3919
- # "priceChangePercent": "2.075",
3920
- # "weightedAvgPrice": "0.03342681",
3921
- # "prevClosePrice": "0.03310300",
3922
- # "lastPrice": "0.03378900",
3923
- # "lastQty": "0.07700000",
3924
- # "bidPrice": "0.03378900",
3925
- # "bidQty": "7.16800000",
3926
- # "askPrice": "0.03379000",
3927
- # "askQty": "24.00000000",
3928
- # "openPrice": "0.03310200",
3929
- # "highPrice": "0.03388900",
3930
- # "lowPrice": "0.03306900",
3931
- # "volume": "205478.41000000",
3932
- # "quoteVolume": "6868.48826294",
3933
- # "openTime": 1601469986932,
3934
- # "closeTime": 1601556386932,
3935
- # "firstId": 196098772,
3936
- # "lastId": 196186315,
3937
- # "count": 87544
3938
- # }
3928
+ # spot - ticker
3929
+ #
3930
+ # {
3931
+ # "symbol": "BTCUSDT",
3932
+ # "priceChange": "-188.18000000",
3933
+ # "priceChangePercent": "-0.159",
3934
+ # "weightedAvgPrice": "118356.64734074",
3935
+ # "lastPrice": "118449.03000000",
3936
+ # "prevClosePrice": "118637.22000000", # field absent in rolling ticker
3937
+ # "lastQty": "0.00731000", # field absent in rolling ticker
3938
+ # "bidPrice": "118449.02000000", # field absent in rolling ticker
3939
+ # "bidQty": "7.15931000", # field absent in rolling ticker
3940
+ # "askPrice": "118449.03000000", # field absent in rolling ticker
3941
+ # "askQty": "0.09592000", # field absent in rolling ticker
3942
+ # "openPrice": "118637.21000000",
3943
+ # "highPrice": "119273.36000000",
3944
+ # "lowPrice": "117427.50000000",
3945
+ # "volume": "14741.41491000",
3946
+ # "quoteVolume": "1744744445.80640740",
3947
+ # "openTime": "1753701474013",
3948
+ # "closeTime": "1753787874013",
3949
+ # "firstId": "5116031635",
3950
+ # "lastId": "5117964946",
3951
+ # "count": "1933312"
3952
+ # }
3953
+ #
3954
+ # usdm tickers
3955
+ #
3956
+ # {
3957
+ # "symbol": "SUSDT",
3958
+ # "priceChange": "-0.0229000",
3959
+ # "priceChangePercent": "-6.777",
3960
+ # "weightedAvgPrice": "0.3210035",
3961
+ # "lastPrice": "0.3150000",
3962
+ # "lastQty": "16",
3963
+ # "openPrice": "0.3379000",
3964
+ # "highPrice": "0.3411000",
3965
+ # "lowPrice": "0.3071000",
3966
+ # "volume": "120588225",
3967
+ # "quoteVolume": "38709237.2289000",
3968
+ # "openTime": "1753701720000",
3969
+ # "closeTime": "1753788172414",
3970
+ # "firstId": "72234973",
3971
+ # "lastId": "72423677",
3972
+ # "count": "188700"
3973
+ # }
3939
3974
  #
3940
3975
  # coinm
3941
3976
  #
@@ -4286,16 +4321,37 @@ class binance(Exchange, ImplicitAPI):
4286
4321
  elif self.is_inverse(type, subType):
4287
4322
  response = self.dapiPublicGetTicker24hr(params)
4288
4323
  elif type == 'spot':
4289
- request: dict = {}
4290
- if symbols is not None:
4291
- request['symbols'] = self.json(self.market_ids(symbols))
4292
- response = self.publicGetTicker24hr(self.extend(request, params))
4324
+ rolling = self.safe_bool(params, 'rolling', False)
4325
+ params = self.omit(params, 'rolling')
4326
+ if rolling:
4327
+ symbols = self.market_symbols(symbols)
4328
+ request: dict = {
4329
+ 'symbols': self.json(self.market_ids(symbols)),
4330
+ }
4331
+ response = self.publicGetTicker(self.extend(request, params))
4332
+ # parseTicker is not able to handle marketType for spot-rolling ticker fields, so we need custom parsing
4333
+ return self.parse_tickers_for_rolling(response, symbols)
4334
+ else:
4335
+ request: dict = {}
4336
+ if symbols is not None:
4337
+ request['symbols'] = self.json(self.market_ids(symbols))
4338
+ response = self.publicGetTicker24hr(self.extend(request, params))
4293
4339
  elif type == 'option':
4294
4340
  response = self.eapiPublicGetTicker(params)
4295
4341
  else:
4296
4342
  raise NotSupported(self.id + ' fetchTickers() does not support ' + type + ' markets yet')
4297
4343
  return self.parse_tickers(response, symbols)
4298
4344
 
4345
+ def parse_tickers_for_rolling(self, response, symbols):
4346
+ results = []
4347
+ for i in range(0, len(response)):
4348
+ marketId = self.safe_string(response[i], 'symbol')
4349
+ tickerMarket = self.safe_market(marketId, None, None, 'spot')
4350
+ parsedTicker = self.parse_ticker(response[i])
4351
+ parsedTicker['symbol'] = tickerMarket['symbol']
4352
+ results.append(parsedTicker)
4353
+ return self.filter_by_array(results, 'symbol', symbols)
4354
+
4299
4355
  def fetch_mark_price(self, symbol: str, params={}) -> Ticker:
4300
4356
  """
4301
4357
  fetches mark price for the market
ccxt/binancecoinm.py CHANGED
@@ -32,7 +32,11 @@ class binancecoinm(binance, ImplicitAPI):
32
32
  'createStopMarketOrder': True,
33
33
  },
34
34
  'options': {
35
- 'fetchMarkets': ['inverse'],
35
+ 'fetchMarkets': {
36
+ 'types': [
37
+ 'inverse',
38
+ ],
39
+ },
36
40
  'defaultSubType': 'inverse',
37
41
  'leverageBrackets': None,
38
42
  },
ccxt/binanceus.py CHANGED
@@ -43,7 +43,9 @@ class binanceus(binance, ImplicitAPI):
43
43
  },
44
44
  },
45
45
  'options': {
46
- 'fetchMarkets': ['spot'],
46
+ 'fetchMarkets': {
47
+ 'types': ['spot'],
48
+ },
47
49
  'defaultType': 'spot',
48
50
  'fetchMargins': False,
49
51
  'quoteOrderQty': False,
ccxt/binanceusdm.py CHANGED
@@ -33,7 +33,9 @@ class binanceusdm(binance, ImplicitAPI):
33
33
  'createStopMarketOrder': True,
34
34
  },
35
35
  'options': {
36
- 'fetchMarkets': ['linear'],
36
+ 'fetchMarkets': {
37
+ 'types': ['linear'],
38
+ },
37
39
  'defaultSubType': 'linear',
38
40
  # https://www.binance.com/en/support/faq/360033162192
39
41
  # tier amount, maintenance margin, initial margin,
ccxt/bingx.py CHANGED
@@ -5057,7 +5057,7 @@ class bingx(Exchange, ImplicitAPI):
5057
5057
  id = self.safe_string(transaction, 'id', dataId)
5058
5058
  address = self.safe_string(transaction, 'address')
5059
5059
  tag = self.safe_string(transaction, 'addressTag')
5060
- timestamp = self.safe_integer(transaction, 'insertTime')
5060
+ timestamp = self.safe_integer_2(transaction, 'insertTime', 'timestamp')
5061
5061
  datetime = self.iso8601(timestamp)
5062
5062
  if timestamp is None:
5063
5063
  datetime = self.safe_string(transaction, 'applyTime')
ccxt/bitget.py CHANGED
@@ -3816,6 +3816,9 @@ class bitget(Exchange, ImplicitAPI):
3816
3816
  if historicalEndpointNeeded:
3817
3817
  response = self.publicSpotGetV2SpotMarketHistoryCandles(self.extend(request, params))
3818
3818
  else:
3819
+ if not limitDefined:
3820
+ request['limit'] = 1000
3821
+ limit = 1000
3819
3822
  response = self.publicSpotGetV2SpotMarketCandles(self.extend(request, params))
3820
3823
  else:
3821
3824
  priceType = None
@@ -3824,8 +3827,14 @@ class bitget(Exchange, ImplicitAPI):
3824
3827
  productType, params = self.handle_product_type_and_params(market, params)
3825
3828
  request['productType'] = productType
3826
3829
  extended = self.extend(request, params)
3827
- # todo: mark & index also have their "recent" endpoints, but not priority now.
3828
- if priceType == 'mark':
3830
+ if not historicalEndpointNeeded and (priceType == 'mark' or priceType == 'index'):
3831
+ if not limitDefined:
3832
+ extended['limit'] = 1000
3833
+ limit = 1000
3834
+ # Recent endpoint for mark/index prices
3835
+ # https://www.bitget.com/api-doc/contract/market/Get-Candle-Data
3836
+ response = self.publicMixGetV2MixMarketCandles(self.extend({'kLineType': priceType}, extended))
3837
+ elif priceType == 'mark':
3829
3838
  response = self.publicMixGetV2MixMarketHistoryMarkCandles(extended)
3830
3839
  elif priceType == 'index':
3831
3840
  response = self.publicMixGetV2MixMarketHistoryIndexCandles(extended)
@@ -3833,6 +3842,9 @@ class bitget(Exchange, ImplicitAPI):
3833
3842
  if historicalEndpointNeeded:
3834
3843
  response = self.publicMixGetV2MixMarketHistoryCandles(extended)
3835
3844
  else:
3845
+ if not limitDefined:
3846
+ extended['limit'] = 1000
3847
+ limit = 1000
3836
3848
  response = self.publicMixGetV2MixMarketCandles(extended)
3837
3849
  if response == '':
3838
3850
  return [] # happens when a new token is listed
ccxt/coinmetro.py CHANGED
@@ -220,7 +220,6 @@ class coinmetro(Exchange, ImplicitAPI):
220
220
  'options': {
221
221
  'currenciesByIdForParseMarket': None,
222
222
  'currencyIdsListForParseMarket': ['QRDO'],
223
- 'skippedMarkets': ['VXVUSDT'], # broken markets which do not have enough info in API
224
223
  },
225
224
  'features': {
226
225
  'spot': {
@@ -461,11 +460,11 @@ class coinmetro(Exchange, ImplicitAPI):
461
460
  # ...
462
461
  # ]
463
462
  #
464
- skippedMarkets = self.safe_list(self.options, 'skippedMarkets', [])
465
463
  result = []
466
464
  for i in range(0, len(response)):
467
465
  market = self.parse_market(response[i])
468
- if self.in_array(market['id'], skippedMarkets):
466
+ # there are several broken(unavailable info) markets
467
+ if market['base'] is None or market['quote'] is None:
469
468
  continue
470
469
  result.append(market)
471
470
  return result
ccxt/cryptocom.py CHANGED
@@ -6,7 +6,8 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.cryptocom import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Account, Any, Balances, Currencies, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, TradingFees, Transaction
9
+ import math
10
+ from ccxt.base.types import Account, Any, Balances, Currencies, Currency, DepositAddress, Int, LedgerEntry, Market, Num, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, Trade, TradingFeeInterface, TradingFees, Transaction
10
11
  from typing import List
11
12
  from ccxt.base.errors import ExchangeError
12
13
  from ccxt.base.errors import AuthenticationError
@@ -79,7 +80,7 @@ class cryptocom(Exchange, ImplicitAPI):
79
80
  'fetchDepositWithdrawFee': 'emulated',
80
81
  'fetchDepositWithdrawFees': True,
81
82
  'fetchFundingHistory': False,
82
- 'fetchFundingRate': False,
83
+ 'fetchFundingRate': True,
83
84
  'fetchFundingRateHistory': True,
84
85
  'fetchFundingRates': False,
85
86
  'fetchGreeks': False,
@@ -480,6 +481,7 @@ class cryptocom(Exchange, ImplicitAPI):
480
481
  'exceptions': {
481
482
  'exact': {
482
483
  '219': InvalidOrder,
484
+ '306': InsufficientFunds, # {"id" : 1753xxx, "method" : "private/amend-order", "code" : 306, "message" : "INSUFFICIENT_AVAILABLE_BALANCE", "result" : {"client_oid" : "1753xxx", "order_id" : "6530xxx"}}
483
485
  '314': InvalidOrder, # {"id" : 1700xxx, "method" : "private/create-order", "code" : 314, "message" : "EXCEEDS_MAX_ORDER_SIZE", "result" : {"client_oid" : "1700xxx", "order_id" : "6530xxx"}}
484
486
  '325': InvalidOrder, # {"id" : 1741xxx, "method" : "private/create-order", "code" : 325, "message" : "EXCEED_DAILY_VOL_LIMIT", "result" : {"client_oid" : "1741xxx", "order_id" : "6530xxx"}}
485
487
  '415': InvalidOrder, # {"id" : 1741xxx, "method" : "private/create-order", "code" : 415, "message" : "BELOW_MIN_ORDER_SIZE", "result" : {"client_oid" : "1741xxx", "order_id" : "6530xxx"}}
@@ -2849,6 +2851,79 @@ class cryptocom(Exchange, ImplicitAPI):
2849
2851
  result.append(self.parse_settlement(settlements[i], market))
2850
2852
  return result
2851
2853
 
2854
+ def fetch_funding_rate(self, symbol: str, params={}):
2855
+ """
2856
+ fetches historical funding rates
2857
+
2858
+ https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-valuations
2859
+
2860
+ :param str symbol: unified symbol of the market to fetch the funding rate history for
2861
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2862
+ :returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>`
2863
+ """
2864
+ self.load_markets()
2865
+ market = self.market(symbol)
2866
+ if not market['swap']:
2867
+ raise BadSymbol(self.id + ' fetchFundingRate() supports swap contracts only')
2868
+ request: dict = {
2869
+ 'instrument_name': market['id'],
2870
+ 'valuation_type': 'estimated_funding_rate',
2871
+ 'count': 1,
2872
+ }
2873
+ response = self.v1PublicGetPublicGetValuations(self.extend(request, params))
2874
+ #
2875
+ # {
2876
+ # "id": -1,
2877
+ # "method": "public/get-valuations",
2878
+ # "code": 0,
2879
+ # "result": {
2880
+ # "data": [
2881
+ # {
2882
+ # "v": "-0.000001884",
2883
+ # "t": 1687892400000
2884
+ # },
2885
+ # ],
2886
+ # "instrument_name": "BTCUSD-PERP"
2887
+ # }
2888
+ # }
2889
+ #
2890
+ result = self.safe_dict(response, 'result', {})
2891
+ data = self.safe_list(result, 'data', [])
2892
+ entry = self.safe_dict(data, 0, {})
2893
+ return self.parse_funding_rate(entry, market)
2894
+
2895
+ def parse_funding_rate(self, contract, market: Market = None) -> FundingRate:
2896
+ #
2897
+ # {
2898
+ # "v": "-0.000001884",
2899
+ # "t": 1687892400000
2900
+ # },
2901
+ #
2902
+ timestamp = self.safe_integer(contract, 't')
2903
+ fundingTimestamp = None
2904
+ if timestamp is not None:
2905
+ fundingTimestamp = int(math.ceil(timestamp / 3600000)) * 3600000 # end of the next hour
2906
+ return {
2907
+ 'info': contract,
2908
+ 'symbol': self.safe_symbol(None, market),
2909
+ 'markPrice': None,
2910
+ 'indexPrice': None,
2911
+ 'interestRate': None,
2912
+ 'estimatedSettlePrice': None,
2913
+ 'timestamp': timestamp,
2914
+ 'datetime': self.iso8601(timestamp),
2915
+ 'fundingRate': self.safe_number(contract, 'v'),
2916
+ 'fundingTimestamp': fundingTimestamp,
2917
+ 'fundingDatetime': self.iso8601(fundingTimestamp),
2918
+ 'nextFundingRate': None,
2919
+ 'nextFundingTimestamp': None,
2920
+ 'nextFundingDatetime': None,
2921
+ 'previousFundingRate': None,
2922
+ 'previousFundingTimestamp': None,
2923
+ 'previousFundingDatetime': None,
2924
+ 'interval': '1h',
2925
+ }
2926
+
2852
2927
  def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
2853
2928
  """
2854
2929
  fetches historical funding rates
ccxt/exmo.py CHANGED
@@ -956,7 +956,7 @@ class exmo(Exchange, ImplicitAPI):
956
956
  request['from'] = to - (limit * duration) - 1
957
957
  request['to'] = to
958
958
  else:
959
- request['from'] = self.parse_to_int(since / 1000) - 1
959
+ request['from'] = self.parse_to_int(since / 1000)
960
960
  if untilIsDefined:
961
961
  request['to'] = min(until, now)
962
962
  else:
ccxt/foxbit.py CHANGED
@@ -95,7 +95,7 @@ class foxbit(Exchange, ImplicitAPI):
95
95
  '1M': '1M',
96
96
  },
97
97
  'urls': {
98
- 'logo': 'https://github.com/user-attachments/assets/63be1a3a-775d-459b-8c03-493c71c0253c',
98
+ 'logo': 'https://github.com/user-attachments/assets/ba1435eb-1d59-4393-8de7-0db10a002fb3',
99
99
  'api': {
100
100
  'public': 'https://api.foxbit.com.br',
101
101
  'private': 'https://api.foxbit.com.br',
ccxt/gate.py CHANGED
@@ -686,7 +686,6 @@ class gate(Exchange, ImplicitAPI):
686
686
  'SOL': 'SOL',
687
687
  'POLYGON': 'POL',
688
688
  'MATIC': 'POL',
689
- 'OP': 'OPETH',
690
689
  'OPTIMISM': 'OPETH',
691
690
  'ADA': 'ADA', # CARDANO
692
691
  'AVAXC': 'AVAX_C',
@@ -3788,7 +3787,7 @@ class gate(Exchange, ImplicitAPI):
3788
3787
  start = self.parse_to_int(since / 1000)
3789
3788
  request['from'] = start
3790
3789
  request['to'] = self.sum(start, 30 * 24 * 60 * 60)
3791
- request, params = self.handle_until_option('to', request, params)
3790
+ request, params = self.handle_until_option('to', request, params, 0.001)
3792
3791
  response = self.privateWalletGetWithdrawals(self.extend(request, params))
3793
3792
  return self.parse_transactions(response, currency)
3794
3793
 
ccxt/hashkey.py CHANGED
@@ -55,11 +55,15 @@ class hashkey(Exchange, ImplicitAPI):
55
55
  'future': False,
56
56
  'option': False,
57
57
  'addMargin': False,
58
+ 'borrowCrossMargin': False,
59
+ 'borrowIsolatedMargin': False,
60
+ 'borrowMargin': False,
58
61
  'cancelAllOrders': True,
59
62
  'cancelAllOrdersAfter': False,
60
63
  'cancelOrder': True,
61
64
  'cancelOrders': True,
62
65
  'cancelWithdraw': False,
66
+ 'closeAllPositions': False,
63
67
  'closePosition': False,
64
68
  'createConvertTrade': False,
65
69
  'createDepositAddress': False,
@@ -79,7 +83,14 @@ class hashkey(Exchange, ImplicitAPI):
79
83
  'createTrailingPercentOrder': False,
80
84
  'createTriggerOrder': True,
81
85
  'fetchAccounts': True,
86
+ 'fetchAllGreeks': False,
82
87
  'fetchBalance': True,
88
+ 'fetchBorrowInterest': False,
89
+ 'fetchBorrowRate': False,
90
+ 'fetchBorrowRateHistories': False,
91
+ 'fetchBorrowRateHistory': False,
92
+ 'fetchBorrowRates': False,
93
+ 'fetchBorrowRatesPerSymbol': False,
83
94
  'fetchCanceledAndClosedOrders': True,
84
95
  'fetchCanceledOrders': True,
85
96
  'fetchClosedOrder': True,
@@ -88,6 +99,8 @@ class hashkey(Exchange, ImplicitAPI):
88
99
  'fetchConvertQuote': False,
89
100
  'fetchConvertTrade': False,
90
101
  'fetchConvertTradeHistory': False,
102
+ 'fetchCrossBorrowRate': False,
103
+ 'fetchCrossBorrowRates': False,
91
104
  'fetchCurrencies': True,
92
105
  'fetchDepositAddress': True,
93
106
  'fetchDepositAddresses': False,
@@ -95,23 +108,42 @@ class hashkey(Exchange, ImplicitAPI):
95
108
  'fetchDeposits': True,
96
109
  'fetchDepositsWithdrawals': False,
97
110
  'fetchFundingHistory': False,
111
+ 'fetchFundingInterval': False,
112
+ 'fetchFundingIntervals': False,
98
113
  'fetchFundingRate': True,
99
114
  'fetchFundingRateHistory': True,
100
115
  'fetchFundingRates': True,
116
+ 'fetchGreeks': False,
101
117
  'fetchIndexOHLCV': False,
118
+ 'fetchIsolatedBorrowRate': False,
119
+ 'fetchIsolatedBorrowRates': False,
120
+ 'fetchIsolatedPositions': False,
102
121
  'fetchLedger': True,
103
122
  'fetchLeverage': True,
123
+ 'fetchLeverages': False,
104
124
  'fetchLeverageTiers': True,
125
+ 'fetchLiquidations': False,
126
+ 'fetchLongShortRatio': False,
127
+ 'fetchLongShortRatioHistory': False,
105
128
  'fetchMarginAdjustmentHistory': False,
106
129
  'fetchMarginMode': False,
130
+ 'fetchMarginModes': False,
107
131
  'fetchMarketLeverageTiers': 'emulated',
108
132
  'fetchMarkets': True,
109
133
  'fetchMarkOHLCV': False,
134
+ 'fetchMarkPrice': False,
135
+ 'fetchMarkPrices': False,
136
+ 'fetchMyLiquidations': False,
137
+ 'fetchMySettlementHistory': False,
110
138
  'fetchMyTrades': True,
111
139
  'fetchOHLCV': True,
140
+ 'fetchOpenInterest': False,
112
141
  'fetchOpenInterestHistory': False,
142
+ 'fetchOpenInterests': False,
113
143
  'fetchOpenOrder': False,
114
144
  'fetchOpenOrders': True,
145
+ 'fetchOption': False,
146
+ 'fetchOptionChain': False,
115
147
  'fetchOrder': True,
116
148
  'fetchOrderBook': True,
117
149
  'fetchOrders': False,
@@ -122,7 +154,9 @@ class hashkey(Exchange, ImplicitAPI):
122
154
  'fetchPositions': True,
123
155
  'fetchPositionsForSymbol': True,
124
156
  'fetchPositionsHistory': False,
157
+ 'fetchPositionsRisk': False,
125
158
  'fetchPremiumIndexOHLCV': False,
159
+ 'fetchSettlementHistory': False,
126
160
  'fetchStatus': True,
127
161
  'fetchTicker': True,
128
162
  'fetchTickers': True,
@@ -132,11 +166,16 @@ class hashkey(Exchange, ImplicitAPI):
132
166
  'fetchTradingFees': True, # for spot markets only
133
167
  'fetchTransactions': False,
134
168
  'fetchTransfers': False,
169
+ 'fetchUnderlyingAssets': False,
170
+ 'fetchVolatilityHistory': False,
135
171
  'fetchWithdrawals': True,
136
172
  'reduceMargin': False,
173
+ 'repayCrossMargin': False,
174
+ 'repayIsolatedMargin': False,
137
175
  'sandbox': False,
138
176
  'setLeverage': True,
139
177
  'setMargin': False,
178
+ 'setMarginMode': False,
140
179
  'setPositionMode': False,
141
180
  'transfer': True,
142
181
  'withdraw': True,
ccxt/hyperliquid.py CHANGED
@@ -2964,10 +2964,9 @@ class hyperliquid(Exchange, ImplicitAPI):
2964
2964
  if not self.in_array(toAccount, ['spot', 'swap', 'perp']):
2965
2965
  raise NotSupported(self.id + ' transfer() only support spot <> swap transfer')
2966
2966
  strAmount = self.number_to_string(amount)
2967
- vaultAddress = None
2968
- vaultAddress, params = self.handle_option_and_params(params, 'transfer', 'vaultAddress')
2969
- vaultAddress = self.format_vault_address(vaultAddress)
2967
+ vaultAddress = self.safe_string_2(params, 'vaultAddress', 'subAccountAddress')
2970
2968
  if vaultAddress is not None:
2969
+ vaultAddress = self.format_vault_address(vaultAddress)
2971
2970
  strAmount = strAmount + ' subaccount:' + vaultAddress
2972
2971
  toPerp = (toAccount == 'perp') or (toAccount == 'swap')
2973
2972
  transferPayload: dict = {
@@ -2994,10 +2993,6 @@ class hyperliquid(Exchange, ImplicitAPI):
2994
2993
  transferResponse = self.privatePostExchange(transferRequest)
2995
2994
  return transferResponse
2996
2995
  # transfer between main account and subaccount
2997
- if code is not None:
2998
- code = code.upper()
2999
- if code != 'USDC':
3000
- raise NotSupported(self.id + ' transfer() only support USDC')
3001
2996
  isDeposit = False
3002
2997
  subAccountAddress = None
3003
2998
  if fromAccount == 'main':
@@ -3008,24 +3003,44 @@ class hyperliquid(Exchange, ImplicitAPI):
3008
3003
  else:
3009
3004
  raise NotSupported(self.id + ' transfer() only support main <> subaccount transfer')
3010
3005
  self.check_address(subAccountAddress)
3011
- usd = self.parse_to_int(Precise.string_mul(self.number_to_string(amount), '1000000'))
3012
- action = {
3013
- 'type': 'subAccountTransfer',
3014
- 'subAccountUser': subAccountAddress,
3015
- 'isDeposit': isDeposit,
3016
- 'usd': usd,
3017
- }
3018
- sig = self.sign_l1_action(action, nonce)
3019
- request: dict = {
3020
- 'action': action,
3021
- 'nonce': nonce,
3022
- 'signature': sig,
3023
- }
3024
- response = self.privatePostExchange(request)
3025
- #
3026
- # {'response': {'type': 'default'}, 'status': 'ok'}
3027
- #
3028
- return self.parse_transfer(response)
3006
+ if code is None or code.upper() == 'USDC':
3007
+ # Transfer USDC with subAccountTransfer
3008
+ usd = self.parse_to_int(Precise.string_mul(self.number_to_string(amount), '1000000'))
3009
+ action = {
3010
+ 'type': 'subAccountTransfer',
3011
+ 'subAccountUser': subAccountAddress,
3012
+ 'isDeposit': isDeposit,
3013
+ 'usd': usd,
3014
+ }
3015
+ sig = self.sign_l1_action(action, nonce)
3016
+ request: dict = {
3017
+ 'action': action,
3018
+ 'nonce': nonce,
3019
+ 'signature': sig,
3020
+ }
3021
+ response = self.privatePostExchange(request)
3022
+ #
3023
+ # {'response': {'type': 'default'}, 'status': 'ok'}
3024
+ #
3025
+ return self.parse_transfer(response)
3026
+ else:
3027
+ # Transfer non-USDC with subAccountSpotTransfer
3028
+ symbol = self.symbol(code)
3029
+ action = {
3030
+ 'type': 'subAccountSpotTransfer',
3031
+ 'subAccountUser': subAccountAddress,
3032
+ 'isDeposit': isDeposit,
3033
+ 'token': symbol,
3034
+ 'amount': self.number_to_string(amount),
3035
+ }
3036
+ sig = self.sign_l1_action(action, nonce)
3037
+ request: dict = {
3038
+ 'action': action,
3039
+ 'nonce': nonce,
3040
+ 'signature': sig,
3041
+ }
3042
+ response = self.privatePostExchange(request)
3043
+ return self.parse_transfer(response)
3029
3044
 
3030
3045
  def parse_transfer(self, transfer: dict, currency: Currency = None) -> TransferEntry:
3031
3046
  #