package exchange import ( "encoding/json" "log" "strconv" "time" ) type HyperLiquidWS struct { Tracked []string } type hlAllMidsMsg struct { Channel string `json:"channel"` Data json.RawMessage `json:"data"` } type hlMidsData struct { Mids map[string]string `json:"mids"` } func NewHyperLiquidWS(tracked []string) *HyperLiquidWS { return &HyperLiquidWS{Tracked: tracked} } // Run connects to HyperLiquid WS and streams mid prices. func (h *HyperLiquidWS) Run(updateFn func(coin string, price, bid, ask float64)) error { conn := NewPriceConnector("wss://api.hyperliquid.xyz/ws", "HyperLiquid", 120*time.Second, 30*time.Second) conn.PingInterval = 45 * time.Second conn.OnConnect = func() { log.Printf("[HL WS] Connected") sub := map[string]interface{}{ "method": "subscribe", "subscription": map[string]string{ "type": "allMids", }, } if err := conn.SendJSON(sub); err != nil { log.Printf("[HL WS] Subscribe error: %v", err) } } conn.OnMessage = func(msg []byte) { var raw hlAllMidsMsg if err := json.Unmarshal(msg, &raw); err != nil { return } if raw.Channel != "allMids" { return } var data hlMidsData if err := json.Unmarshal(raw.Data, &data); err != nil { return } for coin, priceStr := range data.Mids { price, err := strconv.ParseFloat(priceStr, 64) if err != nil || price <= 0 { continue } updateFn(coin, price, 0, 0) } } return conn.Run() }