diff --git a/examples/dex_abstraction.py b/examples/dex_abstraction.py new file mode 100644 index 00000000..c15f715d --- /dev/null +++ b/examples/dex_abstraction.py @@ -0,0 +1,52 @@ +# See https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#enable-hip-3-dex-abstraction for more details +import example_utils + +from hyperliquid.exchange import Exchange +from hyperliquid.utils import constants + +SUB_ACCOUNT_NAME = "One" + + +def main(): + address, info, exchange = example_utils.setup(constants.TESTNET_API_URL, skip_ws=True) + + # enable dex abstraction for user via agent + agent_enable_dex_abstraction_result = exchange.agent_enable_dex_abstraction() + print(agent_enable_dex_abstraction_result) + + user = exchange.account_address + if user == exchange.wallet.address: + # disable dex abstraction for user + user_dex_abstraction_result = exchange.user_dex_abstraction(user, False) + print(user_dex_abstraction_result) + print("current user dex abstraction state:", info.query_user_dex_abstraction_state(user)) + + # enable and disable dex abstraction for sub-account of user + sub_accounts = info.query_sub_accounts(user) + sub_account_user = None + for sub_account in sub_accounts: + if sub_account["name"] == SUB_ACCOUNT_NAME: + sub_account_user = sub_account["subAccountUser"] + print("found sub-account, enabling and disabling dex abstraction for", sub_account_user) + + # enable dex abstraction for user via agent by setting the vault_address to the sub_account_user + exchange_with_sub_account = Exchange(exchange.wallet, exchange.base_url, vault_address=sub_account_user) + agent_enable_dex_abstraction_result = exchange_with_sub_account.agent_enable_dex_abstraction() + print("sub-account agent_enable_dex_abstraction result:", agent_enable_dex_abstraction_result) + + for enabled in [True, False]: + user_dex_abstraction_result = exchange.user_dex_abstraction(sub_account_user, enabled) + print(user_dex_abstraction_result) + print( + "current sub-account user dex abstraction state:", + info.query_user_dex_abstraction_state(sub_account_user), + ) + + break + + else: + print("not performing user dex abstraction because not user", exchange.account_address, exchange.wallet.address) + + +if __name__ == "__main__": + main() diff --git a/examples/multi_sig_usd_send.py b/examples/multi_sig_usd_send.py index 34177e87..58fd13c6 100644 --- a/examples/multi_sig_usd_send.py +++ b/examples/multi_sig_usd_send.py @@ -1,7 +1,7 @@ import example_utils from hyperliquid.utils import constants -from hyperliquid.utils.signing import USD_SEND_SIGN_TYPES, get_timestamp_ms, sign_multi_sig_user_signed_action_payload +from hyperliquid.utils.signing import SEND_ASSET_SIGN_TYPES, get_timestamp_ms, sign_multi_sig_user_signed_action_payload def main(): @@ -19,12 +19,16 @@ def main(): # Define the multi-sig inner action - in this case, sending USD action = { - "type": "usdSend", + "type": "sendAsset", "signatureChainId": "0x66eee", "hyperliquidChain": "Testnet", "destination": "0x0000000000000000000000000000000000000000", + "sourceDex": "", + "destinationDex": "", + "token": "USDC", "amount": "100.0", - "time": timestamp, + "fromSubAccount": "", + "nonce": timestamp, } signatures = [] @@ -35,8 +39,8 @@ def main(): wallet, action, exchange.base_url == constants.MAINNET_API_URL, - USD_SEND_SIGN_TYPES, - "HyperliquidTransaction:UsdSend", + SEND_ASSET_SIGN_TYPES, + "HyperliquidTransaction:SendAsset", multi_sig_user, address, ) diff --git a/hyperliquid/exchange.py b/hyperliquid/exchange.py index d677e5f7..96677f2d 100644 --- a/hyperliquid/exchange.py +++ b/hyperliquid/exchange.py @@ -31,6 +31,7 @@ sign_token_delegate_action, sign_usd_class_transfer_action, sign_usd_transfer_action, + sign_user_dex_abstraction_action, sign_withdraw_from_bridge_action, ) from hyperliquid.utils.types import ( @@ -1110,6 +1111,40 @@ def use_big_blocks(self, enable: bool) -> Any: timestamp, ) + def agent_enable_dex_abstraction(self) -> Any: + timestamp = get_timestamp_ms() + action = { + "type": "agentEnableDexAbstraction", + } + signature = sign_l1_action( + self.wallet, + action, + self.vault_address, + timestamp, + self.expires_after, + self.base_url == MAINNET_API_URL, + ) + return self._post_action( + action, + signature, + timestamp, + ) + + def user_dex_abstraction(self, user: str, enabled: bool) -> Any: + timestamp = get_timestamp_ms() + action = { + "type": "userDexAbstraction", + "user": user.lower(), + "enabled": enabled, + "nonce": timestamp, + } + signature = sign_user_dex_abstraction_action(self.wallet, action, self.base_url == MAINNET_API_URL) + return self._post_action( + action, + signature, + timestamp, + ) + def noop(self, nonce): action = {"type": "noop"} signature = sign_l1_action( diff --git a/hyperliquid/info.py b/hyperliquid/info.py index 5898386b..b59f81e8 100644 --- a/hyperliquid/info.py +++ b/hyperliquid/info.py @@ -626,6 +626,9 @@ def query_user_to_multi_sig_signers(self, multi_sig_user: str) -> Any: def query_perp_deploy_auction_status(self) -> Any: return self.post("/info", {"type": "perpDeployAuctionStatus"}) + def query_user_dex_abstraction_state(self, user: str) -> Any: + return self.post("/info", {"type": "userDexAbstraction", "user": user}) + def historical_orders(self, user: str) -> Any: """Retrieve a user's historical orders. diff --git a/hyperliquid/utils/signing.py b/hyperliquid/utils/signing.py index c0b3a0a3..578f05d3 100644 --- a/hyperliquid/utils/signing.py +++ b/hyperliquid/utils/signing.py @@ -115,6 +115,13 @@ {"name": "nonce", "type": "uint64"}, ] +USER_DEX_ABSTRACTION_SIGN_TYPES = [ + {"name": "hyperliquidChain", "type": "string"}, + {"name": "user", "type": "address"}, + {"name": "enabled", "type": "bool"}, + {"name": "nonce", "type": "uint64"}, +] + TOKEN_DELEGATE_TYPES = [ {"name": "hyperliquidChain", "type": "string"}, {"name": "validator", "type": "address"}, @@ -362,6 +369,16 @@ def sign_send_asset_action(wallet, action, is_mainnet): ) +def sign_user_dex_abstraction_action(wallet, action, is_mainnet): + return sign_user_signed_action( + wallet, + action, + USER_DEX_ABSTRACTION_SIGN_TYPES, + "HyperliquidTransaction:UserDexAbstraction", + is_mainnet, + ) + + def sign_convert_to_multi_sig_user_action(wallet, action, is_mainnet): return sign_user_signed_action( wallet, diff --git a/pyproject.toml b/pyproject.toml index 4e08d107..b7e75695 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "hyperliquid-python-sdk" -version = "0.19.0" +version = "0.20.0" description = "SDK for Hyperliquid API trading with Python." readme = "README.md" authors = ["Hyperliquid "]