fix: division-by-zero guard, rate-limit wallet endpoints, safer JSON parse, Lighter HTTP checks

- Guard GridCount-1 division by zero in grid spacing calculation (both grid.go and grid_levels.go)
- Rate-limit /wallet/validate and /wallet/generate endpoints (prevent DoS on key generation)
- Wrap JSON.parse(localStorage) in try-catch in AuthContext (corrupted data → graceful re-login)
- Wrap handleJSONResponse JSON.parse in try-catch with descriptive error
- Add HTTP status code checks for Lighter GetActiveOrders and sendTx
- Replace deprecated strings.Title with cases.Title (golang.org/x/text)
- Reuse HTTP client in checkClaw402Health (was creating new client per call)
This commit is contained in:
shinchan-zhai
2026-03-23 16:47:23 +08:00
parent c014724896
commit abb43c8c68
9 changed files with 64 additions and 17 deletions

View File

@@ -326,8 +326,12 @@ func (at *AutoTrader) InitializeGrid() error {
at.gridState.LowerPrice = gridConfig.LowerPrice
}
// Calculate grid spacing
at.gridState.GridSpacing = (at.gridState.UpperPrice - at.gridState.LowerPrice) / float64(gridConfig.GridCount-1)
// Calculate grid spacing (guard against division by zero when GridCount <= 1)
if gridConfig.GridCount > 1 {
at.gridState.GridSpacing = (at.gridState.UpperPrice - at.gridState.LowerPrice) / float64(gridConfig.GridCount-1)
} else {
at.gridState.GridSpacing = 0
}
// Initialize grid levels
at.initializeGridLevels(price, gridConfig)

View File

@@ -295,7 +295,12 @@ func (at *AutoTrader) autoAdjustGrid() {
}
// Recalculate grid spacing based on new bounds
at.gridState.GridSpacing = (at.gridState.UpperPrice - at.gridState.LowerPrice) / float64(gridConfig.GridCount-1)
// Guard against division by zero when GridCount <= 1
if gridConfig.GridCount > 1 {
at.gridState.GridSpacing = (at.gridState.UpperPrice - at.gridState.LowerPrice) / float64(gridConfig.GridCount-1)
} else {
at.gridState.GridSpacing = 0
}
logger.Infof("[Grid] New bounds: $%.2f - $%.2f, spacing: $%.2f",
at.gridState.LowerPrice, at.gridState.UpperPrice, at.gridState.GridSpacing)

View File

@@ -246,6 +246,14 @@ func (t *LighterTraderV2) GetActiveOrders(symbol string) ([]OrderResponse, error
return nil, fmt.Errorf("failed to read response: %w", err)
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
snippet := string(body)
if len(snippet) > 512 {
snippet = snippet[:512] + "..."
}
return nil, fmt.Errorf("GetActiveOrders API HTTP error (status %d): %s", resp.StatusCode, snippet)
}
logger.Debugf("📋 LIGHTER GetActiveOrders raw response: %s", string(body))
// Parse response - Lighter API uses "orders" field, not "data"

View File

@@ -394,6 +394,14 @@ func (t *LighterTraderV2) submitOrder(txType int, txInfo string) (map[string]int
return nil, err
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
snippet := string(respBody)
if len(snippet) > 512 {
snippet = snippet[:512] + "..."
}
return nil, fmt.Errorf("Lighter sendTx HTTP error (status %d): %s", resp.StatusCode, snippet)
}
// Parse response
var sendResp SendTxResponse
if err := json.Unmarshal(respBody, &sendResp); err != nil {