@@ -52,13 +52,15 @@ def __init__(
5252 self .vault_address = vault_address
5353 self .account_address = account_address
5454 self .info = Info (base_url , True , meta , spot_meta )
55+ self .expires_after : Optional [int ] = None
5556
5657 def _post_action (self , action , signature , nonce ):
5758 payload = {
5859 "action" : action ,
5960 "nonce" : nonce ,
6061 "signature" : signature ,
6162 "vaultAddress" : self .vault_address if action ["type" ] != "usdClassTransfer" else None ,
63+ "expiresAfter" : self .expires_after ,
6264 }
6365 logging .debug (payload )
6466 return self .post ("/exchange" , payload )
@@ -84,6 +86,12 @@ def _slippage_price(
8486 # We round px to 5 significant figures and 6 decimals for perps, 8 decimals for spot
8587 return round (float (f"{ px :.5g} " ), (6 if not is_spot else 8 ) - self .info .asset_to_sz_decimals [asset ])
8688
89+ # expires_after will cause actions to be rejected after that timestamp in milliseconds
90+ # expires_after is not supported on user_signed actions (e.g. usd_transfer) and must be None in order for those
91+ # actions to work.
92+ def set_expires_after (self , expires_after : Optional [int ]) -> None :
93+ self .expires_after = expires_after
94+
8795 def order (
8896 self ,
8997 name : str ,
@@ -122,6 +130,7 @@ def bulk_orders(self, order_requests: List[OrderRequest], builder: Optional[Buil
122130 order_action ,
123131 self .vault_address ,
124132 timestamp ,
133+ self .expires_after ,
125134 self .base_url == MAINNET_API_URL ,
126135 )
127136
@@ -176,6 +185,7 @@ def bulk_modify_orders_new(self, modify_requests: List[ModifyRequest]) -> Any:
176185 modify_action ,
177186 self .vault_address ,
178187 timestamp ,
188+ self .expires_after ,
179189 self .base_url == MAINNET_API_URL ,
180190 )
181191
@@ -262,6 +272,7 @@ def bulk_cancel(self, cancel_requests: List[CancelRequest]) -> Any:
262272 cancel_action ,
263273 self .vault_address ,
264274 timestamp ,
275+ self .expires_after ,
265276 self .base_url == MAINNET_API_URL ,
266277 )
267278
@@ -289,6 +300,7 @@ def bulk_cancel_by_cloid(self, cancel_requests: List[CancelByCloidRequest]) -> A
289300 cancel_action ,
290301 self .vault_address ,
291302 timestamp ,
303+ self .expires_after ,
292304 self .base_url == MAINNET_API_URL ,
293305 )
294306
@@ -317,6 +329,7 @@ def schedule_cancel(self, time: Optional[int]) -> Any:
317329 schedule_cancel_action ,
318330 self .vault_address ,
319331 timestamp ,
332+ self .expires_after ,
320333 self .base_url == MAINNET_API_URL ,
321334 )
322335 return self ._post_action (
@@ -338,6 +351,7 @@ def update_leverage(self, leverage: int, name: str, is_cross: bool = True) -> An
338351 update_leverage_action ,
339352 self .vault_address ,
340353 timestamp ,
354+ self .expires_after ,
341355 self .base_url == MAINNET_API_URL ,
342356 )
343357 return self ._post_action (
@@ -360,6 +374,7 @@ def update_isolated_margin(self, amount: float, name: str) -> Any:
360374 update_isolated_margin_action ,
361375 self .vault_address ,
362376 timestamp ,
377+ self .expires_after ,
363378 self .base_url == MAINNET_API_URL ,
364379 )
365380 return self ._post_action (
@@ -379,6 +394,7 @@ def set_referrer(self, code: str) -> Any:
379394 set_referrer_action ,
380395 None ,
381396 timestamp ,
397+ self .expires_after ,
382398 self .base_url == MAINNET_API_URL ,
383399 )
384400 return self ._post_action (
@@ -398,6 +414,7 @@ def create_sub_account(self, name: str) -> Any:
398414 create_sub_account_action ,
399415 None ,
400416 timestamp ,
417+ self .expires_after ,
401418 self .base_url == MAINNET_API_URL ,
402419 )
403420 return self ._post_action (
@@ -438,6 +455,7 @@ def sub_account_transfer(self, sub_account_user: str, is_deposit: bool, usd: int
438455 sub_account_transfer_action ,
439456 None ,
440457 timestamp ,
458+ self .expires_after ,
441459 self .base_url == MAINNET_API_URL ,
442460 )
443461 return self ._post_action (
@@ -460,6 +478,7 @@ def sub_account_spot_transfer(self, sub_account_user: str, is_deposit: bool, tok
460478 sub_account_transfer_action ,
461479 None ,
462480 timestamp ,
481+ self .expires_after ,
463482 self .base_url == MAINNET_API_URL ,
464483 )
465484 return self ._post_action (
@@ -477,7 +496,7 @@ def vault_usd_transfer(self, vault_address: str, is_deposit: bool, usd: int) ->
477496 "usd" : usd ,
478497 }
479498 is_mainnet = self .base_url == MAINNET_API_URL
480- signature = sign_l1_action (self .wallet , vault_transfer_action , None , timestamp , is_mainnet )
499+ signature = sign_l1_action (self .wallet , vault_transfer_action , None , timestamp , self . expires_after , is_mainnet )
481500 return self ._post_action (
482501 vault_transfer_action ,
483502 signature ,
@@ -590,6 +609,7 @@ def spot_deploy_register_token(
590609 action ,
591610 None ,
592611 timestamp ,
612+ self .expires_after ,
593613 self .base_url == MAINNET_API_URL ,
594614 )
595615 return self ._post_action (
@@ -615,6 +635,7 @@ def spot_deploy_user_genesis(
615635 action ,
616636 None ,
617637 timestamp ,
638+ self .expires_after ,
618639 self .base_url == MAINNET_API_URL ,
619640 )
620641 return self ._post_action (
@@ -636,6 +657,7 @@ def spot_deploy_enable_freeze_privilege(self, token: int) -> Any:
636657 action ,
637658 None ,
638659 timestamp ,
660+ self .expires_after ,
639661 self .base_url == MAINNET_API_URL ,
640662 )
641663 return self ._post_action (
@@ -659,6 +681,7 @@ def spot_deploy_freeze_user(self, token: int, user: str, freeze: bool) -> Any:
659681 action ,
660682 None ,
661683 timestamp ,
684+ self .expires_after ,
662685 self .base_url == MAINNET_API_URL ,
663686 )
664687 return self ._post_action (
@@ -680,6 +703,7 @@ def spot_deploy_revoke_freeze_privilege(self, token: int) -> Any:
680703 action ,
681704 None ,
682705 timestamp ,
706+ self .expires_after ,
683707 self .base_url == MAINNET_API_URL ,
684708 )
685709 return self ._post_action (
@@ -705,6 +729,7 @@ def spot_deploy_genesis(self, token: int, max_supply: str, no_hyperliquidity: bo
705729 action ,
706730 None ,
707731 timestamp ,
732+ self .expires_after ,
708733 self .base_url == MAINNET_API_URL ,
709734 )
710735 return self ._post_action (
@@ -726,6 +751,7 @@ def spot_deploy_register_spot(self, base_token: int, quote_token: int) -> Any:
726751 action ,
727752 None ,
728753 timestamp ,
754+ self .expires_after ,
729755 self .base_url == MAINNET_API_URL ,
730756 )
731757 return self ._post_action (
@@ -755,6 +781,30 @@ def spot_deploy_register_hyperliquidity(
755781 action ,
756782 None ,
757783 timestamp ,
784+ self .expires_after ,
785+ self .base_url == MAINNET_API_URL ,
786+ )
787+ return self ._post_action (
788+ action ,
789+ signature ,
790+ timestamp ,
791+ )
792+
793+ def spot_deploy_set_deployer_trading_fee_share (self , token : int , share : str ) -> Any :
794+ timestamp = get_timestamp_ms ()
795+ action = {
796+ "type" : "spotDeploy" ,
797+ "setDeployerTradingFeeShare" : {
798+ "token" : token ,
799+ "share" : share ,
800+ },
801+ }
802+ signature = sign_l1_action (
803+ self .wallet ,
804+ action ,
805+ None ,
806+ timestamp ,
807+ self .expires_after ,
758808 self .base_url == MAINNET_API_URL ,
759809 )
760810 return self ._post_action (
@@ -782,6 +832,7 @@ def multi_sig(self, multi_sig_user, inner_action, signatures, nonce, vault_addre
782832 is_mainnet ,
783833 vault_address ,
784834 nonce ,
835+ self .expires_after ,
785836 )
786837 return self ._post_action (
787838 multi_sig_action ,
@@ -800,6 +851,7 @@ def use_big_blocks(self, enable: bool) -> Any:
800851 action ,
801852 None ,
802853 timestamp ,
854+ self .expires_after ,
803855 self .base_url == MAINNET_API_URL ,
804856 )
805857 return self ._post_action (
0 commit comments