ccxt 4.4.92__py2.py3-none-any.whl → 4.4.94__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 (58) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/lbank.py +1 -1
  3. ccxt/ascendex.py +9 -8
  4. ccxt/async_support/__init__.py +1 -1
  5. ccxt/async_support/ascendex.py +9 -8
  6. ccxt/async_support/base/exchange.py +4 -1
  7. ccxt/async_support/base/ws/client.py +3 -0
  8. ccxt/async_support/binance.py +42 -1
  9. ccxt/async_support/bitmex.py +3 -3
  10. ccxt/async_support/bybit.py +83 -10
  11. ccxt/async_support/coinbase.py +4 -1
  12. ccxt/async_support/coinbaseexchange.py +53 -0
  13. ccxt/async_support/coincheck.py +45 -4
  14. ccxt/async_support/coinex.py +16 -12
  15. ccxt/async_support/coinmetro.py +15 -3
  16. ccxt/async_support/cryptomus.py +30 -52
  17. ccxt/async_support/deribit.py +6 -6
  18. ccxt/async_support/exmo.py +64 -52
  19. ccxt/async_support/htx.py +5 -1
  20. ccxt/async_support/hyperliquid.py +126 -33
  21. ccxt/async_support/kucoin.py +12 -14
  22. ccxt/async_support/latoken.py +19 -71
  23. ccxt/async_support/lbank.py +2 -2
  24. ccxt/async_support/okx.py +159 -3
  25. ccxt/async_support/paradex.py +54 -0
  26. ccxt/async_support/phemex.py +3 -3
  27. ccxt/async_support/wavesexchange.py +12 -2
  28. ccxt/base/exchange.py +96 -31
  29. ccxt/binance.py +42 -1
  30. ccxt/bitmex.py +3 -3
  31. ccxt/bybit.py +83 -10
  32. ccxt/coinbase.py +4 -1
  33. ccxt/coinbaseexchange.py +53 -0
  34. ccxt/coincheck.py +45 -4
  35. ccxt/coinex.py +16 -12
  36. ccxt/coinmetro.py +14 -3
  37. ccxt/cryptomus.py +30 -52
  38. ccxt/deribit.py +6 -6
  39. ccxt/exmo.py +64 -52
  40. ccxt/htx.py +5 -1
  41. ccxt/hyperliquid.py +126 -33
  42. ccxt/kucoin.py +12 -14
  43. ccxt/latoken.py +19 -71
  44. ccxt/lbank.py +2 -2
  45. ccxt/okx.py +159 -3
  46. ccxt/paradex.py +54 -0
  47. ccxt/phemex.py +3 -3
  48. ccxt/pro/__init__.py +1 -1
  49. ccxt/pro/bitstamp.py +48 -16
  50. ccxt/pro/bybit.py +2 -1
  51. ccxt/test/tests_async.py +17 -15
  52. ccxt/test/tests_sync.py +17 -15
  53. ccxt/wavesexchange.py +12 -2
  54. {ccxt-4.4.92.dist-info → ccxt-4.4.94.dist-info}/METADATA +4 -4
  55. {ccxt-4.4.92.dist-info → ccxt-4.4.94.dist-info}/RECORD +58 -58
  56. {ccxt-4.4.92.dist-info → ccxt-4.4.94.dist-info}/LICENSE.txt +0 -0
  57. {ccxt-4.4.92.dist-info → ccxt-4.4.94.dist-info}/WHEEL +0 -0
  58. {ccxt-4.4.92.dist-info → ccxt-4.4.94.dist-info}/top_level.txt +0 -0
ccxt/exmo.py CHANGED
@@ -709,73 +709,85 @@ class exmo(Exchange, ImplicitAPI):
709
709
  for i in range(0, len(currencyList)):
710
710
  currency = currencyList[i]
711
711
  currencyId = self.safe_string(currency, 'name')
712
- name = self.safe_string(currency, 'description')
713
- providers = self.safe_value(cryptoList, currencyId)
714
- active = False
712
+ code = self.safe_currency_code(currencyId)
715
713
  type = 'crypto'
716
- limits: dict = {
717
- 'deposit': {
718
- 'min': None,
719
- 'max': None,
720
- },
721
- 'withdraw': {
722
- 'min': None,
723
- 'max': None,
724
- },
725
- }
726
- fee = None
727
- depositEnabled = None
728
- withdrawEnabled = None
714
+ networks = {}
715
+ providers = self.safe_list(cryptoList, currencyId)
729
716
  if providers is None:
730
- active = True
731
717
  type = 'fiat'
732
718
  else:
733
719
  for j in range(0, len(providers)):
734
720
  provider = providers[j]
721
+ name = self.safe_string(provider, 'name')
722
+ # get network-id by removing extra things
723
+ networkId = name.replace(currencyId + ' ', '')
724
+ networkId = networkId.replace('(', '')
725
+ replaceChar = ')' # transpiler trick
726
+ networkId = networkId.replace(replaceChar, '')
727
+ networkCode = self.network_id_to_code(networkId)
728
+ if not (networkCode in networks):
729
+ networks[networkCode] = {
730
+ 'id': networkId,
731
+ 'network': networkCode,
732
+ 'active': None,
733
+ 'deposit': None,
734
+ 'withdraw': None,
735
+ 'fee': None,
736
+ 'limits': {
737
+ 'withdraw': {
738
+ 'min': None,
739
+ 'max': None,
740
+ },
741
+ 'deposit': {
742
+ 'min': None,
743
+ 'max': None,
744
+ },
745
+ },
746
+ 'info': [], # set, because of multiple network sub-entries
747
+ }
735
748
  typeInner = self.safe_string(provider, 'type')
736
749
  minValue = self.safe_string(provider, 'min')
737
750
  maxValue = self.safe_string(provider, 'max')
738
- if Precise.string_eq(maxValue, '0.0'):
739
- maxValue = None
740
- activeProvider = self.safe_value(provider, 'enabled')
751
+ activeProvider = self.safe_bool(provider, 'enabled')
752
+ networkEntry = networks[networkCode]
741
753
  if typeInner == 'deposit':
742
- if activeProvider and not depositEnabled:
743
- depositEnabled = True
744
- elif not activeProvider:
745
- depositEnabled = False
754
+ networkEntry['deposit'] = activeProvider
755
+ networkEntry['limits']['deposit']['min'] = minValue
756
+ networkEntry['limits']['deposit']['max'] = maxValue
746
757
  elif typeInner == 'withdraw':
747
- if activeProvider and not withdrawEnabled:
748
- withdrawEnabled = True
749
- elif not activeProvider:
750
- withdrawEnabled = False
751
- if activeProvider:
752
- active = True
753
- limitMin = self.number_to_string(limits[typeInner]['min'])
754
- if (limits[typeInner]['min'] is None) or (Precise.string_lt(minValue, limitMin)):
755
- limits[typeInner]['min'] = minValue
756
- limits[typeInner]['max'] = maxValue
757
- if typeInner == 'withdraw':
758
- commissionDesc = self.safe_string(provider, 'commission_desc')
759
- fee = self.parse_fixed_float_value(commissionDesc)
760
- code = self.safe_currency_code(currencyId)
761
- info = {
762
- 'currency': currency,
763
- 'providers': providers,
764
- }
765
- result[code] = {
758
+ networkEntry['withdraw'] = activeProvider
759
+ networkEntry['limits']['withdraw']['min'] = minValue
760
+ networkEntry['limits']['withdraw']['max'] = maxValue
761
+ info = self.safe_list(networkEntry, 'info')
762
+ info.append(provider)
763
+ networkEntry['info'] = info
764
+ networks[networkCode] = networkEntry
765
+ result[code] = self.safe_currency_structure({
766
766
  'id': currencyId,
767
767
  'code': code,
768
- 'name': name,
768
+ 'name': self.safe_string(currency, 'description'),
769
769
  'type': type,
770
- 'active': active,
771
- 'deposit': depositEnabled,
772
- 'withdraw': withdrawEnabled,
773
- 'fee': fee,
770
+ 'active': None,
771
+ 'deposit': None,
772
+ 'withdraw': None,
773
+ 'fee': None,
774
774
  'precision': self.parse_number('1e-8'),
775
- 'limits': limits,
776
- 'info': info,
777
- 'networks': {},
778
- }
775
+ 'limits': {
776
+ 'withdraw': {
777
+ 'min': None,
778
+ 'max': None,
779
+ },
780
+ 'deposit': {
781
+ 'min': None,
782
+ 'max': None,
783
+ },
784
+ },
785
+ 'info': {
786
+ 'currency': currency,
787
+ 'providers': providers,
788
+ },
789
+ 'networks': networks,
790
+ })
779
791
  return result
780
792
 
781
793
  def fetch_markets(self, params={}) -> List[Market]:
ccxt/htx.py CHANGED
@@ -6576,12 +6576,16 @@ class htx(Exchange, ImplicitAPI):
6576
6576
  paginate = False
6577
6577
  paginate, params = self.handle_option_and_params(params, 'fetchFundingRateHistory', 'paginate')
6578
6578
  if paginate:
6579
- return self.fetch_paginated_call_cursor('fetchFundingRateHistory', symbol, since, limit, params, 'page_index', 'current_page', 1, 50)
6579
+ return self.fetch_paginated_call_cursor('fetchFundingRateHistory', symbol, since, limit, params, 'current_page', 'page_index', 1, 50)
6580
6580
  self.load_markets()
6581
6581
  market = self.market(symbol)
6582
6582
  request: dict = {
6583
6583
  'contract_code': market['id'],
6584
6584
  }
6585
+ if limit is not None:
6586
+ request['page_size'] = limit
6587
+ else:
6588
+ request['page_size'] = 50 # max
6585
6589
  response = None
6586
6590
  if market['inverse']:
6587
6591
  response = self.contractPublicGetSwapApiV1SwapHistoricalFundingRate(self.extend(request, params))
ccxt/hyperliquid.py CHANGED
@@ -353,6 +353,8 @@ class hyperliquid(Exchange, ImplicitAPI):
353
353
  :param dict [params]: extra parameters specific to the exchange API endpoint
354
354
  :returns dict: an associative dictionary of currencies
355
355
  """
356
+ if self.check_required_credentials(False):
357
+ self.handle_builder_fee_approval()
356
358
  request: dict = {
357
359
  'type': 'meta',
358
360
  }
@@ -626,6 +628,7 @@ class hyperliquid(Exchange, ImplicitAPI):
626
628
  'quote': quote,
627
629
  'settle': None,
628
630
  'baseId': baseId,
631
+ 'baseName': baseName,
629
632
  'quoteId': quoteId,
630
633
  'settleId': None,
631
634
  'type': 'spot',
@@ -695,7 +698,8 @@ class hyperliquid(Exchange, ImplicitAPI):
695
698
  # }
696
699
  #
697
700
  quoteId = 'USDC'
698
- base = self.safe_string(market, 'name')
701
+ baseName = self.safe_string(market, 'name')
702
+ base = self.safe_currency_code(baseName)
699
703
  quote = self.safe_currency_code(quoteId)
700
704
  baseId = self.safe_string(market, 'baseId')
701
705
  settleId = 'USDC'
@@ -727,6 +731,7 @@ class hyperliquid(Exchange, ImplicitAPI):
727
731
  'quote': quote,
728
732
  'settle': settle,
729
733
  'baseId': baseId,
734
+ 'baseName': baseName,
730
735
  'quoteId': quoteId,
731
736
  'settleId': settleId,
732
737
  'type': 'swap',
@@ -783,6 +788,7 @@ class hyperliquid(Exchange, ImplicitAPI):
783
788
  :param str [params.user]: user address, will default to self.walletAddress if not provided
784
789
  :param str [params.type]: wallet type, ['spot', 'swap'], defaults to swap
785
790
  :param str [params.marginMode]: 'cross' or 'isolated', for margin trading, uses self.options.defaultMarginMode if not passed, defaults to None/None/None
791
+ :param str [params.subAccountAddress]: sub account user address
786
792
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
787
793
  """
788
794
  userAddress = None
@@ -792,9 +798,8 @@ class hyperliquid(Exchange, ImplicitAPI):
792
798
  marginMode = None
793
799
  marginMode, params = self.handle_margin_mode_and_params('fetchBalance', params)
794
800
  isSpot = (type == 'spot')
795
- reqType = 'spotClearinghouseState' if (isSpot) else 'clearinghouseState'
796
801
  request: dict = {
797
- 'type': reqType,
802
+ 'type': 'spotClearinghouseState' if (isSpot) else 'clearinghouseState',
798
803
  'user': userAddress,
799
804
  }
800
805
  response = self.publicPostInfo(self.extend(request, params))
@@ -878,7 +883,7 @@ class hyperliquid(Exchange, ImplicitAPI):
878
883
  market = self.market(symbol)
879
884
  request: dict = {
880
885
  'type': 'l2Book',
881
- 'coin': market['base'] if market['swap'] else market['id'],
886
+ 'coin': market['baseName'] if market['swap'] else market['id'],
882
887
  }
883
888
  response = self.publicPostInfo(self.extend(request, params))
884
889
  #
@@ -1111,7 +1116,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1111
1116
  request: dict = {
1112
1117
  'type': 'candleSnapshot',
1113
1118
  'req': {
1114
- 'coin': market['base'] if market['swap'] else market['id'],
1119
+ 'coin': market['baseName'] if market['swap'] else market['id'],
1115
1120
  'interval': self.safe_string(self.timeframes, timeframe, timeframe),
1116
1121
  'startTime': since,
1117
1122
  'endTime': until,
@@ -1174,6 +1179,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1174
1179
  :param int [params.until]: timestamp in ms of the latest trade
1175
1180
  :param str [params.address]: wallet address that made trades
1176
1181
  :param str [params.user]: wallet address that made trades
1182
+ :param str [params.subAccountAddress]: sub account user address
1177
1183
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1178
1184
  """
1179
1185
  userAddress = None
@@ -1352,6 +1358,67 @@ class hyperliquid(Exchange, ImplicitAPI):
1352
1358
  }
1353
1359
  return self.sign_user_signed_action(messageTypes, message)
1354
1360
 
1361
+ def build_approve_builder_fee_sig(self, message):
1362
+ messageTypes: dict = {
1363
+ 'HyperliquidTransaction:ApproveBuilderFee': [
1364
+ {'name': 'hyperliquidChain', 'type': 'string'},
1365
+ {'name': 'maxFeeRate', 'type': 'string'},
1366
+ {'name': 'builder', 'type': 'address'},
1367
+ {'name': 'nonce', 'type': 'uint64'},
1368
+ ],
1369
+ }
1370
+ return self.sign_user_signed_action(messageTypes, message)
1371
+
1372
+ def approve_builder_fee(self, builder: str, maxFeeRate: str):
1373
+ nonce = self.milliseconds()
1374
+ isSandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
1375
+ payload: dict = {
1376
+ 'hyperliquidChain': 'Testnet' if isSandboxMode else 'Mainnet',
1377
+ 'maxFeeRate': maxFeeRate,
1378
+ 'builder': builder,
1379
+ 'nonce': nonce,
1380
+ }
1381
+ sig = self.build_approve_builder_fee_sig(payload)
1382
+ action = {
1383
+ 'hyperliquidChain': payload['hyperliquidChain'],
1384
+ 'signatureChainId': '0x66eee',
1385
+ 'maxFeeRate': payload['maxFeeRate'],
1386
+ 'builder': payload['builder'],
1387
+ 'nonce': nonce,
1388
+ 'type': 'approveBuilderFee',
1389
+ }
1390
+ request: dict = {
1391
+ 'action': action,
1392
+ 'nonce': nonce,
1393
+ 'signature': sig,
1394
+ 'vaultAddress': None,
1395
+ }
1396
+ #
1397
+ # {
1398
+ # "status": "ok",
1399
+ # "response": {
1400
+ # "type": "default"
1401
+ # }
1402
+ # }
1403
+ #
1404
+ return self.privatePostExchange(request)
1405
+
1406
+ def handle_builder_fee_approval(self):
1407
+ buildFee = self.safe_bool(self.options, 'builderFee', True)
1408
+ if not buildFee:
1409
+ return False # skip if builder fee is not enabled
1410
+ approvedBuilderFee = self.safe_bool(self.options, 'approvedBuilderFee', False)
1411
+ if approvedBuilderFee:
1412
+ return True # skip if builder fee is already approved
1413
+ try:
1414
+ builder = self.safe_string(self.options, 'builder', '0x6530512A6c89C7cfCEbC3BA7fcD9aDa5f30827a6')
1415
+ maxFeeRate = self.safe_string(self.options, 'feeRate', '0.01%')
1416
+ self.approve_builder_fee(builder, maxFeeRate)
1417
+ self.options['approvedBuilderFee'] = True
1418
+ except Exception as e:
1419
+ self.options['builderFee'] = False # disable builder fee if an error occurs
1420
+ return True
1421
+
1355
1422
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1356
1423
  """
1357
1424
  create a trade order
@@ -1371,6 +1438,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1371
1438
  :param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1372
1439
  :param str [params.slippage]: the slippage for market order
1373
1440
  :param str [params.vaultAddress]: the vault address for order
1441
+ :param str [params.subAccountAddress]: sub account user address
1374
1442
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1375
1443
  """
1376
1444
  self.load_markets()
@@ -1389,6 +1457,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1389
1457
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1390
1458
  """
1391
1459
  self.load_markets()
1460
+ self.handle_builder_fee_approval()
1392
1461
  request = self.create_orders_request(orders, params)
1393
1462
  response = self.privatePostExchange(request)
1394
1463
  #
@@ -1552,10 +1621,10 @@ class hyperliquid(Exchange, ImplicitAPI):
1552
1621
  'type': 'order',
1553
1622
  'orders': orderReq,
1554
1623
  'grouping': grouping,
1555
- # 'brokerCode': 1, # cant
1556
1624
  }
1557
- if vaultAddress is None:
1558
- orderAction['brokerCode'] = 1
1625
+ if self.safe_bool(self.options, 'approvedBuilderFee', False):
1626
+ wallet = self.safe_string_lower(self.options, 'builder', '0x6530512A6c89C7cfCEbC3BA7fcD9aDa5f30827a6')
1627
+ orderAction['builder'] = {'b': wallet, 'f': self.safe_integer(self.options, 'feeInt', 10)}
1559
1628
  signature = self.sign_l1_action(orderAction, nonce, vaultAddress)
1560
1629
  request: dict = {
1561
1630
  'action': orderAction,
@@ -1580,6 +1649,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1580
1649
  :param dict [params]: extra parameters specific to the exchange API endpoint
1581
1650
  :param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1582
1651
  :param str [params.vaultAddress]: the vault address for order
1652
+ :param str [params.subAccountAddress]: sub account user address
1583
1653
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1584
1654
  """
1585
1655
  orders = self.cancel_orders([id], symbol, params)
@@ -1597,6 +1667,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1597
1667
  :param dict [params]: extra parameters specific to the exchange API endpoint
1598
1668
  :param string|str[] [params.clientOrderId]: client order ids,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1599
1669
  :param str [params.vaultAddress]: the vault address
1670
+ :param str [params.subAccountAddress]: sub account user address
1600
1671
  :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1601
1672
  """
1602
1673
  self.check_required_credentials()
@@ -1635,7 +1706,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1635
1706
  })
1636
1707
  cancelAction['cancels'] = cancelReq
1637
1708
  vaultAddress = None
1638
- vaultAddress, params = self.handle_option_and_params(params, 'cancelOrders', 'vaultAddress')
1709
+ vaultAddress, params = self.handle_option_and_params_2(params, 'cancelOrders', 'vaultAddress', 'subAccountAddress')
1639
1710
  vaultAddress = self.format_vault_address(vaultAddress)
1640
1711
  signature = self.sign_l1_action(cancelAction, nonce, vaultAddress)
1641
1712
  request['action'] = cancelAction
@@ -1679,6 +1750,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1679
1750
  :param CancellationRequest[] orders: each order should contain the parameters required by cancelOrder namely id and symbol, example [{"id": "a", "symbol": "BTC/USDT"}, {"id": "b", "symbol": "ETH/USDT"}]
1680
1751
  :param dict [params]: extra parameters specific to the exchange API endpoint
1681
1752
  :param str [params.vaultAddress]: the vault address
1753
+ :param str [params.subAccountAddress]: sub account user address
1682
1754
  :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1683
1755
  """
1684
1756
  self.check_required_credentials()
@@ -1715,7 +1787,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1715
1787
  cancelAction['type'] = 'cancelByCloid' if cancelByCloid else 'cancel'
1716
1788
  cancelAction['cancels'] = cancelReq
1717
1789
  vaultAddress = None
1718
- vaultAddress, params = self.handle_option_and_params(params, 'cancelOrdersForSymbols', 'vaultAddress')
1790
+ vaultAddress, params = self.handle_option_and_params_2(params, 'cancelOrdersForSymbols', 'vaultAddress', 'subAccountAddress')
1719
1791
  vaultAddress = self.format_vault_address(vaultAddress)
1720
1792
  signature = self.sign_l1_action(cancelAction, nonce, vaultAddress)
1721
1793
  request['action'] = cancelAction
@@ -1745,6 +1817,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1745
1817
  :param number timeout: time in milliseconds, 0 represents cancel the timer
1746
1818
  :param dict [params]: extra parameters specific to the exchange API endpoint
1747
1819
  :param str [params.vaultAddress]: the vault address
1820
+ :param str [params.subAccountAddress]: sub account user address
1748
1821
  :returns dict: the api result
1749
1822
  """
1750
1823
  self.check_required_credentials()
@@ -1760,7 +1833,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1760
1833
  'time': nonce + timeout,
1761
1834
  }
1762
1835
  vaultAddress = None
1763
- vaultAddress, params = self.handle_option_and_params(params, 'cancelAllOrdersAfter', 'vaultAddress')
1836
+ vaultAddress, params = self.handle_option_and_params_2(params, 'cancelAllOrdersAfter', 'vaultAddress', 'subAccountAddress')
1764
1837
  vaultAddress = self.format_vault_address(vaultAddress)
1765
1838
  signature = self.sign_l1_action(cancelAction, nonce, vaultAddress)
1766
1839
  request['action'] = cancelAction
@@ -1903,6 +1976,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1903
1976
  :param float [params.triggerPrice]: The price at which a trigger order is triggered at
1904
1977
  :param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1905
1978
  :param str [params.vaultAddress]: the vault address for order
1979
+ :param str [params.subAccountAddress]: sub account user address
1906
1980
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1907
1981
  """
1908
1982
  self.load_markets()
@@ -2022,7 +2096,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2022
2096
  market = self.market(symbol)
2023
2097
  request: dict = {
2024
2098
  'type': 'fundingHistory',
2025
- 'coin': market['base'],
2099
+ 'coin': market['baseName'],
2026
2100
  }
2027
2101
  if since is not None:
2028
2102
  request['startTime'] = since
@@ -2070,6 +2144,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2070
2144
  :param dict [params]: extra parameters specific to the exchange API endpoint
2071
2145
  :param str [params.user]: user address, will default to self.walletAddress if not provided
2072
2146
  :param str [params.method]: 'openOrders' or 'frontendOpenOrders' default is 'frontendOpenOrders'
2147
+ :param str [params.subAccountAddress]: sub account user address
2073
2148
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2074
2149
  """
2075
2150
  userAddress = None
@@ -2158,6 +2233,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2158
2233
  :param int [limit]: the maximum number of open orders structures to retrieve
2159
2234
  :param dict [params]: extra parameters specific to the exchange API endpoint
2160
2235
  :param str [params.user]: user address, will default to self.walletAddress if not provided
2236
+ :param str [params.subAccountAddress]: sub account user address
2161
2237
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2162
2238
  """
2163
2239
  userAddress = None
@@ -2194,6 +2270,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2194
2270
  :param str symbol: unified symbol of the market the order was made in
2195
2271
  :param dict [params]: extra parameters specific to the exchange API endpoint
2196
2272
  :param str [params.user]: user address, will default to self.walletAddress if not provided
2273
+ :param str [params.subAccountAddress]: sub account user address
2197
2274
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2198
2275
  """
2199
2276
  userAddress = None
@@ -2419,6 +2496,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2419
2496
  :param int [limit]: the maximum number of trades structures to retrieve
2420
2497
  :param dict [params]: extra parameters specific to the exchange API endpoint
2421
2498
  :param int [params.until]: timestamp in ms of the latest trade
2499
+ :param str [params.subAccountAddress]: sub account user address
2422
2500
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
2423
2501
  """
2424
2502
  userAddress = None
@@ -2539,6 +2617,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2539
2617
  :param str[] [symbols]: list of unified market symbols
2540
2618
  :param dict [params]: extra parameters specific to the exchange API endpoint
2541
2619
  :param str [params.user]: user address, will default to self.walletAddress if not provided
2620
+ :param str [params.subAccountAddress]: sub account user address
2542
2621
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
2543
2622
  """
2544
2623
  self.load_markets()
@@ -2679,6 +2758,8 @@ class hyperliquid(Exchange, ImplicitAPI):
2679
2758
  :param str symbol: unified market symbol of the market the position is held in, default is None
2680
2759
  :param dict [params]: extra parameters specific to the exchange API endpoint
2681
2760
  :param str [params.leverage]: the rate of leverage, is required if setting trade mode(symbol)
2761
+ :param str [params.vaultAddress]: the vault address
2762
+ :param str [params.subAccountAddress]: sub account user address
2682
2763
  :returns dict: response from the exchange
2683
2764
  """
2684
2765
  if symbol is None:
@@ -2699,7 +2780,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2699
2780
  'leverage': leverage,
2700
2781
  }
2701
2782
  vaultAddress = None
2702
- vaultAddress, params = self.handle_option_and_params(params, 'setMarginMode', 'vaultAddress')
2783
+ vaultAddress, params = self.handle_option_and_params_2(params, 'setMarginMode', 'vaultAddress', 'subAccountAddress')
2703
2784
  if vaultAddress is not None:
2704
2785
  if vaultAddress.startswith('0x'):
2705
2786
  vaultAddress = vaultAddress.replace('0x', '')
@@ -2748,7 +2829,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2748
2829
  'leverage': leverage,
2749
2830
  }
2750
2831
  vaultAddress = None
2751
- vaultAddress, params = self.handle_option_and_params(params, 'setLeverage', 'vaultAddress')
2832
+ vaultAddress, params = self.handle_option_and_params_2(params, 'setLeverage', 'vaultAddress', 'subAccountAddress')
2752
2833
  vaultAddress = self.format_vault_address(vaultAddress)
2753
2834
  signature = self.sign_l1_action(updateAction, nonce, vaultAddress)
2754
2835
  request: dict = {
@@ -2780,6 +2861,8 @@ class hyperliquid(Exchange, ImplicitAPI):
2780
2861
  :param str symbol: unified market symbol
2781
2862
  :param float amount: amount of margin to add
2782
2863
  :param dict [params]: extra parameters specific to the exchange API endpoint
2864
+ :param str [params.vaultAddress]: the vault address
2865
+ :param str [params.subAccountAddress]: sub account user address
2783
2866
  :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=add-margin-structure>`
2784
2867
  """
2785
2868
  return self.modify_margin_helper(symbol, amount, 'add', params)
@@ -2793,6 +2876,8 @@ class hyperliquid(Exchange, ImplicitAPI):
2793
2876
  :param str symbol: unified market symbol
2794
2877
  :param float amount: the amount of margin to remove
2795
2878
  :param dict [params]: extra parameters specific to the exchange API endpoint
2879
+ :param str [params.vaultAddress]: the vault address
2880
+ :param str [params.subAccountAddress]: sub account user address
2796
2881
  :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=reduce-margin-structure>`
2797
2882
  """
2798
2883
  return self.modify_margin_helper(symbol, amount, 'reduce', params)
@@ -2812,7 +2897,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2812
2897
  'ntli': sz,
2813
2898
  }
2814
2899
  vaultAddress = None
2815
- vaultAddress, params = self.handle_option_and_params(params, 'modifyMargin', 'vaultAddress')
2900
+ vaultAddress, params = self.handle_option_and_params_2(params, 'modifyMargin', 'vaultAddress', 'subAccountAddress')
2816
2901
  vaultAddress = self.format_vault_address(vaultAddress)
2817
2902
  signature = self.sign_l1_action(updateAction, nonce, vaultAddress)
2818
2903
  request: dict = {
@@ -2907,28 +2992,31 @@ class hyperliquid(Exchange, ImplicitAPI):
2907
2992
  transferRequest['vaultAddress'] = vaultAddress
2908
2993
  transferResponse = self.privatePostExchange(transferRequest)
2909
2994
  return transferResponse
2910
- # handle sub-account/different account transfer
2911
- self.check_address(toAccount)
2995
+ # transfer between main account and subaccount
2912
2996
  if code is not None:
2913
2997
  code = code.upper()
2914
2998
  if code != 'USDC':
2915
2999
  raise NotSupported(self.id + ' transfer() only support USDC')
2916
- payload: dict = {
2917
- 'hyperliquidChain': 'Testnet' if isSandboxMode else 'Mainnet',
2918
- 'destination': toAccount,
2919
- 'amount': self.number_to_string(amount),
2920
- 'time': nonce,
3000
+ isDeposit = False
3001
+ subAccountAddress = None
3002
+ if fromAccount == 'main':
3003
+ subAccountAddress = toAccount
3004
+ isDeposit = True
3005
+ elif toAccount == 'main':
3006
+ subAccountAddress = fromAccount
3007
+ else:
3008
+ raise NotSupported(self.id + ' transfer() only support main <> subaccount transfer')
3009
+ self.check_address(subAccountAddress)
3010
+ usd = self.parse_to_int(Precise.string_mul(self.number_to_string(amount), '1000000'))
3011
+ action = {
3012
+ 'type': 'subAccountTransfer',
3013
+ 'subAccountUser': subAccountAddress,
3014
+ 'isDeposit': isDeposit,
3015
+ 'usd': usd,
2921
3016
  }
2922
- sig = self.build_usd_send_sig(payload)
3017
+ sig = self.sign_l1_action(action, nonce)
2923
3018
  request: dict = {
2924
- 'action': {
2925
- 'hyperliquidChain': payload['hyperliquidChain'],
2926
- 'signatureChainId': '0x66eee', # check self out
2927
- 'destination': toAccount,
2928
- 'amount': str(amount),
2929
- 'time': nonce,
2930
- 'type': 'usdSend',
2931
- },
3019
+ 'action': action,
2932
3020
  'nonce': nonce,
2933
3021
  'signature': sig,
2934
3022
  }
@@ -3073,6 +3161,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3073
3161
  :param str symbol: unified market symbol
3074
3162
  :param dict [params]: extra parameters specific to the exchange API endpoint
3075
3163
  :param str [params.user]: user address, will default to self.walletAddress if not provided
3164
+ :param str [params.subAccountAddress]: sub account user address
3076
3165
  :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
3077
3166
  """
3078
3167
  self.load_markets()
@@ -3179,6 +3268,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3179
3268
  :param int [limit]: max number of ledger entries to return
3180
3269
  :param dict [params]: extra parameters specific to the exchange API endpoint
3181
3270
  :param int [params.until]: timestamp in ms of the latest ledger entry
3271
+ :param str [params.subAccountAddress]: sub account user address
3182
3272
  :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
3183
3273
  """
3184
3274
  self.load_markets()
@@ -3266,6 +3356,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3266
3356
  :param int [limit]: the maximum number of deposits structures to retrieve
3267
3357
  :param dict [params]: extra parameters specific to the exchange API endpoint
3268
3358
  :param int [params.until]: the latest time in ms to fetch withdrawals for
3359
+ :param str [params.subAccountAddress]: sub account user address
3269
3360
  :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
3270
3361
  """
3271
3362
  self.load_markets()
@@ -3307,6 +3398,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3307
3398
  :param int [limit]: the maximum number of withdrawals structures to retrieve
3308
3399
  :param dict [params]: extra parameters specific to the exchange API endpoint
3309
3400
  :param int [params.until]: the latest time in ms to fetch withdrawals for
3401
+ :param str [params.subAccountAddress]: sub account user address
3310
3402
  :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
3311
3403
  """
3312
3404
  self.load_markets()
@@ -3404,6 +3496,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3404
3496
  :param int [since]: the earliest time in ms to fetch funding history for
3405
3497
  :param int [limit]: the maximum number of funding history structures to retrieve
3406
3498
  :param dict [params]: extra parameters specific to the exchange API endpoint
3499
+ :param str [params.subAccountAddress]: sub account user address
3407
3500
  :returns dict: a `funding history structure <https://docs.ccxt.com/#/?id=funding-history-structure>`
3408
3501
  """
3409
3502
  self.load_markets()
@@ -3494,7 +3587,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3494
3587
 
3495
3588
  def handle_public_address(self, methodName: str, params: dict):
3496
3589
  userAux = None
3497
- userAux, params = self.handle_option_and_params(params, methodName, 'user')
3590
+ userAux, params = self.handle_option_and_params_2(params, methodName, 'user', 'subAccountAddress')
3498
3591
  user = userAux
3499
3592
  user, params = self.handle_option_and_params(params, methodName, 'address', userAux)
3500
3593
  if (user is not None) and (user != ''):
@@ -3561,7 +3654,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3561
3654
  def parse_create_edit_order_args(self, id: Str, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
3562
3655
  market = self.market(symbol)
3563
3656
  vaultAddress = None
3564
- vaultAddress, params = self.handle_option_and_params(params, 'createOrder', 'vaultAddress')
3657
+ vaultAddress, params = self.handle_option_and_params_2(params, 'createOrder', 'vaultAddress', 'subAccountAddress')
3565
3658
  vaultAddress = self.format_vault_address(vaultAddress)
3566
3659
  symbol = market['symbol']
3567
3660
  order = {