Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Trade perpetual futures and spot tokens on Hyperliquid DEX with 18 tools for orders, positions, funding, and USDC transfers.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
exports.py
1"""2Hyperliquid skill exports — read-only tools, sync via requests.34Bypasses the async client entirely. Uses direct POST to /info endpoint.5Wallet address resolved via Fly OIDC → wallet-service.67Write operations (hl_order, hl_cancel, etc.) are NOT exported — they require8the agent's signing pipeline. Use /chat/stream to invoke those from task scripts.910Usage in task scripts:11from core.skill_tools import hyperliquid12account = hyperliquid.hl_account()13mids = hyperliquid.hl_market()14candles = hyperliquid.hl_candles(coin="BTC", interval="1h", hours_back=24)15"""16import os17import json18import time19import http.client20import socket21import requests2223HL_API = os.environ.get("HYPERLIQUID_API_URL", "https://api.hyperliquid.xyz")24FLY_API_SOCKET = "/.fly/api"25WALLET_SERVICE_URL = os.environ.get("WALLET_SERVICE_URL", "https://wallet-service-dev.fly.dev")26OIDC_AUDIENCE = os.environ.get("WALLET_OIDC_AUDIENCE", WALLET_SERVICE_URL)2728_cached_address = None293031def _get_oidc_token():32"""Get OIDC token from Fly unix socket."""33conn = http.client.HTTPConnection("localhost")34conn.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)35conn.sock.connect(FLY_API_SOCKET)36body = json.dumps({"aud": OIDC_AUDIENCE}).encode()37conn.request("POST", "/v1/tokens/oidc", body=body,38headers={"Host": "localhost", "Content-Type": "application/json"})39resp = conn.getresponse()40token = resp.read().decode().strip()41conn.close()42return token434445def _get_address():46"""Get agent's EVM wallet address (cached)."""47global _cached_address48if _cached_address:49return _cached_address50if not os.path.exists(FLY_API_SOCKET):51raise RuntimeError("Not on Fly machine — wallet unavailable")52token = _get_oidc_token()53r = requests.get(f"{WALLET_SERVICE_URL}/agent/wallet",54headers={"Authorization": f"Bearer {token}"}, timeout=15)55r.raise_for_status()56data = r.json()57for w in (data if isinstance(data, list) else data.get("wallets", [])):58if w.get("chain_type") == "ethereum":59_cached_address = w["wallet_address"]60return _cached_address61raise RuntimeError("No ethereum wallet found")626364def _info(req_type, **kwargs):65"""POST to Hyperliquid /info endpoint."""66payload = {"type": req_type, **kwargs}67r = requests.post(f"{HL_API}/info", json=payload, timeout=15)68r.raise_for_status()69data = r.json()70if isinstance(data, dict) and data.get("status") == "err":71raise Exception(f"Hyperliquid error: {data.get('response', data)}")72return data737475# ── Exported read-only tools (names match SKILL.md) ──767778def hl_account(dex=None):79"""Get perp account state: positions, margin, PnL."""80addr = _get_address()81if dex:82return _info("clearinghouseState", user=addr, dex=dex)83return _info("clearinghouseState", user=addr)848586def hl_balances():87"""Get spot token balances."""88return _info("spotClearinghouseState", user=_get_address())899091def hl_open_orders():92"""Get all open orders."""93return _info("openOrders", user=_get_address())949596def hl_market(dex=None):97"""Get current mid prices for all assets."""98if dex:99return _info("allMids", dex=dex)100return _info("allMids")101102103def hl_orderbook(coin):104"""Get L2 orderbook snapshot for a coin."""105return _info("l2Book", coin=coin)106107108def hl_fills():109"""Get recent trade fills for this wallet."""110return _info("userFills", user=_get_address())111112113def hl_candles(coin, interval="1h", hours_back=24, start=None, end=None):114"""Get OHLCV candlestick data.115116Args:117coin: e.g. "BTC", "ETH"118interval: "1m","5m","15m","1h","4h","1d"119hours_back: lookback period in hours (default 24)120start/end: explicit timestamps in ms (override hours_back)121"""122if end is None:123end = int(time.time() * 1000)124if start is None:125start = end - hours_back * 3600 * 1000126return _info("candleSnapshot", req={"coin": coin, "interval": interval, "startTime": start, "endTime": end})127128129def hl_funding(coin, hours_back=24, start=None):130"""Get historical funding rates for a coin.131132Args:133coin: e.g. "BTC"134hours_back: lookback in hours (default 24)135start: explicit start timestamp in ms (overrides hours_back)136"""137if start is None:138start = int((time.time() - hours_back * 3600) * 1000)139return _info("fundingHistory", coin=coin, startTime=start)140141142def hl_predicted_funding():143"""Get predicted next funding rates for all assets."""144return _info("predictedFundings")145146147def hl_order_status(oid):148"""Look up a single order by oid."""149return _info("orderStatus", user=_get_address(), oid=oid)150151152def hl_user_fees():153"""Get user fee schedule."""154return _info("userFees", user=_get_address())155