ccxt 4.4.93__py2.py3-none-any.whl → 4.4.95__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 (52) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/bingx.py +3 -0
  3. ccxt/abstract/hyperliquid.py +1 -1
  4. ccxt/abstract/woo.py +59 -4
  5. ccxt/async_support/__init__.py +1 -1
  6. ccxt/async_support/base/exchange.py +1 -1
  7. ccxt/async_support/base/ws/future.py +2 -0
  8. ccxt/async_support/bingx.py +129 -92
  9. ccxt/async_support/bitget.py +1 -1
  10. ccxt/async_support/bitstamp.py +2 -0
  11. ccxt/async_support/blofin.py +6 -1
  12. ccxt/async_support/bybit.py +3 -3
  13. ccxt/async_support/coinbase.py +40 -1
  14. ccxt/async_support/coinmate.py +34 -0
  15. ccxt/async_support/coinmetro.py +15 -3
  16. ccxt/async_support/coinone.py +34 -0
  17. ccxt/async_support/coinsph.py +29 -0
  18. ccxt/async_support/gate.py +1 -1
  19. ccxt/async_support/htx.py +5 -1
  20. ccxt/async_support/hyperliquid.py +126 -33
  21. ccxt/async_support/okx.py +10 -3
  22. ccxt/async_support/wavesexchange.py +12 -2
  23. ccxt/async_support/woo.py +1251 -875
  24. ccxt/base/errors.py +0 -6
  25. ccxt/base/exchange.py +44 -22
  26. ccxt/bingx.py +129 -92
  27. ccxt/bitget.py +1 -1
  28. ccxt/bitstamp.py +2 -0
  29. ccxt/blofin.py +6 -1
  30. ccxt/bybit.py +3 -3
  31. ccxt/coinbase.py +40 -1
  32. ccxt/coinmate.py +34 -0
  33. ccxt/coinmetro.py +14 -3
  34. ccxt/coinone.py +34 -0
  35. ccxt/coinsph.py +29 -0
  36. ccxt/gate.py +1 -1
  37. ccxt/htx.py +5 -1
  38. ccxt/hyperliquid.py +126 -33
  39. ccxt/okx.py +10 -3
  40. ccxt/pro/__init__.py +1 -1
  41. ccxt/pro/hyperliquid.py +6 -6
  42. ccxt/pro/kraken.py +17 -16
  43. ccxt/pro/mexc.py +10 -10
  44. ccxt/test/tests_async.py +19 -17
  45. ccxt/test/tests_sync.py +19 -17
  46. ccxt/wavesexchange.py +12 -2
  47. ccxt/woo.py +1251 -875
  48. {ccxt-4.4.93.dist-info → ccxt-4.4.95.dist-info}/METADATA +4 -4
  49. {ccxt-4.4.93.dist-info → ccxt-4.4.95.dist-info}/RECORD +52 -52
  50. {ccxt-4.4.93.dist-info → ccxt-4.4.95.dist-info}/LICENSE.txt +0 -0
  51. {ccxt-4.4.93.dist-info → ccxt-4.4.95.dist-info}/WHEEL +0 -0
  52. {ccxt-4.4.93.dist-info → ccxt-4.4.95.dist-info}/top_level.txt +0 -0
ccxt/hyperliquid.py CHANGED
@@ -173,6 +173,7 @@ class hyperliquid(Exchange, ImplicitAPI):
173
173
  'orderStatus': 2,
174
174
  'spotClearinghouseState': 2,
175
175
  'exchangeStatus': 2,
176
+ 'candleSnapshot': 3,
176
177
  },
177
178
  },
178
179
  },
@@ -353,6 +354,8 @@ class hyperliquid(Exchange, ImplicitAPI):
353
354
  :param dict [params]: extra parameters specific to the exchange API endpoint
354
355
  :returns dict: an associative dictionary of currencies
355
356
  """
357
+ if self.check_required_credentials(False):
358
+ self.handle_builder_fee_approval()
356
359
  request: dict = {
357
360
  'type': 'meta',
358
361
  }
@@ -626,6 +629,7 @@ class hyperliquid(Exchange, ImplicitAPI):
626
629
  'quote': quote,
627
630
  'settle': None,
628
631
  'baseId': baseId,
632
+ 'baseName': baseName,
629
633
  'quoteId': quoteId,
630
634
  'settleId': None,
631
635
  'type': 'spot',
@@ -728,6 +732,7 @@ class hyperliquid(Exchange, ImplicitAPI):
728
732
  'quote': quote,
729
733
  'settle': settle,
730
734
  'baseId': baseId,
735
+ 'baseName': baseName,
731
736
  'quoteId': quoteId,
732
737
  'settleId': settleId,
733
738
  'type': 'swap',
@@ -784,6 +789,7 @@ class hyperliquid(Exchange, ImplicitAPI):
784
789
  :param str [params.user]: user address, will default to self.walletAddress if not provided
785
790
  :param str [params.type]: wallet type, ['spot', 'swap'], defaults to swap
786
791
  :param str [params.marginMode]: 'cross' or 'isolated', for margin trading, uses self.options.defaultMarginMode if not passed, defaults to None/None/None
792
+ :param str [params.subAccountAddress]: sub account user address
787
793
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
788
794
  """
789
795
  userAddress = None
@@ -793,9 +799,8 @@ class hyperliquid(Exchange, ImplicitAPI):
793
799
  marginMode = None
794
800
  marginMode, params = self.handle_margin_mode_and_params('fetchBalance', params)
795
801
  isSpot = (type == 'spot')
796
- reqType = 'spotClearinghouseState' if (isSpot) else 'clearinghouseState'
797
802
  request: dict = {
798
- 'type': reqType,
803
+ 'type': 'spotClearinghouseState' if (isSpot) else 'clearinghouseState',
799
804
  'user': userAddress,
800
805
  }
801
806
  response = self.publicPostInfo(self.extend(request, params))
@@ -879,7 +884,7 @@ class hyperliquid(Exchange, ImplicitAPI):
879
884
  market = self.market(symbol)
880
885
  request: dict = {
881
886
  'type': 'l2Book',
882
- 'coin': market['base'] if market['swap'] else market['id'],
887
+ 'coin': market['baseName'] if market['swap'] else market['id'],
883
888
  }
884
889
  response = self.publicPostInfo(self.extend(request, params))
885
890
  #
@@ -1112,7 +1117,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1112
1117
  request: dict = {
1113
1118
  'type': 'candleSnapshot',
1114
1119
  'req': {
1115
- 'coin': market['base'] if market['swap'] else market['id'],
1120
+ 'coin': market['baseName'] if market['swap'] else market['id'],
1116
1121
  'interval': self.safe_string(self.timeframes, timeframe, timeframe),
1117
1122
  'startTime': since,
1118
1123
  'endTime': until,
@@ -1175,6 +1180,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1175
1180
  :param int [params.until]: timestamp in ms of the latest trade
1176
1181
  :param str [params.address]: wallet address that made trades
1177
1182
  :param str [params.user]: wallet address that made trades
1183
+ :param str [params.subAccountAddress]: sub account user address
1178
1184
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1179
1185
  """
1180
1186
  userAddress = None
@@ -1353,6 +1359,67 @@ class hyperliquid(Exchange, ImplicitAPI):
1353
1359
  }
1354
1360
  return self.sign_user_signed_action(messageTypes, message)
1355
1361
 
1362
+ def build_approve_builder_fee_sig(self, message):
1363
+ messageTypes: dict = {
1364
+ 'HyperliquidTransaction:ApproveBuilderFee': [
1365
+ {'name': 'hyperliquidChain', 'type': 'string'},
1366
+ {'name': 'maxFeeRate', 'type': 'string'},
1367
+ {'name': 'builder', 'type': 'address'},
1368
+ {'name': 'nonce', 'type': 'uint64'},
1369
+ ],
1370
+ }
1371
+ return self.sign_user_signed_action(messageTypes, message)
1372
+
1373
+ def approve_builder_fee(self, builder: str, maxFeeRate: str):
1374
+ nonce = self.milliseconds()
1375
+ isSandboxMode = self.safe_bool(self.options, 'sandboxMode', False)
1376
+ payload: dict = {
1377
+ 'hyperliquidChain': 'Testnet' if isSandboxMode else 'Mainnet',
1378
+ 'maxFeeRate': maxFeeRate,
1379
+ 'builder': builder,
1380
+ 'nonce': nonce,
1381
+ }
1382
+ sig = self.build_approve_builder_fee_sig(payload)
1383
+ action = {
1384
+ 'hyperliquidChain': payload['hyperliquidChain'],
1385
+ 'signatureChainId': '0x66eee',
1386
+ 'maxFeeRate': payload['maxFeeRate'],
1387
+ 'builder': payload['builder'],
1388
+ 'nonce': nonce,
1389
+ 'type': 'approveBuilderFee',
1390
+ }
1391
+ request: dict = {
1392
+ 'action': action,
1393
+ 'nonce': nonce,
1394
+ 'signature': sig,
1395
+ 'vaultAddress': None,
1396
+ }
1397
+ #
1398
+ # {
1399
+ # "status": "ok",
1400
+ # "response": {
1401
+ # "type": "default"
1402
+ # }
1403
+ # }
1404
+ #
1405
+ return self.privatePostExchange(request)
1406
+
1407
+ def handle_builder_fee_approval(self):
1408
+ buildFee = self.safe_bool(self.options, 'builderFee', True)
1409
+ if not buildFee:
1410
+ return False # skip if builder fee is not enabled
1411
+ approvedBuilderFee = self.safe_bool(self.options, 'approvedBuilderFee', False)
1412
+ if approvedBuilderFee:
1413
+ return True # skip if builder fee is already approved
1414
+ try:
1415
+ builder = self.safe_string(self.options, 'builder', '0x6530512A6c89C7cfCEbC3BA7fcD9aDa5f30827a6')
1416
+ maxFeeRate = self.safe_string(self.options, 'feeRate', '0.01%')
1417
+ self.approve_builder_fee(builder, maxFeeRate)
1418
+ self.options['approvedBuilderFee'] = True
1419
+ except Exception as e:
1420
+ self.options['builderFee'] = False # disable builder fee if an error occurs
1421
+ return True
1422
+
1356
1423
  def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1357
1424
  """
1358
1425
  create a trade order
@@ -1372,6 +1439,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1372
1439
  :param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1373
1440
  :param str [params.slippage]: the slippage for market order
1374
1441
  :param str [params.vaultAddress]: the vault address for order
1442
+ :param str [params.subAccountAddress]: sub account user address
1375
1443
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1376
1444
  """
1377
1445
  self.load_markets()
@@ -1390,6 +1458,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1390
1458
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1391
1459
  """
1392
1460
  self.load_markets()
1461
+ self.handle_builder_fee_approval()
1393
1462
  request = self.create_orders_request(orders, params)
1394
1463
  response = self.privatePostExchange(request)
1395
1464
  #
@@ -1553,10 +1622,10 @@ class hyperliquid(Exchange, ImplicitAPI):
1553
1622
  'type': 'order',
1554
1623
  'orders': orderReq,
1555
1624
  'grouping': grouping,
1556
- # 'brokerCode': 1, # cant
1557
1625
  }
1558
- if vaultAddress is None:
1559
- orderAction['brokerCode'] = 1
1626
+ if self.safe_bool(self.options, 'approvedBuilderFee', False):
1627
+ wallet = self.safe_string_lower(self.options, 'builder', '0x6530512A6c89C7cfCEbC3BA7fcD9aDa5f30827a6')
1628
+ orderAction['builder'] = {'b': wallet, 'f': self.safe_integer(self.options, 'feeInt', 10)}
1560
1629
  signature = self.sign_l1_action(orderAction, nonce, vaultAddress)
1561
1630
  request: dict = {
1562
1631
  'action': orderAction,
@@ -1581,6 +1650,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1581
1650
  :param dict [params]: extra parameters specific to the exchange API endpoint
1582
1651
  :param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1583
1652
  :param str [params.vaultAddress]: the vault address for order
1653
+ :param str [params.subAccountAddress]: sub account user address
1584
1654
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1585
1655
  """
1586
1656
  orders = self.cancel_orders([id], symbol, params)
@@ -1598,6 +1668,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1598
1668
  :param dict [params]: extra parameters specific to the exchange API endpoint
1599
1669
  :param string|str[] [params.clientOrderId]: client order ids,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1600
1670
  :param str [params.vaultAddress]: the vault address
1671
+ :param str [params.subAccountAddress]: sub account user address
1601
1672
  :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1602
1673
  """
1603
1674
  self.check_required_credentials()
@@ -1636,7 +1707,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1636
1707
  })
1637
1708
  cancelAction['cancels'] = cancelReq
1638
1709
  vaultAddress = None
1639
- vaultAddress, params = self.handle_option_and_params(params, 'cancelOrders', 'vaultAddress')
1710
+ vaultAddress, params = self.handle_option_and_params_2(params, 'cancelOrders', 'vaultAddress', 'subAccountAddress')
1640
1711
  vaultAddress = self.format_vault_address(vaultAddress)
1641
1712
  signature = self.sign_l1_action(cancelAction, nonce, vaultAddress)
1642
1713
  request['action'] = cancelAction
@@ -1680,6 +1751,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1680
1751
  :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"}]
1681
1752
  :param dict [params]: extra parameters specific to the exchange API endpoint
1682
1753
  :param str [params.vaultAddress]: the vault address
1754
+ :param str [params.subAccountAddress]: sub account user address
1683
1755
  :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1684
1756
  """
1685
1757
  self.check_required_credentials()
@@ -1716,7 +1788,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1716
1788
  cancelAction['type'] = 'cancelByCloid' if cancelByCloid else 'cancel'
1717
1789
  cancelAction['cancels'] = cancelReq
1718
1790
  vaultAddress = None
1719
- vaultAddress, params = self.handle_option_and_params(params, 'cancelOrdersForSymbols', 'vaultAddress')
1791
+ vaultAddress, params = self.handle_option_and_params_2(params, 'cancelOrdersForSymbols', 'vaultAddress', 'subAccountAddress')
1720
1792
  vaultAddress = self.format_vault_address(vaultAddress)
1721
1793
  signature = self.sign_l1_action(cancelAction, nonce, vaultAddress)
1722
1794
  request['action'] = cancelAction
@@ -1746,6 +1818,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1746
1818
  :param number timeout: time in milliseconds, 0 represents cancel the timer
1747
1819
  :param dict [params]: extra parameters specific to the exchange API endpoint
1748
1820
  :param str [params.vaultAddress]: the vault address
1821
+ :param str [params.subAccountAddress]: sub account user address
1749
1822
  :returns dict: the api result
1750
1823
  """
1751
1824
  self.check_required_credentials()
@@ -1761,7 +1834,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1761
1834
  'time': nonce + timeout,
1762
1835
  }
1763
1836
  vaultAddress = None
1764
- vaultAddress, params = self.handle_option_and_params(params, 'cancelAllOrdersAfter', 'vaultAddress')
1837
+ vaultAddress, params = self.handle_option_and_params_2(params, 'cancelAllOrdersAfter', 'vaultAddress', 'subAccountAddress')
1765
1838
  vaultAddress = self.format_vault_address(vaultAddress)
1766
1839
  signature = self.sign_l1_action(cancelAction, nonce, vaultAddress)
1767
1840
  request['action'] = cancelAction
@@ -1904,6 +1977,7 @@ class hyperliquid(Exchange, ImplicitAPI):
1904
1977
  :param float [params.triggerPrice]: The price at which a trigger order is triggered at
1905
1978
  :param str [params.clientOrderId]: client order id,(optional 128 bit hex string e.g. 0x1234567890abcdef1234567890abcdef)
1906
1979
  :param str [params.vaultAddress]: the vault address for order
1980
+ :param str [params.subAccountAddress]: sub account user address
1907
1981
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1908
1982
  """
1909
1983
  self.load_markets()
@@ -2023,7 +2097,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2023
2097
  market = self.market(symbol)
2024
2098
  request: dict = {
2025
2099
  'type': 'fundingHistory',
2026
- 'coin': market['base'],
2100
+ 'coin': market['baseName'],
2027
2101
  }
2028
2102
  if since is not None:
2029
2103
  request['startTime'] = since
@@ -2071,6 +2145,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2071
2145
  :param dict [params]: extra parameters specific to the exchange API endpoint
2072
2146
  :param str [params.user]: user address, will default to self.walletAddress if not provided
2073
2147
  :param str [params.method]: 'openOrders' or 'frontendOpenOrders' default is 'frontendOpenOrders'
2148
+ :param str [params.subAccountAddress]: sub account user address
2074
2149
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2075
2150
  """
2076
2151
  userAddress = None
@@ -2159,6 +2234,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2159
2234
  :param int [limit]: the maximum number of open orders structures to retrieve
2160
2235
  :param dict [params]: extra parameters specific to the exchange API endpoint
2161
2236
  :param str [params.user]: user address, will default to self.walletAddress if not provided
2237
+ :param str [params.subAccountAddress]: sub account user address
2162
2238
  :returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
2163
2239
  """
2164
2240
  userAddress = None
@@ -2195,6 +2271,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2195
2271
  :param str symbol: unified symbol of the market the order was made in
2196
2272
  :param dict [params]: extra parameters specific to the exchange API endpoint
2197
2273
  :param str [params.user]: user address, will default to self.walletAddress if not provided
2274
+ :param str [params.subAccountAddress]: sub account user address
2198
2275
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
2199
2276
  """
2200
2277
  userAddress = None
@@ -2420,6 +2497,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2420
2497
  :param int [limit]: the maximum number of trades structures to retrieve
2421
2498
  :param dict [params]: extra parameters specific to the exchange API endpoint
2422
2499
  :param int [params.until]: timestamp in ms of the latest trade
2500
+ :param str [params.subAccountAddress]: sub account user address
2423
2501
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
2424
2502
  """
2425
2503
  userAddress = None
@@ -2540,6 +2618,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2540
2618
  :param str[] [symbols]: list of unified market symbols
2541
2619
  :param dict [params]: extra parameters specific to the exchange API endpoint
2542
2620
  :param str [params.user]: user address, will default to self.walletAddress if not provided
2621
+ :param str [params.subAccountAddress]: sub account user address
2543
2622
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
2544
2623
  """
2545
2624
  self.load_markets()
@@ -2680,6 +2759,8 @@ class hyperliquid(Exchange, ImplicitAPI):
2680
2759
  :param str symbol: unified market symbol of the market the position is held in, default is None
2681
2760
  :param dict [params]: extra parameters specific to the exchange API endpoint
2682
2761
  :param str [params.leverage]: the rate of leverage, is required if setting trade mode(symbol)
2762
+ :param str [params.vaultAddress]: the vault address
2763
+ :param str [params.subAccountAddress]: sub account user address
2683
2764
  :returns dict: response from the exchange
2684
2765
  """
2685
2766
  if symbol is None:
@@ -2700,7 +2781,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2700
2781
  'leverage': leverage,
2701
2782
  }
2702
2783
  vaultAddress = None
2703
- vaultAddress, params = self.handle_option_and_params(params, 'setMarginMode', 'vaultAddress')
2784
+ vaultAddress, params = self.handle_option_and_params_2(params, 'setMarginMode', 'vaultAddress', 'subAccountAddress')
2704
2785
  if vaultAddress is not None:
2705
2786
  if vaultAddress.startswith('0x'):
2706
2787
  vaultAddress = vaultAddress.replace('0x', '')
@@ -2749,7 +2830,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2749
2830
  'leverage': leverage,
2750
2831
  }
2751
2832
  vaultAddress = None
2752
- vaultAddress, params = self.handle_option_and_params(params, 'setLeverage', 'vaultAddress')
2833
+ vaultAddress, params = self.handle_option_and_params_2(params, 'setLeverage', 'vaultAddress', 'subAccountAddress')
2753
2834
  vaultAddress = self.format_vault_address(vaultAddress)
2754
2835
  signature = self.sign_l1_action(updateAction, nonce, vaultAddress)
2755
2836
  request: dict = {
@@ -2781,6 +2862,8 @@ class hyperliquid(Exchange, ImplicitAPI):
2781
2862
  :param str symbol: unified market symbol
2782
2863
  :param float amount: amount of margin to add
2783
2864
  :param dict [params]: extra parameters specific to the exchange API endpoint
2865
+ :param str [params.vaultAddress]: the vault address
2866
+ :param str [params.subAccountAddress]: sub account user address
2784
2867
  :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=add-margin-structure>`
2785
2868
  """
2786
2869
  return self.modify_margin_helper(symbol, amount, 'add', params)
@@ -2794,6 +2877,8 @@ class hyperliquid(Exchange, ImplicitAPI):
2794
2877
  :param str symbol: unified market symbol
2795
2878
  :param float amount: the amount of margin to remove
2796
2879
  :param dict [params]: extra parameters specific to the exchange API endpoint
2880
+ :param str [params.vaultAddress]: the vault address
2881
+ :param str [params.subAccountAddress]: sub account user address
2797
2882
  :returns dict: a `margin structure <https://docs.ccxt.com/#/?id=reduce-margin-structure>`
2798
2883
  """
2799
2884
  return self.modify_margin_helper(symbol, amount, 'reduce', params)
@@ -2813,7 +2898,7 @@ class hyperliquid(Exchange, ImplicitAPI):
2813
2898
  'ntli': sz,
2814
2899
  }
2815
2900
  vaultAddress = None
2816
- vaultAddress, params = self.handle_option_and_params(params, 'modifyMargin', 'vaultAddress')
2901
+ vaultAddress, params = self.handle_option_and_params_2(params, 'modifyMargin', 'vaultAddress', 'subAccountAddress')
2817
2902
  vaultAddress = self.format_vault_address(vaultAddress)
2818
2903
  signature = self.sign_l1_action(updateAction, nonce, vaultAddress)
2819
2904
  request: dict = {
@@ -2908,28 +2993,31 @@ class hyperliquid(Exchange, ImplicitAPI):
2908
2993
  transferRequest['vaultAddress'] = vaultAddress
2909
2994
  transferResponse = self.privatePostExchange(transferRequest)
2910
2995
  return transferResponse
2911
- # handle sub-account/different account transfer
2912
- self.check_address(toAccount)
2996
+ # transfer between main account and subaccount
2913
2997
  if code is not None:
2914
2998
  code = code.upper()
2915
2999
  if code != 'USDC':
2916
3000
  raise NotSupported(self.id + ' transfer() only support USDC')
2917
- payload: dict = {
2918
- 'hyperliquidChain': 'Testnet' if isSandboxMode else 'Mainnet',
2919
- 'destination': toAccount,
2920
- 'amount': self.number_to_string(amount),
2921
- 'time': nonce,
3001
+ isDeposit = False
3002
+ subAccountAddress = None
3003
+ if fromAccount == 'main':
3004
+ subAccountAddress = toAccount
3005
+ isDeposit = True
3006
+ elif toAccount == 'main':
3007
+ subAccountAddress = fromAccount
3008
+ else:
3009
+ raise NotSupported(self.id + ' transfer() only support main <> subaccount transfer')
3010
+ 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,
2922
3017
  }
2923
- sig = self.build_usd_send_sig(payload)
3018
+ sig = self.sign_l1_action(action, nonce)
2924
3019
  request: dict = {
2925
- 'action': {
2926
- 'hyperliquidChain': payload['hyperliquidChain'],
2927
- 'signatureChainId': '0x66eee', # check self out
2928
- 'destination': toAccount,
2929
- 'amount': str(amount),
2930
- 'time': nonce,
2931
- 'type': 'usdSend',
2932
- },
3020
+ 'action': action,
2933
3021
  'nonce': nonce,
2934
3022
  'signature': sig,
2935
3023
  }
@@ -3074,6 +3162,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3074
3162
  :param str symbol: unified market symbol
3075
3163
  :param dict [params]: extra parameters specific to the exchange API endpoint
3076
3164
  :param str [params.user]: user address, will default to self.walletAddress if not provided
3165
+ :param str [params.subAccountAddress]: sub account user address
3077
3166
  :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
3078
3167
  """
3079
3168
  self.load_markets()
@@ -3180,6 +3269,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3180
3269
  :param int [limit]: max number of ledger entries to return
3181
3270
  :param dict [params]: extra parameters specific to the exchange API endpoint
3182
3271
  :param int [params.until]: timestamp in ms of the latest ledger entry
3272
+ :param str [params.subAccountAddress]: sub account user address
3183
3273
  :returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
3184
3274
  """
3185
3275
  self.load_markets()
@@ -3267,6 +3357,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3267
3357
  :param int [limit]: the maximum number of deposits structures to retrieve
3268
3358
  :param dict [params]: extra parameters specific to the exchange API endpoint
3269
3359
  :param int [params.until]: the latest time in ms to fetch withdrawals for
3360
+ :param str [params.subAccountAddress]: sub account user address
3270
3361
  :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
3271
3362
  """
3272
3363
  self.load_markets()
@@ -3308,6 +3399,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3308
3399
  :param int [limit]: the maximum number of withdrawals structures to retrieve
3309
3400
  :param dict [params]: extra parameters specific to the exchange API endpoint
3310
3401
  :param int [params.until]: the latest time in ms to fetch withdrawals for
3402
+ :param str [params.subAccountAddress]: sub account user address
3311
3403
  :returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
3312
3404
  """
3313
3405
  self.load_markets()
@@ -3405,6 +3497,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3405
3497
  :param int [since]: the earliest time in ms to fetch funding history for
3406
3498
  :param int [limit]: the maximum number of funding history structures to retrieve
3407
3499
  :param dict [params]: extra parameters specific to the exchange API endpoint
3500
+ :param str [params.subAccountAddress]: sub account user address
3408
3501
  :returns dict: a `funding history structure <https://docs.ccxt.com/#/?id=funding-history-structure>`
3409
3502
  """
3410
3503
  self.load_markets()
@@ -3495,7 +3588,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3495
3588
 
3496
3589
  def handle_public_address(self, methodName: str, params: dict):
3497
3590
  userAux = None
3498
- userAux, params = self.handle_option_and_params(params, methodName, 'user')
3591
+ userAux, params = self.handle_option_and_params_2(params, methodName, 'user', 'subAccountAddress')
3499
3592
  user = userAux
3500
3593
  user, params = self.handle_option_and_params(params, methodName, 'address', userAux)
3501
3594
  if (user is not None) and (user != ''):
@@ -3507,7 +3600,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3507
3600
  def coin_to_market_id(self, coin: Str):
3508
3601
  if coin.find('/') > -1 or coin.find('@') > -1:
3509
3602
  return coin # spot
3510
- return coin + '/USDC:USDC'
3603
+ return self.safe_currency_code(coin) + '/USDC:USDC'
3511
3604
 
3512
3605
  def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
3513
3606
  if not response:
@@ -3562,7 +3655,7 @@ class hyperliquid(Exchange, ImplicitAPI):
3562
3655
  def parse_create_edit_order_args(self, id: Str, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
3563
3656
  market = self.market(symbol)
3564
3657
  vaultAddress = None
3565
- vaultAddress, params = self.handle_option_and_params(params, 'createOrder', 'vaultAddress')
3658
+ vaultAddress, params = self.handle_option_and_params_2(params, 'createOrder', 'vaultAddress', 'subAccountAddress')
3566
3659
  vaultAddress = self.format_vault_address(vaultAddress)
3567
3660
  symbol = market['symbol']
3568
3661
  order = {
ccxt/okx.py CHANGED
@@ -2556,11 +2556,11 @@ class okx(Exchange, ImplicitAPI):
2556
2556
  # it may be incorrect to use total, free and used for swap accounts
2557
2557
  eq = self.safe_string(balance, 'eq')
2558
2558
  availEq = self.safe_string(balance, 'availEq')
2559
- if (eq is None) or (availEq is None):
2559
+ account['total'] = eq
2560
+ if availEq is None:
2560
2561
  account['free'] = self.safe_string(balance, 'availBal')
2561
2562
  account['used'] = self.safe_string(balance, 'frozenBal')
2562
2563
  else:
2563
- account['total'] = eq
2564
2564
  account['free'] = availEq
2565
2565
  result[code] = account
2566
2566
  result['timestamp'] = timestamp
@@ -2958,7 +2958,8 @@ class okx(Exchange, ImplicitAPI):
2958
2958
  stopLossTriggerPrice = self.safe_value_n(stopLoss, ['triggerPrice', 'stopPrice', 'slTriggerPx'])
2959
2959
  if stopLossTriggerPrice is None:
2960
2960
  raise InvalidOrder(self.id + ' createOrder() requires a trigger price in params["stopLoss"]["triggerPrice"], or params["stopLoss"]["stopPrice"], or params["stopLoss"]["slTriggerPx"] for a stop loss order')
2961
- request['slTriggerPx'] = self.price_to_precision(symbol, stopLossTriggerPrice)
2961
+ slTriggerPx = self.price_to_precision(symbol, stopLossTriggerPrice)
2962
+ request['slTriggerPx'] = slTriggerPx
2962
2963
  stopLossLimitPrice = self.safe_value_n(stopLoss, ['price', 'stopLossPrice', 'slOrdPx'])
2963
2964
  stopLossOrderType = self.safe_string(stopLoss, 'type')
2964
2965
  if stopLossOrderType is not None:
@@ -3024,6 +3025,12 @@ class okx(Exchange, ImplicitAPI):
3024
3025
  # tpOrdKind is 'condition' which is the default
3025
3026
  if twoWayCondition:
3026
3027
  request['ordType'] = 'oco'
3028
+ if side == 'sell':
3029
+ request = self.omit(request, 'tgtCcy')
3030
+ if self.safe_string(request, 'tdMode') == 'cash':
3031
+ # for some reason tdMode = cash throws
3032
+ # {"code":"1","data":[{"algoClOrdId":"","algoId":"","clOrdId":"","sCode":"51000","sMsg":"Parameter tdMode error ","tag":""}],"msg":""}
3033
+ request['tdMode'] = marginMode
3027
3034
  if takeProfitPrice is not None:
3028
3035
  request['tpTriggerPx'] = self.price_to_precision(symbol, takeProfitPrice)
3029
3036
  tpOrdPxReq = '-1'
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.93'
7
+ __version__ = '4.4.95'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/pro/hyperliquid.py CHANGED
@@ -170,7 +170,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
170
170
  'method': 'subscribe',
171
171
  'subscription': {
172
172
  'type': 'l2Book',
173
- 'coin': market['base'] if market['swap'] else market['id'],
173
+ 'coin': market['baseName'] if market['swap'] else market['id'],
174
174
  },
175
175
  }
176
176
  message = self.extend(request, params)
@@ -199,7 +199,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
199
199
  'method': 'unsubscribe',
200
200
  'subscription': {
201
201
  'type': 'l2Book',
202
- 'coin': market['base'] if market['swap'] else market['id'],
202
+ 'coin': market['baseName'] if market['swap'] else market['id'],
203
203
  },
204
204
  }
205
205
  message = self.extend(request, params)
@@ -500,7 +500,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
500
500
  'method': 'subscribe',
501
501
  'subscription': {
502
502
  'type': 'trades',
503
- 'coin': market['base'] if market['swap'] else market['id'],
503
+ 'coin': market['baseName'] if market['swap'] else market['id'],
504
504
  },
505
505
  }
506
506
  message = self.extend(request, params)
@@ -529,7 +529,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
529
529
  'method': 'unsubscribe',
530
530
  'subscription': {
531
531
  'type': 'trades',
532
- 'coin': market['base'] if market['swap'] else market['id'],
532
+ 'coin': market['baseName'] if market['swap'] else market['id'],
533
533
  },
534
534
  }
535
535
  message = self.extend(request, params)
@@ -653,7 +653,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
653
653
  'method': 'subscribe',
654
654
  'subscription': {
655
655
  'type': 'candle',
656
- 'coin': market['base'] if market['swap'] else market['id'],
656
+ 'coin': market['baseName'] if market['swap'] else market['id'],
657
657
  'interval': timeframe,
658
658
  },
659
659
  }
@@ -683,7 +683,7 @@ class hyperliquid(ccxt.async_support.hyperliquid):
683
683
  'method': 'unsubscribe',
684
684
  'subscription': {
685
685
  'type': 'candle',
686
- 'coin': market['base'] if market['swap'] else market['id'],
686
+ 'coin': market['baseName'] if market['swap'] else market['id'],
687
687
  'interval': timeframe,
688
688
  },
689
689
  }
ccxt/pro/kraken.py CHANGED
@@ -745,15 +745,13 @@ class kraken(ccxt.async_support.kraken):
745
745
  :param dict [params]: extra parameters specific to the exchange API endpoint
746
746
  :returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
747
747
  """
748
- request: dict = {}
748
+ requiredParams: dict = {}
749
749
  if limit is not None:
750
750
  if self.in_array(limit, [10, 25, 100, 500, 1000]):
751
- request['params'] = {
752
- 'depth': limit, # default 10, valid options 10, 25, 100, 500, 1000
753
- }
751
+ requiredParams['depth'] = limit # default 10, valid options 10, 25, 100, 500, 1000
754
752
  else:
755
753
  raise NotSupported(self.id + ' watchOrderBook accepts limit values of 10, 25, 100, 500 and 1000 only')
756
- orderbook = await self.watch_multi_helper('orderbook', 'book', symbols, {'limit': limit}, self.extend(request, params))
754
+ orderbook = await self.watch_multi_helper('orderbook', 'book', symbols, {'limit': limit}, self.extend(requiredParams, params))
757
755
  return orderbook.limit()
758
756
 
759
757
  async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
@@ -1614,17 +1612,20 @@ class kraken(ccxt.async_support.kraken):
1614
1612
  #
1615
1613
  errorMessage = self.safe_string_2(message, 'errorMessage', 'error')
1616
1614
  if errorMessage is not None:
1617
- requestId = self.safe_value_2(message, 'reqid', 'req_id')
1618
- if requestId is not None:
1619
- broad = self.exceptions['ws']['broad']
1620
- broadKey = self.find_broadly_matched_key(broad, errorMessage)
1621
- exception = None
1622
- if broadKey is None:
1623
- exception = ExchangeError(errorMessage) # c# requirement to convert the errorMessage to string
1624
- else:
1625
- exception = broad[broadKey](errorMessage)
1626
- client.reject(exception, requestId)
1627
- return False
1615
+ # requestId = self.safe_value_2(message, 'reqid', 'req_id')
1616
+ broad = self.exceptions['ws']['broad']
1617
+ broadKey = self.find_broadly_matched_key(broad, errorMessage)
1618
+ exception = None
1619
+ if broadKey is None:
1620
+ exception = ExchangeError(errorMessage) # c# requirement to convert the errorMessage to string
1621
+ else:
1622
+ exception = broad[broadKey](errorMessage)
1623
+ # if requestId is not None:
1624
+ # client.reject(exception, requestId)
1625
+ # else:
1626
+ client.reject(exception)
1627
+ # }
1628
+ return False
1628
1629
  return True
1629
1630
 
1630
1631
  def handle_message(self, client: Client, message):