Every StartOrderSync spawned a ticker goroutine that ran forever — it
survived trader stop AND deletion, so each quick-created trader left a
permanent 30s Hyperliquid poll behind. Stacked leaks turned into an
~8s effective hammer that tripped Hyperliquid's 429 rate limit, which
then broke the symbol board, trader creation, and order sync itself.
- new trader/syncloop package: shared stoppable sync loop with
exponential failure backoff (30s base, 5min cap)
- all 9 exchanges' StartOrderSync now take the trader's stop channel
and stop when the trader stops (close broadcast from AutoTrader.Stop)
- provider/hyperliquid: GetPerpDexCoins now serves a 5min TTL cache and
falls back to the stale board when the upstream returns 429, so the
symbol panel keeps working through rate limiting
go-hyperliquid's NewExchange auto-fetches meta/spotMeta/perpDexs and
panics if any of those API calls fail (NewInfo: panic(err)). The quick
trade flow constructs a probe trader inside POST /api/traders, so any
transient Hyperliquid API hiccup crashed the request with a recovered
panic and a bare 500. Wrap the constructor in initExchangeClient, which
converts the panic into an error that surfaces through the existing
exchange-probe validation path as an honest, retryable message.
- marginOverheadFactor/takerFeeRate/positionSizeSafetyFactor in sizing math
- aggressiveBuyPriceFactor/aggressiveSellPriceFactor in hyperliquid and aster
simulated market orders
- dustQuantityEpsilon in FIFO position rebuild
- binance/bybit/gate: SDK default http.DefaultClient has no timeout; use a
dedicated 30s-timeout client so a hung connection cannot stall the loop
- bybit: stop mutating http.DefaultClient.Transport, which leaked the
referer header into every other HTTP request in the process
- add types.ParseFloatField: empty exchange fields stay zero, but malformed
numeric values now surface as errors instead of silently becoming zero
balances (applied to GetBalance across 8 exchanges)
- wrap order/market-data errors in auto_trader_orders and okx cancel paths
with symbol context; log per-order cancel failures in okx CancelAllOrders
The Hyperliquid wallet-connect flow signs configuration values that
must match what the server expects and what the order placement layer
sends on-chain. The same constants live in four call sites:
- trader/hyperliquid/trader.go (used at order placement)
- api/handler_hyperliquid_wallet.go (returned by the connect endpoint
and validated on submit)
- web/src/components/common/HyperliquidWalletConnect.tsx
(signed by the user during connect)
- trader/hyperliquid/builder_fee_test.go
(pins the trader-side value)
Refresh all four together so the surfaces stay in lockstep.
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.
- Add Hyperliquid/XYZ symbol normalization tests and backend coverage
- Extend kline and market data lookup paths for US stock symbols
- Wire frontend data API types for stock-oriented market requests
This PR adds support for Hyperliquid's Unified Account mode where Spot USDC
balance can be used as collateral for Perpetual trading.
Changes:
- Add HyperliquidUnifiedAcct field to Exchange config (default: true)
- Update HyperliquidTrader to support unified account mode
- When enabled, Spot USDC balance is added to available trading balance
- Update API request/response structs for unified account toggle
- Update trader config propagation from exchange config
This aligns with Hyperliquid's roadmap to make Unified Account the default.
Gate.io Integration:
- Add Gate trader with full Trader interface implementation
- Add order_sync.go for background trade synchronization
- Fix quantity display (convert contracts to actual tokens via quanto_multiplier)
- Fix fill price return in OpenLong/OpenShort/CloseLong/CloseShort
- Add Gate-specific CoinAnk K-line data source support
- Add Gate to supported exchanges in frontend and backend
- Add Gate/KuCoin logo SVG icons
Trader Package Refactoring:
- Move exchange-specific code into subdirectories (binance/, bybit/, okx/, bitget/, hyperliquid/, aster/, lighter/, gate/)
- Create types/ package for shared types to avoid circular dependencies
- Move TraderTestSuite to trader/testutil package to avoid import cycles
- Update market.GetWithExchange to support exchange-specific data