async-hyperliquid 0.3.10__tar.gz → 0.4.0__tar.gz
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.
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/PKG-INFO +1 -1
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/pyproject.toml +1 -1
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/async_hyperliquid.py +108 -32
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/info.py +2 -1
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/utils/signing.py +8 -4
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/utils/types.py +41 -1
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/LICENSE +0 -0
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/README.md +0 -0
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/__init__.py +0 -0
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/async_api.py +0 -0
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/exchange.py +0 -0
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/utils/__init__.py +0 -0
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/utils/constants.py +0 -0
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/utils/decorators.py +0 -0
- {async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/utils/miscs.py +0 -0
{async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/async_hyperliquid.py
RENAMED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import re
|
|
1
2
|
import math
|
|
2
3
|
import asyncio
|
|
4
|
+
import warnings
|
|
3
5
|
from typing import Literal
|
|
4
6
|
|
|
5
7
|
from aiohttp import ClientSession, ClientTimeout
|
|
@@ -22,12 +24,12 @@ from async_hyperliquid.utils.miscs import (
|
|
|
22
24
|
from async_hyperliquid.utils.types import (
|
|
23
25
|
Cloid,
|
|
24
26
|
Metas,
|
|
27
|
+
LimitTif,
|
|
25
28
|
PerpMeta,
|
|
26
29
|
Position,
|
|
27
30
|
SpotMeta,
|
|
28
31
|
OrderType,
|
|
29
32
|
Portfolio,
|
|
30
|
-
LimitOrder,
|
|
31
33
|
Abstraction,
|
|
32
34
|
UserDeposit,
|
|
33
35
|
AccountState,
|
|
@@ -38,12 +40,15 @@ from async_hyperliquid.utils.types import (
|
|
|
38
40
|
SpotTokenMeta,
|
|
39
41
|
UserOpenOrders,
|
|
40
42
|
OrderWithStatus,
|
|
43
|
+
AgentAbstraction,
|
|
41
44
|
PlaceOrderRequest,
|
|
42
45
|
BatchCancelRequest,
|
|
43
46
|
ClearinghouseState,
|
|
47
|
+
UserSetAbstraction,
|
|
44
48
|
UserNonFundingDelta,
|
|
45
49
|
BatchPlaceOrderRequest,
|
|
46
50
|
SpotClearinghouseState,
|
|
51
|
+
limit_order_type,
|
|
47
52
|
)
|
|
48
53
|
from async_hyperliquid.utils.signing import (
|
|
49
54
|
encode_order,
|
|
@@ -501,17 +506,12 @@ class AsyncHyperliquid(AsyncAPI):
|
|
|
501
506
|
positions.extend(result)
|
|
502
507
|
return positions
|
|
503
508
|
|
|
504
|
-
async def
|
|
505
|
-
if not address:
|
|
506
|
-
address = self.address
|
|
507
|
-
return await self.info.get_user_dex_abstraction(address)
|
|
508
|
-
|
|
509
|
-
async def get_user_abstraction_state(
|
|
509
|
+
async def get_user_abstraction(
|
|
510
510
|
self, address: str | None = None
|
|
511
|
-
) ->
|
|
511
|
+
) -> Abstraction:
|
|
512
512
|
if not address:
|
|
513
513
|
address = self.address
|
|
514
|
-
return await self.info.
|
|
514
|
+
return await self.info.get_user_abstraction(address)
|
|
515
515
|
|
|
516
516
|
# Exchange API
|
|
517
517
|
async def _round_sz_px(self, coin: str, sz: float, px: float):
|
|
@@ -521,26 +521,46 @@ class AsyncHyperliquid(AsyncAPI):
|
|
|
521
521
|
px_decimals = (6 if not is_spot else 8) - sz_decimals
|
|
522
522
|
return asset, round_float(sz, sz_decimals), round_px(px, px_decimals)
|
|
523
523
|
|
|
524
|
-
async def
|
|
524
|
+
async def place_market_order(
|
|
525
525
|
self,
|
|
526
526
|
coin: str,
|
|
527
527
|
is_buy: bool,
|
|
528
528
|
sz: float,
|
|
529
|
-
px: float,
|
|
530
|
-
is_market: bool = True,
|
|
531
529
|
*,
|
|
532
530
|
ro: bool = False,
|
|
533
|
-
order_type: OrderType = LimitOrder.IOC.value, # type: ignore
|
|
534
531
|
cloid: Cloid | None = None,
|
|
535
532
|
slippage: float = 0.05, # Default slippage is 5%
|
|
536
533
|
builder: OrderBuilder | None = None,
|
|
537
534
|
):
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
535
|
+
mid_px = await self.get_mid_price(coin)
|
|
536
|
+
slippage_factor = (1 + slippage) if is_buy else (1 - slippage)
|
|
537
|
+
px = mid_px * slippage_factor
|
|
538
|
+
# Market order is an aggressive Limit Order IoC
|
|
539
|
+
return await self.place_typed_order(
|
|
540
|
+
coin=coin,
|
|
541
|
+
is_buy=is_buy,
|
|
542
|
+
sz=sz,
|
|
543
|
+
px=px,
|
|
544
|
+
ro=ro,
|
|
545
|
+
order_type=limit_order_type(LimitTif.IOC),
|
|
546
|
+
cloid=cloid,
|
|
547
|
+
builder=builder,
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
async def place_typed_order(
|
|
551
|
+
self,
|
|
552
|
+
coin: str,
|
|
553
|
+
is_buy: bool,
|
|
554
|
+
sz: float,
|
|
555
|
+
px: float,
|
|
556
|
+
*,
|
|
557
|
+
ro: bool = False,
|
|
558
|
+
order_type: OrderType | None = None,
|
|
559
|
+
cloid: Cloid | None = None,
|
|
560
|
+
builder: OrderBuilder | None = None,
|
|
561
|
+
):
|
|
562
|
+
if order_type is None:
|
|
563
|
+
order_type = limit_order_type(LimitTif.IOC)
|
|
544
564
|
|
|
545
565
|
asset, sz, px = await self._round_sz_px(coin, sz, px)
|
|
546
566
|
|
|
@@ -556,6 +576,42 @@ class AsyncHyperliquid(AsyncAPI):
|
|
|
556
576
|
|
|
557
577
|
return await self.place_orders([order_req], builder=builder)
|
|
558
578
|
|
|
579
|
+
async def place_order(
|
|
580
|
+
self,
|
|
581
|
+
coin: str,
|
|
582
|
+
is_buy: bool,
|
|
583
|
+
sz: float,
|
|
584
|
+
px: float,
|
|
585
|
+
is_market: bool = True,
|
|
586
|
+
*,
|
|
587
|
+
ro: bool = False,
|
|
588
|
+
order_type: OrderType | None = None,
|
|
589
|
+
cloid: Cloid | None = None,
|
|
590
|
+
slippage: float = 0.05, # Default slippage is 5%
|
|
591
|
+
builder: OrderBuilder | None = None,
|
|
592
|
+
):
|
|
593
|
+
if is_market:
|
|
594
|
+
return await self.place_market_order(
|
|
595
|
+
coin=coin,
|
|
596
|
+
is_buy=is_buy,
|
|
597
|
+
sz=sz,
|
|
598
|
+
ro=ro,
|
|
599
|
+
cloid=cloid,
|
|
600
|
+
slippage=slippage,
|
|
601
|
+
builder=builder,
|
|
602
|
+
)
|
|
603
|
+
|
|
604
|
+
return await self.place_typed_order(
|
|
605
|
+
coin=coin,
|
|
606
|
+
is_buy=is_buy,
|
|
607
|
+
sz=sz,
|
|
608
|
+
px=px,
|
|
609
|
+
ro=ro,
|
|
610
|
+
order_type=order_type,
|
|
611
|
+
cloid=cloid,
|
|
612
|
+
builder=builder,
|
|
613
|
+
)
|
|
614
|
+
|
|
559
615
|
async def place_orders(
|
|
560
616
|
self,
|
|
561
617
|
orders: list[PlaceOrderRequest],
|
|
@@ -603,7 +659,7 @@ class AsyncHyperliquid(AsyncAPI):
|
|
|
603
659
|
reqs = []
|
|
604
660
|
dexs = list(set(get_coin_dex(o["coin"]) for o in orders))
|
|
605
661
|
all_mids = await self.get_dexs_mids(dexs)
|
|
606
|
-
order_type =
|
|
662
|
+
order_type = limit_order_type(LimitTif.IOC)
|
|
607
663
|
for o in orders:
|
|
608
664
|
coin = o["coin"]
|
|
609
665
|
market_price = all_mids[coin]
|
|
@@ -1014,6 +1070,12 @@ class AsyncHyperliquid(AsyncAPI):
|
|
|
1014
1070
|
async def user_dex_abstraction(
|
|
1015
1071
|
self, user: str | None = None, enabled: bool = True
|
|
1016
1072
|
):
|
|
1073
|
+
warnings.warn(
|
|
1074
|
+
"user_dex_abstraction is deprecated and may be removed in a "
|
|
1075
|
+
"future release.",
|
|
1076
|
+
DeprecationWarning,
|
|
1077
|
+
stacklevel=2,
|
|
1078
|
+
)
|
|
1017
1079
|
nonce = get_timestamp_ms()
|
|
1018
1080
|
if user is None:
|
|
1019
1081
|
user = self.address
|
|
@@ -1028,30 +1090,44 @@ class AsyncHyperliquid(AsyncAPI):
|
|
|
1028
1090
|
)
|
|
1029
1091
|
return await self.exchange.post_action_with_sig(action, sig, nonce)
|
|
1030
1092
|
|
|
1031
|
-
async def agent_enable_dex_abstraction(self):
|
|
1032
|
-
action = {"type": "agentEnableDexAbstraction"}
|
|
1033
|
-
return await self.exchange.post_action(
|
|
1034
|
-
action, vault=self.vault, expires=self.expires
|
|
1035
|
-
)
|
|
1036
|
-
|
|
1037
1093
|
async def user_set_abstraction(
|
|
1038
|
-
self, abstraction:
|
|
1094
|
+
self, abstraction: UserSetAbstraction, user: str | None = None
|
|
1039
1095
|
):
|
|
1040
|
-
if address is None:
|
|
1041
|
-
address = self.address
|
|
1042
|
-
|
|
1043
1096
|
nonce = get_timestamp_ms()
|
|
1097
|
+
if user is None:
|
|
1098
|
+
user = self.address
|
|
1099
|
+
if re.fullmatch(r"0x[a-fA-F0-9]{40}", user) is None:
|
|
1100
|
+
raise ValueError(
|
|
1101
|
+
f"user must be a 42-char hex address, got: {user!r}"
|
|
1102
|
+
)
|
|
1044
1103
|
action = {
|
|
1045
1104
|
"type": "userSetAbstraction",
|
|
1046
|
-
"user":
|
|
1105
|
+
"user": user.lower(),
|
|
1047
1106
|
"abstraction": abstraction,
|
|
1048
1107
|
"nonce": nonce,
|
|
1049
1108
|
}
|
|
1050
1109
|
sig = sign_user_set_abstraction_action(
|
|
1051
1110
|
self.account, action, self.is_mainnet
|
|
1052
1111
|
)
|
|
1053
|
-
|
|
1054
1112
|
return await self.exchange.post_action_with_sig(action, sig, nonce)
|
|
1055
1113
|
|
|
1114
|
+
async def agent_enable_dex_abstraction(self):
|
|
1115
|
+
warnings.warn(
|
|
1116
|
+
"agent_enable_dex_abstraction is deprecated and may be removed "
|
|
1117
|
+
"in a future release.",
|
|
1118
|
+
DeprecationWarning,
|
|
1119
|
+
stacklevel=2,
|
|
1120
|
+
)
|
|
1121
|
+
action = {"type": "agentEnableDexAbstraction"}
|
|
1122
|
+
return await self.exchange.post_action(
|
|
1123
|
+
action, vault=self.vault, expires=self.expires
|
|
1124
|
+
)
|
|
1125
|
+
|
|
1126
|
+
async def agent_set_abstraction(self, abstraction: AgentAbstraction):
|
|
1127
|
+
action = {"type": "agentSetAbstraction", "abstraction": abstraction}
|
|
1128
|
+
return await self.exchange.post_action(
|
|
1129
|
+
action, vault=self.vault, expires=self.expires
|
|
1130
|
+
)
|
|
1131
|
+
|
|
1056
1132
|
|
|
1057
1133
|
AsyncHyper = AsyncHyperliquid
|
|
@@ -4,6 +4,7 @@ from aiohttp import ClientSession
|
|
|
4
4
|
|
|
5
5
|
from async_hyperliquid.async_api import AsyncAPI
|
|
6
6
|
from async_hyperliquid.utils.types import (
|
|
7
|
+
Abstraction,
|
|
7
8
|
Depth,
|
|
8
9
|
Candles,
|
|
9
10
|
Endpoint,
|
|
@@ -183,7 +184,7 @@ class InfoAPI(AsyncAPI):
|
|
|
183
184
|
payload = {"type": "userDexAbstraction", "user": address}
|
|
184
185
|
return await self.post(payload)
|
|
185
186
|
|
|
186
|
-
async def
|
|
187
|
+
async def get_user_abstraction(self, address: str) -> Abstraction:
|
|
187
188
|
payload = {"type": "userAbstraction", "user": address}
|
|
188
189
|
return await self.post(payload)
|
|
189
190
|
|
|
@@ -8,6 +8,7 @@ from eth_utils.conversions import to_hex
|
|
|
8
8
|
from eth_account.signers.local import LocalAccount
|
|
9
9
|
|
|
10
10
|
from async_hyperliquid.utils.types import (
|
|
11
|
+
LimitTif,
|
|
11
12
|
OrderType,
|
|
12
13
|
OrderAction,
|
|
13
14
|
EncodedOrder,
|
|
@@ -15,6 +16,9 @@ from async_hyperliquid.utils.types import (
|
|
|
15
16
|
OrderBuilder,
|
|
16
17
|
SignedAction,
|
|
17
18
|
PlaceOrderRequest,
|
|
19
|
+
is_limit_order_type,
|
|
20
|
+
is_trigger_order_type,
|
|
21
|
+
limit_order_type,
|
|
18
22
|
)
|
|
19
23
|
from async_hyperliquid.utils.constants import (
|
|
20
24
|
SIGNATURE_CHAIN_ID,
|
|
@@ -27,9 +31,9 @@ from async_hyperliquid.utils.constants import (
|
|
|
27
31
|
APPROVE_BUILDER_FEE_TYPES,
|
|
28
32
|
STAKING_TRANSFER_SIGN_TYPES,
|
|
29
33
|
MULTI_SIG_ENVELOPE_SIGN_TYPES,
|
|
34
|
+
USER_SET_ABSTRACTION_SIGN_TYPES,
|
|
30
35
|
USD_CLASS_TRANSFER_SIGN_TYPES,
|
|
31
36
|
USER_DEX_ABSTRACTION_SIGN_TYPES,
|
|
32
|
-
USER_SET_ABSTRACTION_SIGN_TYPES,
|
|
33
37
|
CONVERT_TO_MULTI_SIG_USER_SIGN_TYPES,
|
|
34
38
|
)
|
|
35
39
|
|
|
@@ -114,9 +118,9 @@ def round_float(x: float) -> str:
|
|
|
114
118
|
|
|
115
119
|
|
|
116
120
|
def ensure_order_type(order_type: OrderType) -> OrderType:
|
|
117
|
-
if
|
|
118
|
-
return
|
|
119
|
-
|
|
121
|
+
if is_limit_order_type(order_type):
|
|
122
|
+
return limit_order_type(LimitTif(order_type["limit"]["tif"]))
|
|
123
|
+
if is_trigger_order_type(order_type):
|
|
120
124
|
return {
|
|
121
125
|
"trigger": {
|
|
122
126
|
"isMarket": order_type["trigger"]["isMarket"],
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
-
from typing import Any, Literal, TypedDict
|
|
2
|
+
from typing import Any, Literal, TypeGuard, TypedDict
|
|
3
3
|
|
|
4
4
|
from typing_extensions import NotRequired
|
|
5
5
|
|
|
@@ -47,12 +47,22 @@ class LimitOrderType(TypedDict):
|
|
|
47
47
|
limit: LimitOrderOptions
|
|
48
48
|
|
|
49
49
|
|
|
50
|
+
class LimitTif(str, Enum):
|
|
51
|
+
ALO = "Alo"
|
|
52
|
+
IOC = "Ioc"
|
|
53
|
+
GTC = "Gtc"
|
|
54
|
+
|
|
55
|
+
|
|
50
56
|
class LimitOrder(Enum):
|
|
51
57
|
ALO = {"limit": {"tif": "Alo"}}
|
|
52
58
|
IOC = {"limit": {"tif": "Ioc"}}
|
|
53
59
|
GTC = {"limit": {"tif": "Gtc"}}
|
|
54
60
|
|
|
55
61
|
|
|
62
|
+
def limit_order_type(tif: LimitTif) -> LimitOrderType:
|
|
63
|
+
return {"limit": {"tif": tif.value}}
|
|
64
|
+
|
|
65
|
+
|
|
56
66
|
class TriggerOrderOptions(TypedDict):
|
|
57
67
|
isMarket: bool
|
|
58
68
|
triggerPx: str
|
|
@@ -63,9 +73,39 @@ class TriggerOrderType(TypedDict):
|
|
|
63
73
|
trigger: TriggerOrderOptions
|
|
64
74
|
|
|
65
75
|
|
|
76
|
+
class TriggerTpsl(str, Enum):
|
|
77
|
+
TP = "tp"
|
|
78
|
+
SL = "sl"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def trigger_order_type(
|
|
82
|
+
*, is_market: bool, trigger_px: float | str, tpsl: TriggerTpsl
|
|
83
|
+
) -> TriggerOrderType:
|
|
84
|
+
return {
|
|
85
|
+
"trigger": {
|
|
86
|
+
"isMarket": is_market,
|
|
87
|
+
"triggerPx": str(trigger_px),
|
|
88
|
+
"tpsl": tpsl.value,
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
66
93
|
OrderType = LimitOrderType | TriggerOrderType
|
|
67
94
|
|
|
68
95
|
GroupOptions = Literal["na", "normalTpsl", "positionTpsl"]
|
|
96
|
+
Abstraction = Literal[
|
|
97
|
+
"unifiedAccount", "portfolioMargin", "disabled", "default", "dexAbstraction"
|
|
98
|
+
]
|
|
99
|
+
UserSetAbstraction = Literal["disabled", "unifiedAccount", "portfolioMargin"]
|
|
100
|
+
AgentAbstraction = Literal["i", "u", "p"]
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def is_limit_order_type(order_type: OrderType) -> TypeGuard[LimitOrderType]:
|
|
104
|
+
return "limit" in order_type and "trigger" not in order_type
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def is_trigger_order_type(order_type: OrderType) -> TypeGuard[TriggerOrderType]:
|
|
108
|
+
return "trigger" in order_type and "limit" not in order_type
|
|
69
109
|
|
|
70
110
|
|
|
71
111
|
class BasicPlaceOrderRequest(TypedDict):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/utils/__init__.py
RENAMED
|
File without changes
|
{async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/utils/constants.py
RENAMED
|
File without changes
|
{async_hyperliquid-0.3.10 → async_hyperliquid-0.4.0}/src/async_hyperliquid/utils/decorators.py
RENAMED
|
File without changes
|
|
File without changes
|