mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-06-06 05:51:19 +08:00
fix(hyperliquid): bump go-hyperliquid v0.26 -> v0.36 to dodge spot-meta panic
go-hyperliquid v0.26.0 crashed at startup with
panic: runtime error: index out of range [479] with length 464
github.com/sonirico/go-hyperliquid.NewInfo (info.go:75)
NewExchange -> NewHyperliquidTrader -> AutoTrader.NewAutoTrader
-> TraderManager.LoadTradersFromStore -> main.main
The library's NewInfo built the spot-asset map by indexing
`spotMeta.Tokens[spotInfo.Tokens[0]]` directly, but Hyperliquid recently
added spot tokens whose Tokens[0] value (a logical token *index*, not an
array position) was larger than the Tokens slice length. With every
restart the backend panicked before the API server bound, so the
frontend's `/api/*` proxy got connection refused on every poll and the
dashboard rendered "全是 error" toasts.
v0.36 fixes the panic by building `tokensByIndex map[int]SpotTokenInfo`
and looking up by logical index instead of position. Adopting v0.36
required two small adaptations to our wrapper:
- trader/hyperliquid/trader.go: NewExchange grew an extra `perpDexs
*MixedArray` argument. Passing `nil` keeps the existing
"auto-fetch on first use" behavior.
- trader/hyperliquid/trader_sync.go: `Info.NameToAsset(coin) int` was
renamed to `Info.CoinToAsset(coin) (int, bool)` with an `ok` flag.
refreshMetaIfNeeded now treats `!ok || assetID == 0` as "needs
refresh" (the same semantic as the old `assetID == 0`).
Verified: backend rebuilds cleanly, container is healthy, all
Hyperliquid traders load, AI cycles execute, and Hyperliquid order
sync receives the full historical trade window.
This commit is contained in:
16
go.mod
16
go.mod
@@ -18,7 +18,7 @@ require (
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/rs/zerolog v1.34.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/sonirico/go-hyperliquid v0.26.0
|
||||
github.com/sonirico/go-hyperliquid v0.36.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
golang.org/x/crypto v0.51.0
|
||||
golang.org/x/net v0.55.0
|
||||
@@ -66,7 +66,7 @@ require (
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.1 // indirect
|
||||
github.com/mailru/easyjson v0.9.2 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.32 // indirect
|
||||
@@ -76,21 +76,21 @@ require (
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/procfs v0.17.0 // indirect
|
||||
github.com/prometheus/procfs v0.19.2 // indirect
|
||||
github.com/quic-go/qpack v0.6.0 // indirect
|
||||
github.com/quic-go/quic-go v0.59.1 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/sonirico/vago v0.10.0 // indirect
|
||||
github.com/sonirico/vago/lol v0.0.0-20250901170347-2d1d82c510bd // indirect
|
||||
github.com/sonirico/vago v0.11.4 // indirect
|
||||
github.com/sonirico/vago/lol v0.1.0 // indirect
|
||||
github.com/supranational/blst v0.3.16 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.3.0 // indirect
|
||||
github.com/valyala/fastjson v1.6.7 // indirect
|
||||
github.com/valyala/fastjson v1.6.10 // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
go.elastic.co/apm/module/apmzerolog/v2 v2.7.1 // indirect
|
||||
go.elastic.co/apm/v2 v2.7.1 // indirect
|
||||
go.elastic.co/apm/module/apmzerolog/v2 v2.7.2 // indirect
|
||||
go.elastic.co/apm/v2 v2.7.2 // indirect
|
||||
go.elastic.co/fastjson v1.5.1 // indirect
|
||||
golang.org/x/arch v0.20.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
||||
|
||||
36
go.sum
36
go.sum
@@ -136,8 +136,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mailru/easyjson v0.9.1 h1:LbtsOm5WAswyWbvTEOqhypdPeZzHavpZx96/n553mR8=
|
||||
github.com/mailru/easyjson v0.9.1/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mailru/easyjson v0.9.2 h1:dX8U45hQsZpxd80nLvDGihsQ/OxlvTkVUXH2r/8cb2M=
|
||||
github.com/mailru/easyjson v0.9.2/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
@@ -165,8 +165,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
|
||||
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
|
||||
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
|
||||
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
|
||||
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||
github.com/quic-go/quic-go v0.59.1 h1:0Gmua0HW1Tv7ANR7hUYwRyD0MG5OJfgvYSZasGZzBic=
|
||||
@@ -186,17 +186,17 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/sonirico/go-hyperliquid v0.26.0 h1:C2KjaD2R/AxH1FOPl6W1LyvAx/XUHdTQYgjb4PUcPN0=
|
||||
github.com/sonirico/go-hyperliquid v0.26.0/go.mod h1:SYzazq5hqC8lI1+MgSO0aJVrf0TAfyibp5NjUqnwv2I=
|
||||
github.com/sonirico/vago v0.10.0 h1:y+4Wo56tK+88a5lUwVrZUO2RRLaPcBgjI5cupKpT1Oc=
|
||||
github.com/sonirico/vago v0.10.0/go.mod h1:HCfnyPHId7V+zBZ5BLfIsdHIO+ewo6+uhF1N0hxlldc=
|
||||
github.com/sonirico/vago/lol v0.0.0-20250901170347-2d1d82c510bd h1:rbvNORW8/0AtH/8W/SUwUykbuh2SeQBrNgFLqYpGTWY=
|
||||
github.com/sonirico/vago/lol v0.0.0-20250901170347-2d1d82c510bd/go.mod h1:pteYccB32seEf19i0TPk7DKdEZdWJ/n9K9DF8AFeXGU=
|
||||
github.com/sonirico/go-hyperliquid v0.36.0 h1:97aNCFf7PbvXtpCh+kdpqlAmLCyu4vB/USaKL73mSB8=
|
||||
github.com/sonirico/go-hyperliquid v0.36.0/go.mod h1:6UkIfvbqOPtCNcdC2TQ7vVPy5k8pqgoMucbGep4gCuY=
|
||||
github.com/sonirico/vago v0.11.4 h1:KlKh5iYYxKii1bhReKDIE10LPz/GPPqAcn4EvZl4t54=
|
||||
github.com/sonirico/vago v0.11.4/go.mod h1:HCfnyPHId7V+zBZ5BLfIsdHIO+ewo6+uhF1N0hxlldc=
|
||||
github.com/sonirico/vago/lol v0.1.0 h1:YjI+JAQ6enMYlpoM23w6J+1b11TJ8rqPpuD2NDHdFlA=
|
||||
github.com/sonirico/vago/lol v0.1.0/go.mod h1:k8CVrcWhKbPSX5821lt8L64z/DaST2TUaxiJOdPaSA0=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4=
|
||||
github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
@@ -214,16 +214,16 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
||||
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||
github.com/valyala/fastjson v1.6.7 h1:ZE4tRy0CIkh+qDc5McjatheGX2czdn8slQjomexVpBM=
|
||||
github.com/valyala/fastjson v1.6.7/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||
github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4=
|
||||
github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE=
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||
go.elastic.co/apm/module/apmzerolog/v2 v2.7.1 h1:C9+KrlqS8F4SZFu+ct0Jmv2YLmzDhWsI8htK6exd3vg=
|
||||
go.elastic.co/apm/module/apmzerolog/v2 v2.7.1/go.mod h1:wXViB7paxMUrERgZrmUb+0FCqgb13Dull1JOOd8Hcj0=
|
||||
go.elastic.co/apm/v2 v2.7.1 h1:OFjARuESjBsxw7wHrEAnfSVNCHGBATXSI/kPvBARY/A=
|
||||
go.elastic.co/apm/v2 v2.7.1/go.mod h1:tQhBAjwh93b2leuAdzGwta/sP7Yc7QoKTSjeIHHDuog=
|
||||
go.elastic.co/apm/module/apmzerolog/v2 v2.7.2 h1:JPgmhFEUDfjvIrfZdWEgkwu5H2Nzhze6GFan+qoUQYo=
|
||||
go.elastic.co/apm/module/apmzerolog/v2 v2.7.2/go.mod h1:oQIxTgTMMef1FgFghymN+GCXpWhW6rpQRihV8Gjoi+w=
|
||||
go.elastic.co/apm/v2 v2.7.2 h1:0blxpxOMOcpBTz034RBqvEw806y0CDJwo/ut+2wZsHA=
|
||||
go.elastic.co/apm/v2 v2.7.2/go.mod h1:KJcwwsaouDzcLd8EviAO+y8yrfZzD6PhUCEg82bvLV4=
|
||||
go.elastic.co/fastjson v1.5.1 h1:zeh1xHrFH79aQ6Xsw7YxixvnOdAl3OSv0xch/jRDzko=
|
||||
go.elastic.co/fastjson v1.5.1/go.mod h1:WtvH5wz8z9pDOPqNYSYKoLLv/9zCWZLeejHWuvdL/EM=
|
||||
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
|
||||
|
||||
@@ -133,15 +133,21 @@ func NewHyperliquidTrader(privateKeyHex string, walletAddr string, testnet bool,
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Create Exchange client (Exchange includes Info functionality)
|
||||
// Create Exchange client (Exchange includes Info functionality).
|
||||
// v0.36 signature: ctx, privateKey, baseURL, meta, vaultAddr, accountAddr,
|
||||
// spotMeta, perpDexs, ...opts. nil values are auto-fetched on first use.
|
||||
// v0.36 fixed the spot-meta indexing panic that crashed earlier versions
|
||||
// when Hyperliquid added new spot tokens whose Tokens[0] index pointed
|
||||
// past the Tokens array end.
|
||||
exchange := hyperliquid.NewExchange(
|
||||
ctx,
|
||||
privateKey,
|
||||
apiURL,
|
||||
nil, // Meta will be fetched automatically
|
||||
nil, // Meta — fetched automatically
|
||||
"", // vault address (empty for personal account)
|
||||
walletAddr, // wallet address
|
||||
nil, // SpotMeta will be fetched automatically
|
||||
nil, // SpotMeta — fetched automatically
|
||||
nil, // perpDexs — fetched automatically
|
||||
)
|
||||
|
||||
logger.Infof("✓ Hyperliquid trader initialized successfully (testnet=%v, wallet=%s)", testnet, walletAddr)
|
||||
|
||||
@@ -11,10 +11,14 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// refreshMetaIfNeeded refreshes meta information when invalid (triggered when Asset ID is 0)
|
||||
// refreshMetaIfNeeded refreshes meta information when invalid (triggered when Asset ID is 0).
|
||||
//
|
||||
// NOTE: go-hyperliquid v0.27 renamed `NameToAsset(coin) int` to
|
||||
// `CoinToAsset(coin) (int, bool)` — the second return is `ok` for whether
|
||||
// the coin exists in the meta cache. We treat `!ok` (or zero asset for a
|
||||
// perp) as "need refresh" the same way the old code did.
|
||||
func (t *HyperliquidTrader) refreshMetaIfNeeded(coin string) error {
|
||||
assetID := t.exchange.Info().NameToAsset(coin)
|
||||
if assetID != 0 {
|
||||
if assetID, ok := t.exchange.Info().CoinToAsset(coin); ok && assetID != 0 {
|
||||
return nil // Meta is normal, no refresh needed
|
||||
}
|
||||
|
||||
@@ -34,8 +38,8 @@ func (t *HyperliquidTrader) refreshMetaIfNeeded(coin string) error {
|
||||
logger.Infof("✅ Meta information refreshed, contains %d assets", len(meta.Universe))
|
||||
|
||||
// Verify Asset ID after refresh
|
||||
assetID = t.exchange.Info().NameToAsset(coin)
|
||||
if assetID == 0 {
|
||||
assetID, ok := t.exchange.Info().CoinToAsset(coin)
|
||||
if !ok || assetID == 0 {
|
||||
return fmt.Errorf("❌ Even after refreshing Meta, Asset ID for %s is still 0. Possible reasons:\n"+
|
||||
" 1. This coin is not listed on Hyperliquid\n"+
|
||||
" 2. Coin name is incorrect (should be BTC not BTCUSDT)\n"+
|
||||
|
||||
Reference in New Issue
Block a user