Skip to content

spot_meta_and_asset_ctxs doesn't inject dex into the payload #257

Description

@satwikkansal
    def spot_meta_and_asset_ctxs(self) -> SpotMetaAndAssetCtxs:
        """Retrieve exchange spot asset contexts
        POST /info
        Returns:
            [
                {
                    universe: [
                        {
                            tokens: [int, int],
                            name: str,
                            index: int,
                            isCanonical: bool
                        },
                        ...
                    ],
                    tokens: [
                        {
                            name: str,
                            szDecimals: int,
                            weiDecimals: int,
                            index: int,
                            tokenId: str,
                            isCanonical: bool
                        },
                        ...
                    ]
                },
                [
                    {
                        dayNtlVlm: float string,
                        markPx: float string,
                        midPx: Optional(float string),
                        prevDayPx: float string,
                        circulatingSupply: float string,
                        coin: str
                    }
                    ...
                ]
            ]
        """
        return cast(SpotMetaAndAssetCtxs, self.post("/info", {"type": "spotMetaAndAssetCtxs"}))

While the Info class supports perp_dexs constructor argument, when I fetch spot_meta_and_asset_ctxs the dex is not passed in the payload, nor the method supports a dex argument

Activity

  1. added a commit that references this issue on Mar 2, 2026
    8e7c28b
  2. massimiliano1991 commented on Sep 5, 2026

    @massimiliano1991

    I looked into this and measured it live today (2026-09-05, mainnet). The short version: the API ignores dex on spotMetaAndAssetCtxs, so injecting it into the payload would be a silent no-op rather than a fix. The reason is that HIP-3 partitions perp markets, not spot.

    Spot is not dex-partitioned — verified. The response is structurally identical whether dex is absent, empty, a made-up string, or a real HIP-3 dex name:

    import json, urllib.request
    def post(p):
        r = urllib.request.Request("https://api.hyperliquid.xyz/info",
            data=json.dumps(p).encode(), headers={"Content-Type": "application/json"})
        return json.load(urllib.request.urlopen(r))
    
    def structure(r):  # drop volatile prices, keep the shape
        meta, ctxs = r
        return ([(u["name"], u["index"]) for u in meta["universe"]],
                [(t["name"], t["index"]) for t in meta["tokens"]],
                sorted(c["coin"] for c in ctxs))
    
    base = structure(post({"type": "spotMetaAndAssetCtxs"}))
    for dex in ("test", "vntl"):
        same = structure(post({"type": "spotMetaAndAssetCtxs", "dex": dex})) == base
        print(f"dex={dex!r:8} identical structure: {same}")
    # dex='test'   identical structure: True
    # dex='vntl'   identical structure: True
    # universe=326  tokens=499  coins=718 in all cases

    Contrast — the perp endpoints do respond to dex, which is why the request feels natural but the analogy doesn't hold for spot:

    def uni(p): return [u["name"] for u in post(p)["universe"]]
    print(len(uni({"type": "meta"})))                       # 233  (BTC, ETH, ...)
    print(len(uni({"type": "meta", "dex": "xyz"})))         # 119  (xyz:XYZ100, xyz:TSLA, ...)
    print(len(uni({"type": "meta", "dex": "flx"})))         # 16   (flx:TSLA, ...)

    Each HIP-3 perp DEX carries its own perp universe; the global spot universe (spotMetaAndAssetCtxs) is shared and has no per-dex view to select. So dex is meaningful on the perp meta/metaAndAssetCtxs/user_state/open_orders family (that gap is being tracked in #278 and documented in #286/#320), but on spotMetaAndAssetCtxs there is nothing for it to switch.

    My suggestion: rather than add a dex argument that the API silently drops (which would mislead callers into thinking a per-dex spot view exists), it's more accurate to leave the signature as-is and, if anything, add a one-line docstring note that spot contexts are global and not dex-scoped. Happy to open that docs PR if a maintainer agrees.

    (Observed: the identical-structure and count results above, from live mainnet calls. Deduced: the HIP-3 perp-vs-spot partitioning as the cause — consistent with the perp-meta results but I haven't seen it stated in the docs.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions