ccxt 4.2.86__py2.py3-none-any.whl → 4.2.88__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (82) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/ascendex.py +16 -6
  3. ccxt/async_support/__init__.py +1 -1
  4. ccxt/async_support/ascendex.py +16 -6
  5. ccxt/async_support/base/exchange.py +1 -1
  6. ccxt/async_support/binance.py +28 -11
  7. ccxt/async_support/bingx.py +39 -3
  8. ccxt/async_support/bitfinex.py +2 -0
  9. ccxt/async_support/bitfinex2.py +18 -4
  10. ccxt/async_support/bitflyer.py +18 -0
  11. ccxt/async_support/bitget.py +37 -22
  12. ccxt/async_support/bitopro.py +2 -0
  13. ccxt/async_support/bitrue.py +16 -8
  14. ccxt/async_support/bitvavo.py +2 -0
  15. ccxt/async_support/btcmarkets.py +1 -1
  16. ccxt/async_support/btcturk.py +2 -1
  17. ccxt/async_support/coinex.py +182 -58
  18. ccxt/async_support/cryptocom.py +1 -1
  19. ccxt/async_support/currencycom.py +1 -1
  20. ccxt/async_support/delta.py +8 -6
  21. ccxt/async_support/digifinex.py +9 -7
  22. ccxt/async_support/exmo.py +15 -15
  23. ccxt/async_support/gate.py +23 -20
  24. ccxt/async_support/hitbtc.py +31 -7
  25. ccxt/async_support/htx.py +2 -2
  26. ccxt/async_support/huobijp.py +1 -1
  27. ccxt/async_support/hyperliquid.py +242 -16
  28. ccxt/async_support/idex.py +1 -1
  29. ccxt/async_support/krakenfutures.py +4 -5
  30. ccxt/async_support/kucoin.py +7 -4
  31. ccxt/async_support/kucoinfutures.py +2 -2
  32. ccxt/async_support/lbank.py +2 -0
  33. ccxt/async_support/mexc.py +4 -4
  34. ccxt/async_support/oceanex.py +1 -1
  35. ccxt/async_support/okx.py +29 -15
  36. ccxt/async_support/phemex.py +6 -4
  37. ccxt/async_support/wazirx.py +1 -1
  38. ccxt/async_support/zonda.py +2 -0
  39. ccxt/base/exchange.py +22 -3
  40. ccxt/base/types.py +12 -0
  41. ccxt/binance.py +28 -11
  42. ccxt/bingx.py +39 -3
  43. ccxt/bitfinex.py +2 -0
  44. ccxt/bitfinex2.py +18 -4
  45. ccxt/bitflyer.py +18 -0
  46. ccxt/bitget.py +37 -22
  47. ccxt/bitopro.py +2 -0
  48. ccxt/bitrue.py +16 -8
  49. ccxt/bitvavo.py +2 -0
  50. ccxt/btcmarkets.py +1 -1
  51. ccxt/btcturk.py +2 -1
  52. ccxt/coinex.py +182 -58
  53. ccxt/cryptocom.py +1 -1
  54. ccxt/currencycom.py +1 -1
  55. ccxt/delta.py +8 -6
  56. ccxt/digifinex.py +9 -7
  57. ccxt/exmo.py +15 -15
  58. ccxt/gate.py +23 -20
  59. ccxt/hitbtc.py +31 -7
  60. ccxt/htx.py +2 -2
  61. ccxt/huobijp.py +1 -1
  62. ccxt/hyperliquid.py +241 -16
  63. ccxt/idex.py +1 -1
  64. ccxt/krakenfutures.py +4 -5
  65. ccxt/kucoin.py +7 -4
  66. ccxt/kucoinfutures.py +2 -2
  67. ccxt/lbank.py +2 -0
  68. ccxt/mexc.py +4 -4
  69. ccxt/oceanex.py +1 -1
  70. ccxt/okx.py +29 -15
  71. ccxt/phemex.py +6 -4
  72. ccxt/pro/__init__.py +1 -1
  73. ccxt/pro/kucoin.py +10 -6
  74. ccxt/test/base/test_last_price.py +0 -1
  75. ccxt/test/base/test_shared_methods.py +1 -2
  76. ccxt/test/base/test_status.py +1 -1
  77. ccxt/wazirx.py +1 -1
  78. ccxt/zonda.py +2 -0
  79. {ccxt-4.2.86.dist-info → ccxt-4.2.88.dist-info}/METADATA +5 -6
  80. {ccxt-4.2.86.dist-info → ccxt-4.2.88.dist-info}/RECORD +82 -82
  81. {ccxt-4.2.86.dist-info → ccxt-4.2.88.dist-info}/WHEEL +0 -0
  82. {ccxt-4.2.86.dist-info → ccxt-4.2.88.dist-info}/top_level.txt +0 -0
@@ -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, Currency, FundingHistory, Greeks, Int, Leverage, Leverages, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
+ from ccxt.base.types import Balances, Currency, FundingHistory, Greeks, Int, Leverage, Leverages, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import PermissionDenied
@@ -1824,7 +1824,7 @@ class gate(Exchange, ImplicitAPI):
1824
1824
  await self.load_markets()
1825
1825
  currency = self.currency(code)
1826
1826
  request = {
1827
- 'currency': currency['id'],
1827
+ 'currency': currency['id'], # todo: currencies have network-junctions
1828
1828
  }
1829
1829
  response = await self.privateWalletGetDepositAddress(self.extend(request, params))
1830
1830
  addresses = self.safe_value(response, 'multichain_addresses')
@@ -1871,7 +1871,7 @@ class gate(Exchange, ImplicitAPI):
1871
1871
  rawNetwork = self.safe_string_upper(params, 'network')
1872
1872
  params = self.omit(params, 'network')
1873
1873
  request = {
1874
- 'currency': currency['id'],
1874
+ 'currency': currency['id'], # todo: currencies have network-junctions
1875
1875
  }
1876
1876
  response = await self.privateWalletGetDepositAddress(self.extend(request, params))
1877
1877
  #
@@ -3346,7 +3346,7 @@ class gate(Exchange, ImplicitAPI):
3346
3346
  currency = None
3347
3347
  if code is not None:
3348
3348
  currency = self.currency(code)
3349
- request['currency'] = currency['id']
3349
+ request['currency'] = currency['id'] # todo: currencies have network-junctions
3350
3350
  if limit is not None:
3351
3351
  request['limit'] = limit
3352
3352
  if since is not None:
@@ -3378,7 +3378,7 @@ class gate(Exchange, ImplicitAPI):
3378
3378
  currency = None
3379
3379
  if code is not None:
3380
3380
  currency = self.currency(code)
3381
- request['currency'] = currency['id']
3381
+ request['currency'] = currency['id'] # todo: currencies have network-junctions
3382
3382
  if limit is not None:
3383
3383
  request['limit'] = limit
3384
3384
  if since is not None:
@@ -3405,7 +3405,7 @@ class gate(Exchange, ImplicitAPI):
3405
3405
  await self.load_markets()
3406
3406
  currency = self.currency(code)
3407
3407
  request = {
3408
- 'currency': currency['id'],
3408
+ 'currency': currency['id'], # todo: currencies have network-junctions
3409
3409
  'address': address,
3410
3410
  'amount': self.currency_to_precision(code, amount),
3411
3411
  }
@@ -3418,7 +3418,7 @@ class gate(Exchange, ImplicitAPI):
3418
3418
  request['chain'] = network
3419
3419
  params = self.omit(params, 'network')
3420
3420
  else:
3421
- request['chain'] = currency['id']
3421
+ request['chain'] = currency['id'] # todo: currencies have network-junctions
3422
3422
  response = await self.privateWithdrawalsPostWithdrawals(self.extend(request, params))
3423
3423
  #
3424
3424
  # {
@@ -4762,7 +4762,7 @@ class gate(Exchange, ImplicitAPI):
4762
4762
  toId = self.convert_type_to_account(toAccount)
4763
4763
  truncated = self.currency_to_precision(code, amount)
4764
4764
  request = {
4765
- 'currency': currency['id'],
4765
+ 'currency': currency['id'], # todo: currencies have network-junctions
4766
4766
  'amount': truncated,
4767
4767
  }
4768
4768
  if not (fromId in self.options['accountsByType']):
@@ -4783,7 +4783,7 @@ class gate(Exchange, ImplicitAPI):
4783
4783
  request['currency_pair'] = market['id']
4784
4784
  params = self.omit(params, 'symbol')
4785
4785
  if (toId == 'futures') or (toId == 'delivery') or (fromId == 'futures') or (fromId == 'delivery'):
4786
- request['settle'] = currency['id']
4786
+ request['settle'] = currency['id'] # todo: currencies have network-junctions
4787
4787
  response = await self.privateWalletPostTransfers(self.extend(request, params))
4788
4788
  #
4789
4789
  # according to the docs(however actual response seems to be an empty string '')
@@ -5396,7 +5396,7 @@ class gate(Exchange, ImplicitAPI):
5396
5396
  await self.load_markets()
5397
5397
  currency = self.currency(code)
5398
5398
  request = {
5399
- 'currency': currency['id'].upper(),
5399
+ 'currency': currency['id'].upper(), # todo: currencies have network-junctions
5400
5400
  'amount': self.currency_to_precision(code, amount),
5401
5401
  }
5402
5402
  market = self.market(symbol)
@@ -5423,7 +5423,7 @@ class gate(Exchange, ImplicitAPI):
5423
5423
  await self.load_markets()
5424
5424
  currency = self.currency(code)
5425
5425
  request = {
5426
- 'currency': currency['id'].upper(),
5426
+ 'currency': currency['id'].upper(), # todo: currencies have network-junctions
5427
5427
  'amount': self.currency_to_precision(code, amount),
5428
5428
  }
5429
5429
  response = await self.privateMarginPostCrossRepayments(self.extend(request, params))
@@ -5460,7 +5460,7 @@ class gate(Exchange, ImplicitAPI):
5460
5460
  await self.load_markets()
5461
5461
  currency = self.currency(code)
5462
5462
  request = {
5463
- 'currency': currency['id'].upper(),
5463
+ 'currency': currency['id'].upper(), # todo: currencies have network-junctions
5464
5464
  'amount': self.currency_to_precision(code, amount),
5465
5465
  }
5466
5466
  response = None
@@ -5503,7 +5503,7 @@ class gate(Exchange, ImplicitAPI):
5503
5503
  await self.load_markets()
5504
5504
  currency = self.currency(code)
5505
5505
  request = {
5506
- 'currency': currency['id'].upper(),
5506
+ 'currency': currency['id'].upper(), # todo: currencies have network-junctions
5507
5507
  'amount': self.currency_to_precision(code, amount),
5508
5508
  }
5509
5509
  response = await self.privateMarginPostCrossLoans(self.extend(request, params))
@@ -5651,7 +5651,7 @@ class gate(Exchange, ImplicitAPI):
5651
5651
  raise NotSupported(self.id + ' modifyMarginHelper() not support self market type')
5652
5652
  return self.parse_margin_modification(response, market)
5653
5653
 
5654
- def parse_margin_modification(self, data, market: Market = None):
5654
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
5655
5655
  #
5656
5656
  # {
5657
5657
  # "value": "11.9257",
@@ -5684,14 +5684,17 @@ class gate(Exchange, ImplicitAPI):
5684
5684
  total = self.safe_number(data, 'margin')
5685
5685
  return {
5686
5686
  'info': data,
5687
- 'amount': None,
5688
- 'code': self.safe_value(market, 'quote'),
5689
5687
  'symbol': market['symbol'],
5688
+ 'type': None,
5689
+ 'amount': None,
5690
5690
  'total': total,
5691
+ 'code': self.safe_value(market, 'quote'),
5691
5692
  'status': 'ok',
5693
+ 'timestamp': None,
5694
+ 'datetime': None,
5692
5695
  }
5693
5696
 
5694
- async def reduce_margin(self, symbol: str, amount, params={}):
5697
+ async def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
5695
5698
  """
5696
5699
  remove margin from a position
5697
5700
  :see: https://www.gate.io/docs/developers/apiv4/en/#update-position-margin
@@ -5703,7 +5706,7 @@ class gate(Exchange, ImplicitAPI):
5703
5706
  """
5704
5707
  return await self.modify_margin_helper(symbol, -amount, params)
5705
5708
 
5706
- async def add_margin(self, symbol: str, amount, params={}):
5709
+ async def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
5707
5710
  """
5708
5711
  add margin
5709
5712
  :see: https://www.gate.io/docs/developers/apiv4/en/#update-position-margin
@@ -5993,7 +5996,7 @@ class gate(Exchange, ImplicitAPI):
5993
5996
  if (type == 'spot') or (type == 'margin'):
5994
5997
  if code is not None:
5995
5998
  currency = self.currency(code)
5996
- request['currency'] = currency['id']
5999
+ request['currency'] = currency['id'] # todo: currencies have network-junctions
5997
6000
  if (type == 'swap') or (type == 'future'):
5998
6001
  defaultSettle = 'usdt' if (type == 'swap') else 'btc'
5999
6002
  settle = self.safe_string_lower(params, 'settle', defaultSettle)
@@ -6751,7 +6754,7 @@ class gate(Exchange, ImplicitAPI):
6751
6754
  await self.load_markets()
6752
6755
  currency = self.currency(code)
6753
6756
  request = {
6754
- 'underlying': currency['code'] + '_USDT',
6757
+ 'underlying': currency['code'] + '_USDT', # todo: currency['id'].upper() & network junctions
6755
6758
  }
6756
6759
  response = await self.publicOptionsGetContracts(self.extend(request, params))
6757
6760
  #
@@ -6,7 +6,7 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.hitbtc import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Int, Leverage, MarginMode, MarginModes, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
9
+ from ccxt.base.types import Balances, Currency, Int, Leverage, MarginMode, MarginModes, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import PermissionDenied
@@ -1658,7 +1658,7 @@ class hitbtc(Exchange, ImplicitAPI):
1658
1658
  request['from'] = self.iso8601(since)
1659
1659
  request, params = self.handle_until_option('till', request, params)
1660
1660
  if limit is not None:
1661
- request['limit'] = limit
1661
+ request['limit'] = min(limit, 1000)
1662
1662
  price = self.safe_string(params, 'price')
1663
1663
  params = self.omit(params, 'price')
1664
1664
  response = None
@@ -2999,7 +2999,7 @@ class hitbtc(Exchange, ImplicitAPI):
2999
2999
  'previousFundingDatetime': None,
3000
3000
  }
3001
3001
 
3002
- async def modify_margin_helper(self, symbol: str, amount, type, params={}):
3002
+ async def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
3003
3003
  await self.load_markets()
3004
3004
  market = self.market(symbol)
3005
3005
  leverage = self.safe_string(params, 'leverage')
@@ -3052,19 +3052,43 @@ class hitbtc(Exchange, ImplicitAPI):
3052
3052
  'type': type,
3053
3053
  })
3054
3054
 
3055
- def parse_margin_modification(self, data, market: Market = None):
3055
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
3056
+ #
3057
+ # addMargin/reduceMargin
3058
+ #
3059
+ # {
3060
+ # "symbol": "BTCUSDT_PERP",
3061
+ # "type": "isolated",
3062
+ # "leverage": "8.00",
3063
+ # "created_at": "2022-03-30T23:34:27.161Z",
3064
+ # "updated_at": "2022-03-30T23:34:27.161Z",
3065
+ # "currencies": [
3066
+ # {
3067
+ # "code": "USDT",
3068
+ # "margin_balance": "7.000000000000",
3069
+ # "reserved_orders": "0",
3070
+ # "reserved_positions": "0"
3071
+ # }
3072
+ # ],
3073
+ # "positions": null
3074
+ # }
3075
+ #
3056
3076
  currencies = self.safe_value(data, 'currencies', [])
3057
3077
  currencyInfo = self.safe_value(currencies, 0)
3078
+ datetime = self.safe_string(data, 'updated_at')
3058
3079
  return {
3059
3080
  'info': data,
3081
+ 'symbol': market['symbol'],
3060
3082
  'type': None,
3061
3083
  'amount': None,
3084
+ 'total': None,
3062
3085
  'code': self.safe_string(currencyInfo, 'code'),
3063
- 'symbol': market['symbol'],
3064
3086
  'status': None,
3087
+ 'timestamp': self.parse8601(datetime),
3088
+ 'datetime': datetime,
3065
3089
  }
3066
3090
 
3067
- async def reduce_margin(self, symbol: str, amount, params={}):
3091
+ async def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
3068
3092
  """
3069
3093
  remove margin from a position
3070
3094
  :see: https://api.hitbtc.com/#create-update-margin-account-2
@@ -3080,7 +3104,7 @@ class hitbtc(Exchange, ImplicitAPI):
3080
3104
  raise BadRequest(self.id + ' reduceMargin() on hitbtc requires the amount to be 0 and that will remove the entire margin amount')
3081
3105
  return await self.modify_margin_helper(symbol, amount, 'reduce', params)
3082
3106
 
3083
- async def add_margin(self, symbol: str, amount, params={}):
3107
+ async def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
3084
3108
  """
3085
3109
  add margin
3086
3110
  :see: https://api.hitbtc.com/#create-update-margin-account-2
ccxt/async_support/htx.py CHANGED
@@ -2834,7 +2834,7 @@ class htx(Exchange, ImplicitAPI):
2834
2834
  untilSeconds = self.parse_to_int(until / 1000) if (until is not None) else None
2835
2835
  if market['contract']:
2836
2836
  if limit is not None:
2837
- request['size'] = limit # when using limit: from & to are ignored
2837
+ request['size'] = min(limit, 2000) # when using limit: from & to are ignored
2838
2838
  # https://huobiapi.github.io/docs/usdt_swap/v1/en/#general-get-kline-data
2839
2839
  else:
2840
2840
  limit = 2000 # only used for from/to calculation
@@ -2898,7 +2898,7 @@ class htx(Exchange, ImplicitAPI):
2898
2898
  useHistorical, params = self.handle_option_and_params(params, 'fetchOHLCV', 'useHistoricalEndpointForSpot', True)
2899
2899
  if not useHistorical:
2900
2900
  if limit is not None:
2901
- request['size'] = min(2000, limit) # max 2000
2901
+ request['size'] = min(limit, 2000) # max 2000
2902
2902
  response = await self.spotPublicGetMarketHistoryKline(self.extend(request, params))
2903
2903
  else:
2904
2904
  # "from & to" only available for the self endpoint
@@ -927,7 +927,7 @@ class huobijp(Exchange, ImplicitAPI):
927
927
  'period': self.safe_string(self.timeframes, timeframe, timeframe),
928
928
  }
929
929
  if limit is not None:
930
- request['size'] = limit
930
+ request['size'] = min(limit, 2000)
931
931
  response = await self.marketGetHistoryKline(self.extend(request, params))
932
932
  #
933
933
  # {
@@ -5,7 +5,8 @@
5
5
 
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.hyperliquid import ImplicitAPI
8
- from ccxt.base.types import Balances, Int, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Trade, TransferEntry
8
+ import asyncio
9
+ from ccxt.base.types import Balances, Int, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Trade, TransferEntry
9
10
  from typing import List
10
11
  from ccxt.base.errors import ExchangeError
11
12
  from ccxt.base.errors import ArgumentsRequired
@@ -32,7 +33,7 @@ class hyperliquid(Exchange, ImplicitAPI):
32
33
  'pro': True,
33
34
  'has': {
34
35
  'CORS': None,
35
- 'spot': False,
36
+ 'spot': True,
36
37
  'margin': False,
37
38
  'swap': True,
38
39
  'future': True,
@@ -165,6 +166,10 @@ class hyperliquid(Exchange, ImplicitAPI):
165
166
  'taker': self.parse_number('0.00035'),
166
167
  'maker': self.parse_number('0.0001'),
167
168
  },
169
+ 'spot': {
170
+ 'taker': self.parse_number('0.00035'),
171
+ 'maker': self.parse_number('0.0001'),
172
+ },
168
173
  },
169
174
  'requiredCredentials': {
170
175
  'apiKey': False,
@@ -192,6 +197,7 @@ class hyperliquid(Exchange, ImplicitAPI):
192
197
  'commonCurrencies': {
193
198
  },
194
199
  'options': {
200
+ 'defaultType': 'swap',
195
201
  'sandboxMode': False,
196
202
  'defaultSlippage': 0.05,
197
203
  'zeroAddress': '0x0000000000000000000000000000000000000000',
@@ -257,6 +263,22 @@ class hyperliquid(Exchange, ImplicitAPI):
257
263
  :param dict [params]: extra parameters specific to the exchange API endpoint
258
264
  :returns dict[]: an array of objects representing market data
259
265
  """
266
+ rawPromises = [
267
+ self.fetch_swap_markets(params),
268
+ self.fetch_spot_markets(params),
269
+ ]
270
+ promises = await asyncio.gather(*rawPromises)
271
+ swapMarkets = promises[0]
272
+ spotMarkets = promises[1]
273
+ return self.array_concat(swapMarkets, spotMarkets)
274
+
275
+ async def fetch_swap_markets(self, params={}) -> List[Market]:
276
+ """
277
+ retrieves data on all swap markets for hyperliquid
278
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-asset-contexts-includes-mark-price-current-funding-open-interest-etc
279
+ :param dict [params]: extra parameters specific to the exchange API endpoint
280
+ :returns dict[]: an array of objects representing market data
281
+ """
260
282
  request = {
261
283
  'type': 'metaAndAssetCtxs',
262
284
  }
@@ -304,6 +326,129 @@ class hyperliquid(Exchange, ImplicitAPI):
304
326
  result.append(data)
305
327
  return self.parse_markets(result)
306
328
 
329
+ async def fetch_spot_markets(self, params={}) -> List[Market]:
330
+ """
331
+ retrieves data on all spot markets for hyperliquid
332
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-asset-contexts-includes-mark-price-current-funding-open-interest-etc
333
+ :param dict [params]: extra parameters specific to the exchange API endpoint
334
+ :returns dict[]: an array of objects representing market data
335
+ """
336
+ request = {
337
+ 'type': 'spotMetaAndAssetCtxs',
338
+ }
339
+ response = await self.publicPostInfo(self.extend(request, params))
340
+ #
341
+ # [
342
+ # {
343
+ # 'tokens': [
344
+ # {
345
+ # 'name': 'USDC',
346
+ # 'szDecimals': '8',
347
+ # 'weiDecimals': '8',
348
+ # },
349
+ # {
350
+ # 'name': 'PURR',
351
+ # 'szDecimals': '0',
352
+ # 'weiDecimals': '5',
353
+ # },
354
+ # ],
355
+ # 'universe': [
356
+ # {
357
+ # 'name': 'PURR/USDC',
358
+ # 'tokens': [
359
+ # 1,
360
+ # 0,
361
+ # ],
362
+ # },
363
+ # ],
364
+ # },
365
+ # [
366
+ # {
367
+ # 'dayNtlVlm': '264250385.14640012',
368
+ # 'markPx': '0.018314',
369
+ # 'midPx': '0.0182235',
370
+ # 'prevDayPx': '0.017427',
371
+ # },
372
+ # ],
373
+ # ]
374
+ #
375
+ first = self.safe_dict(response, 0, {})
376
+ meta = self.safe_list(first, 'universe', [])
377
+ tokens = self.safe_list(first, 'tokens', [])
378
+ markets = []
379
+ for i in range(0, len(meta)):
380
+ market = self.safe_dict(meta, i, {})
381
+ marketName = self.safe_string(market, 'name')
382
+ marketParts = marketName.split('/')
383
+ baseName = self.safe_string(marketParts, 0)
384
+ quoteId = self.safe_string(marketParts, 1)
385
+ base = self.safe_currency_code(baseName)
386
+ quote = self.safe_currency_code(quoteId)
387
+ symbol = base + '/' + quote
388
+ fees = self.safe_dict(self.fees, 'spot', {})
389
+ taker = self.safe_number(fees, 'taker')
390
+ maker = self.safe_number(fees, 'maker')
391
+ tokensPos = self.safe_list(market, 'tokens', [])
392
+ baseTokenPos = self.safe_integer(tokensPos, 0)
393
+ quoteTokenPos = self.safe_integer(tokensPos, 1)
394
+ baseTokenInfo = self.safe_dict(tokens, baseTokenPos, {})
395
+ quoteTokenInfo = self.safe_dict(tokens, quoteTokenPos, {})
396
+ baseDecimals = self.safe_string(baseTokenInfo, 'szDecimals')
397
+ quoteDecimals = self.safe_integer(quoteTokenInfo, 'szDecimals')
398
+ baseId = self.number_to_string(i + 10000)
399
+ markets.append(self.safe_market_structure({
400
+ 'id': baseId,
401
+ 'symbol': symbol,
402
+ 'base': base,
403
+ 'quote': quote,
404
+ 'settle': None,
405
+ 'baseId': baseId,
406
+ 'quoteId': quoteId,
407
+ 'settleId': None,
408
+ 'type': 'spot',
409
+ 'spot': True,
410
+ 'margin': None,
411
+ 'swap': False,
412
+ 'future': False,
413
+ 'option': False,
414
+ 'active': True,
415
+ 'contract': False,
416
+ 'linear': True,
417
+ 'inverse': False,
418
+ 'taker': taker,
419
+ 'maker': maker,
420
+ 'contractSize': None,
421
+ 'expiry': None,
422
+ 'expiryDatetime': None,
423
+ 'strike': None,
424
+ 'optionType': None,
425
+ 'precision': {
426
+ 'amount': self.parse_number(self.parse_precision(baseDecimals)), # decimal places
427
+ 'price': quoteDecimals, # significant digits
428
+ },
429
+ 'limits': {
430
+ 'leverage': {
431
+ 'min': None,
432
+ 'max': None,
433
+ },
434
+ 'amount': {
435
+ 'min': None,
436
+ 'max': None,
437
+ },
438
+ 'price': {
439
+ 'min': None,
440
+ 'max': None,
441
+ },
442
+ 'cost': {
443
+ 'min': None,
444
+ 'max': None,
445
+ },
446
+ },
447
+ 'created': None,
448
+ 'info': market,
449
+ }))
450
+ return markets
451
+
307
452
  def parse_market(self, market) -> Market:
308
453
  #
309
454
  # {
@@ -398,12 +543,17 @@ class hyperliquid(Exchange, ImplicitAPI):
398
543
  :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint#retrieve-a-users-state
399
544
  :param dict [params]: extra parameters specific to the exchange API endpoint
400
545
  :param str [params.user]: user address, will default to self.walletAddress if not provided
546
+ :param str [params.type]: wallet type, ['spot', 'swap'], defaults to swap
401
547
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
402
548
  """
403
549
  userAddress = None
404
550
  userAddress, params = self.handle_public_address('fetchBalance', params)
551
+ type = None
552
+ type, params = self.handle_market_type_and_params('fetchBalance', None, params)
553
+ isSpot = (type == 'spot')
554
+ reqType = 'spotClearinghouseState' if (isSpot) else 'clearinghouseState'
405
555
  request = {
406
- 'type': 'clearinghouseState',
556
+ 'type': reqType,
407
557
  'user': userAddress,
408
558
  }
409
559
  response = await self.publicPostInfo(self.extend(request, params))
@@ -426,7 +576,35 @@ class hyperliquid(Exchange, ImplicitAPI):
426
576
  # "time": "1704261007014",
427
577
  # "withdrawable": "100.0"
428
578
  # }
579
+ # spot
580
+ #
581
+ # {
582
+ # "balances":[
583
+ # {
584
+ # "coin":"USDC",
585
+ # "hold":"0.0",
586
+ # "total":"1481.844"
587
+ # },
588
+ # {
589
+ # "coin":"PURR",
590
+ # "hold":"0.0",
591
+ # "total":"999.65004"
592
+ # }
593
+ # }
429
594
  #
595
+ balances = self.safe_list(response, 'balances')
596
+ if balances is not None:
597
+ spotBalances = {'info': response}
598
+ for i in range(0, len(balances)):
599
+ balance = balances[i]
600
+ code = self.safe_currency_code(self.safe_string(balance, 'coin'))
601
+ account = self.account()
602
+ total = self.safe_string(balance, 'total')
603
+ free = self.safe_string(balance, 'hold')
604
+ account['total'] = total
605
+ account['free'] = free
606
+ spotBalances[code] = account
607
+ return self.safe_balance(spotBalances)
430
608
  data = self.safe_dict(response, 'marginSummary', {})
431
609
  result = {
432
610
  'info': response,
@@ -915,6 +1093,7 @@ class hyperliquid(Exchange, ImplicitAPI):
915
1093
  :param str symbol: unified symbol of the market the order was made in
916
1094
  :param dict [params]: extra parameters specific to the exchange API endpoint
917
1095
  :param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1096
+ :param str [params.vaultAddress]: the vault address for order
918
1097
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
919
1098
  """
920
1099
  return await self.cancel_orders([id], symbol, params)
@@ -928,6 +1107,7 @@ class hyperliquid(Exchange, ImplicitAPI):
928
1107
  :param str [symbol]: unified market symbol
929
1108
  :param dict [params]: extra parameters specific to the exchange API endpoint
930
1109
  :param string|str[] [params.clientOrderId]: client order ids,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1110
+ :param str [params.vaultAddress]: the vault address
931
1111
  :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
932
1112
  """
933
1113
  self.check_required_credentials()
@@ -1377,7 +1557,10 @@ class hyperliquid(Exchange, ImplicitAPI):
1377
1557
  coin = self.safe_string(entry, 'coin')
1378
1558
  marketId = None
1379
1559
  if coin is not None:
1380
- marketId = coin + '/USDC:USDC'
1560
+ if coin.find('/') > -1:
1561
+ marketId = coin
1562
+ else:
1563
+ marketId = coin + '/USDC:USDC'
1381
1564
  if self.safe_string(entry, 'id') is None:
1382
1565
  market = self.safe_market(marketId, None)
1383
1566
  else:
@@ -1772,7 +1955,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1772
1955
  #
1773
1956
  return response
1774
1957
 
1775
- async def add_margin(self, symbol: str, amount, params={}):
1958
+ async def add_margin(self, symbol: str, amount, params={}) -> MarginModification:
1776
1959
  """
1777
1960
  add margin
1778
1961
  :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#update-isolated-margin
@@ -1783,7 +1966,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1783
1966
  """
1784
1967
  return await self.modify_margin_helper(symbol, amount, 'add', params)
1785
1968
 
1786
- async def reduce_margin(self, symbol: str, amount, params={}):
1969
+ async def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
1787
1970
  """
1788
1971
  :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#update-isolated-margin
1789
1972
  remove margin from a position
@@ -1794,7 +1977,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1794
1977
  """
1795
1978
  return await self.modify_margin_helper(symbol, amount, 'reduce', params)
1796
1979
 
1797
- async def modify_margin_helper(self, symbol: str, amount, type, params={}):
1980
+ async def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
1798
1981
  await self.load_markets()
1799
1982
  market = self.market(symbol)
1800
1983
  asset = self.parse_to_int(market['baseId'])
@@ -1828,10 +2011,27 @@ class hyperliquid(Exchange, ImplicitAPI):
1828
2011
  # 'status': 'ok'
1829
2012
  # }
1830
2013
  #
1831
- return response
1832
- # return self.extend(self.parse_margin_modification(response, market), {
1833
- # 'code': code,
1834
- # })
2014
+ return self.extend(self.parse_margin_modification(response, market), {
2015
+ 'code': self.safe_string(response, 'status'),
2016
+ })
2017
+
2018
+ def parse_margin_modification(self, data, market: Market = None) -> MarginModification:
2019
+ #
2020
+ # {
2021
+ # 'type': 'default'
2022
+ # }
2023
+ #
2024
+ return {
2025
+ 'info': data,
2026
+ 'symbol': self.safe_symbol(None, market),
2027
+ 'type': None,
2028
+ 'amount': None,
2029
+ 'total': None,
2030
+ 'code': self.safe_string(market, 'settle'),
2031
+ 'status': None,
2032
+ 'timestamp': None,
2033
+ 'datetime': None,
2034
+ }
1835
2035
 
1836
2036
  async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
1837
2037
  """
@@ -1839,23 +2039,49 @@ class hyperliquid(Exchange, ImplicitAPI):
1839
2039
  :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#l1-usdc-transfer
1840
2040
  :param str code: unified currency code
1841
2041
  :param float amount: amount to transfer
1842
- :param str fromAccount: account to transfer from
1843
- :param str toAccount: account to transfer to
2042
+ :param str fromAccount: account to transfer from *spot, swap*
2043
+ :param str toAccount: account to transfer to *swap, spot or address*
1844
2044
  :param dict [params]: extra parameters specific to the exchange API endpoint
2045
+ :param str [params.vaultAddress]: the vault address for order
1845
2046
  :returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
1846
2047
  """
1847
2048
  self.check_required_credentials()
1848
2049
  await self.load_markets()
2050
+ isSandboxMode = self.safe_bool(self.options, 'sandboxMode')
2051
+ nonce = self.milliseconds()
2052
+ if self.in_array(fromAccount, ['spot', 'swap', 'perp']):
2053
+ # handle swap <> spot account transfer
2054
+ if not self.in_array(toAccount, ['spot', 'swap', 'perp']):
2055
+ raise NotSupported(self.id + 'transfer() only support spot <> swap transfer')
2056
+ vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
2057
+ params = self.omit(params, 'vaultAddress')
2058
+ toPerp = (toAccount == 'perp') or (toAccount == 'swap')
2059
+ action = {
2060
+ 'type': 'spotUser',
2061
+ 'classTransfer': {
2062
+ 'usdc': amount,
2063
+ 'toPerp': toPerp,
2064
+ },
2065
+ }
2066
+ signature = self.sign_l1_action(action, nonce, vaultAddress)
2067
+ innerRequest = {
2068
+ 'action': self.extend(action, params),
2069
+ 'nonce': nonce,
2070
+ 'signature': signature,
2071
+ }
2072
+ if vaultAddress is not None:
2073
+ innerRequest['vaultAddress'] = vaultAddress
2074
+ transferResponse = await self.privatePostExchange(innerRequest)
2075
+ return transferResponse
2076
+ # handle sub-account/different account transfer
1849
2077
  self.check_address(toAccount)
1850
2078
  if code is not None:
1851
2079
  code = code.upper()
1852
2080
  if code != 'USDC':
1853
2081
  raise NotSupported(self.id + 'withdraw() only support USDC')
1854
- isSandboxMode = self.safe_bool(self.options, 'sandboxMode')
1855
- nonce = self.milliseconds()
1856
2082
  payload = {
1857
2083
  'destination': toAccount,
1858
- 'amount': str(amount),
2084
+ 'amount': self.number_to_string(amount),
1859
2085
  'time': nonce,
1860
2086
  }
1861
2087
  sig = self.build_transfer_sig(payload)