async-hyperliquid 0.4.4__tar.gz → 0.4.5__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.
Files changed (20) hide show
  1. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/PKG-INFO +1 -1
  2. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/pyproject.toml +1 -1
  3. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/_async_hyperliquid/core.py +7 -0
  4. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/_async_hyperliquid/info.py +44 -4
  5. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/info.py +2 -2
  6. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/LICENSE +0 -0
  7. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/README.md +0 -0
  8. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/__init__.py +0 -0
  9. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/_async_hyperliquid/__init__.py +0 -0
  10. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/_async_hyperliquid/actions.py +0 -0
  11. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/_async_hyperliquid/orders.py +0 -0
  12. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/async_api.py +0 -0
  13. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/async_hyperliquid.py +0 -0
  14. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/exchange.py +0 -0
  15. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/utils/__init__.py +0 -0
  16. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/utils/constants.py +0 -0
  17. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/utils/decorators.py +0 -0
  18. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/utils/miscs.py +0 -0
  19. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/utils/signing.py +0 -0
  20. {async_hyperliquid-0.4.4 → async_hyperliquid-0.4.5}/src/async_hyperliquid/utils/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: async-hyperliquid
3
- Version: 0.4.4
3
+ Version: 0.4.5
4
4
  Summary: Async Hyperliquid client using aiohttp
5
5
  Keywords: dex,hyperliquid,async,aiohttp,trading,cryptocurrency,defi
6
6
  Author: Yuki
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "async-hyperliquid"
3
- version = "0.4.4"
3
+ version = "0.4.5"
4
4
  description = "Async Hyperliquid client using aiohttp"
5
5
  authors = [{ name = "Yuki", email = "yuqi.lyle@gmail.com" }]
6
6
  readme = "README.md"
@@ -164,6 +164,13 @@ class AsyncHyperliquidCore(AsyncAPI):
164
164
  }
165
165
 
166
166
  async def init_metas(self) -> None:
167
+ # TODO: Add HIP-4 outcome meta initialization from the spot info
168
+ # `outcomeMeta` endpoint once outcomes move beyond testnet-only rollout.
169
+ # Outcome asset IDs do not follow the current perp/spot offset scheme:
170
+ # `encoding = 10 * outcome + side`, coin names use `#{encoding}`, token
171
+ # names use `+{encoding}`, and `asset_id = 100_000_000 + encoding`, so
172
+ # this path will need dedicated outcome mappings instead of reusing the
173
+ # existing perp/spot logic.
167
174
  meta_task = self.info.get_perp_meta()
168
175
  spot_meta_task = self.info.get_spot_meta()
169
176
  all_dex_names_task = self.get_all_dex_name()
@@ -1,6 +1,6 @@
1
1
  import asyncio
2
2
  import warnings
3
- from typing import Literal
3
+ from typing import Literal, cast
4
4
 
5
5
  from async_hyperliquid.utils.constants import ONE_HOUR_MS, PERP_DEX_OFFSET, SPOT_OFFSET
6
6
  from async_hyperliquid.utils.miscs import get_coin_dex, get_timestamp_ms
@@ -9,9 +9,13 @@ from async_hyperliquid.utils.types import (
9
9
  AccountState,
10
10
  ClearinghouseState,
11
11
  OrderWithStatus,
12
+ PerpMeta,
13
+ PerpMetaCtxItem,
12
14
  Portfolio,
13
15
  Position,
16
+ SpotMeta,
14
17
  SpotClearinghouseState,
18
+ SpotMetaCtxItem,
15
19
  UserDeposit,
16
20
  UserNonFundingDelta,
17
21
  UserOpenOrders,
@@ -23,13 +27,49 @@ from .core import AsyncHyperliquidCore
23
27
 
24
28
 
25
29
  class AsyncHyperliquidInfoClient(AsyncHyperliquidCore):
30
+ async def _get_perp_mark_price(self, coin_name: str, dex: str = "") -> float:
31
+ meta_ctx = await self.info.get_perp_meta_ctx(dex)
32
+ meta = cast(PerpMeta, meta_ctx[0])
33
+ asset_ctxs = cast(list[PerpMetaCtxItem], meta_ctx[1])
34
+
35
+ for idx, info in enumerate(meta["universe"]):
36
+ if info["name"] == coin_name:
37
+ return float(asset_ctxs[idx]["markPx"])
38
+
39
+ raise ValueError(f"Coin {coin_name} not found in perp dex '{dex}'")
40
+
41
+ async def _get_spot_mark_price(self, coin_name: str) -> float:
42
+ meta_ctx = await self.info.get_spot_meta_ctx()
43
+ meta = cast(SpotMeta, meta_ctx[0])
44
+ asset_ctxs = cast(list[SpotMetaCtxItem], meta_ctx[1])
45
+
46
+ for info in meta["universe"]:
47
+ if info["name"] == coin_name:
48
+ asset_index = info["index"]
49
+ return float(asset_ctxs[asset_index]["markPx"])
50
+
51
+ raise ValueError(f"Coin {coin_name} not found in spot metadata")
52
+
53
+ async def get_mark_price(self, coin: str) -> float:
54
+ if ":" in coin:
55
+ return await self._get_perp_mark_price(coin, get_coin_dex(coin))
56
+
57
+ coin_name = await self.get_coin_name(coin)
58
+ if coin_name not in self.coin_assets:
59
+ raise ValueError(f"Coin {coin}({coin_name}) not found")
60
+
61
+ asset = self.coin_assets[coin_name]
62
+ is_spot_asset = SPOT_OFFSET <= asset < PERP_DEX_OFFSET
63
+ if is_spot_asset:
64
+ return await self._get_spot_mark_price(coin_name)
65
+
66
+ return await self._get_perp_mark_price(coin_name, get_coin_dex(coin_name))
67
+
26
68
  async def get_market_price(self, coin: str) -> float:
27
69
  warnings.warn(
28
70
  "get_market_price is deprecated and will remove in the future, use get_mid_price instead"
29
71
  )
30
- coin_name = await self.get_coin_name(coin)
31
- market_prices = await self.get_all_market_prices()
32
- return market_prices[coin_name]
72
+ return await self.get_mark_price(coin)
33
73
 
34
74
  async def get_all_market_prices(
35
75
  self, market: Literal["spot", "perp", "all"] = "all"
@@ -190,8 +190,8 @@ class InfoAPI(AsyncAPI):
190
190
  payload = {"type": "meta", "dex": dex}
191
191
  return await self.post(payload)
192
192
 
193
- async def get_perp_meta_ctx(self) -> PerpMetaCtx:
194
- payload = {"type": "metaAndAssetCtxs"}
193
+ async def get_perp_meta_ctx(self, dex: str = "") -> PerpMetaCtx:
194
+ payload = {"type": "metaAndAssetCtxs", "dex": dex}
195
195
  return await self.post(payload)
196
196
 
197
197
  async def get_perp_dexs(self) -> PerpDexs: