- config.json: test_mode=false, ready for sim/testnet trading - trader.go: auto-stop after 5 real trades, exchange response logging, Stop()/Start() API, shuttingDown flag for graceful stop - dashboard.go: POST /api/stop + POST /api/start endpoints, trading status in SSE stats - exchange/hyperliquid.go: switch HL WS to testnet endpoint - exchange/hyperliquid_trade.go: switch REST to testnet endpoint, support base64 + 32-byte EVM private keys - main.go: listen on trader.StopCh (graceful, no process exit) - scanner.go: trim TrackedCoins to only 6 core coins (DOGE/LINK/ONDO/OP/WIF/ARB) - .gitignore: ignore main binary
67 lines
1.4 KiB
Go
67 lines
1.4 KiB
Go
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-testnet.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()
|
|
}
|