fix: prevent panics from unsafe type assertions in trading code + add request body limit

Security & Reliability:
- Add requestBodyLimitMiddleware (1MB) to prevent OOM from oversized API payloads
- Fix defer resp.Body.Close() inside loop in getPublicIPFromAPI (connection leak)
- Add posFloat64/posString safe helpers for position map access

Panic Prevention (critical for trading):
- Convert 30+ unsafe type assertions (pos["key"].(type)) to safe comma-ok
  pattern across all exchange traders: OKX, Hyperliquid, Aster, Bybit,
  KuCoin, Gate, Bitget, Binance
- Fix auto_trader_risk.go: drawdown monitor could panic and silently stop
  monitoring, leaving positions unprotected
- Fix auto_trader_decision.go & auto_trader_loop.go: core trading loop
  position parsing now crash-proof
- All trader/ code now has zero unsafe type assertions

Frontend:
- Fix config.ts: rejected promise cached forever on network error (never retries)
This commit is contained in:
shinchan-zhai
2026-03-23 12:01:44 +08:00
parent 44d1ef42ad
commit acc52f2cf7
16 changed files with 101 additions and 56 deletions

View File

@@ -188,11 +188,11 @@ func (t *OKXTrader) CloseLong(symbol string, quantity float64) (map[string]inter
for _, pos := range positions {
logger.Infof("🔍 OKX position: symbol=%v, side=%v, positionAmt=%v, mgnMode=%v", pos["symbol"], pos["side"], pos["positionAmt"], pos["mgnMode"])
if pos["symbol"] == symbol {
side := pos["side"].(string)
side, _ := pos["side"].(string)
// In net_mode, "long" means positive position
// In dual mode, check explicit "long" side
if side == "long" || (t.positionMode == "net_mode" && side == "long") {
actualQty = pos["positionAmt"].(float64)
actualQty, _ = pos["positionAmt"].(float64)
posFound = true
if mgnMode, ok := pos["mgnMode"].(string); ok && mgnMode != "" {
posMgnMode = mgnMode
@@ -300,7 +300,7 @@ func (t *OKXTrader) CloseShort(symbol string, quantity float64) (map[string]inte
logger.Infof("🔍 OKX position: symbol=%v, side=%v, positionAmt=%v, mgnMode=%v",
pos["symbol"], pos["side"], pos["positionAmt"], pos["mgnMode"])
if pos["symbol"] == symbol && pos["side"] == "short" {
actualQty = pos["positionAmt"].(float64)
actualQty, _ = pos["positionAmt"].(float64)
posFound = true
if mgnMode, ok := pos["mgnMode"].(string); ok && mgnMode != "" {
posMgnMode = mgnMode