mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-05 12:00:59 +08:00
fix: sanitize API error messages to prevent sensitive info exposure
This commit is contained in:
188
api/server.go
188
api/server.go
@@ -486,7 +486,7 @@ func (s *Server) handleCreateTrader(c *gin.Context) {
|
||||
userID := c.GetString("user_id")
|
||||
var req CreateTraderRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid request parameters")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -682,7 +682,7 @@ func (s *Server) handleCreateTrader(c *gin.Context) {
|
||||
err = s.store.Trader().Create(traderRecord)
|
||||
if err != nil {
|
||||
logger.Infof("❌ Failed to create trader: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to create trader: %v", err)})
|
||||
SafeInternalError(c, "Failed to create trader", err)
|
||||
return
|
||||
}
|
||||
logger.Infof("🔧 DEBUG: CreateTrader succeeded")
|
||||
@@ -732,7 +732,7 @@ func (s *Server) handleUpdateTrader(c *gin.Context) {
|
||||
|
||||
var req UpdateTraderRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid request parameters")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -823,7 +823,7 @@ func (s *Server) handleUpdateTrader(c *gin.Context) {
|
||||
traderRecord.ID, traderRecord.Name, traderRecord.AIModelID, traderRecord.StrategyID, req.StrategyID)
|
||||
err = s.store.Trader().Update(traderRecord)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to update trader: %v", err)})
|
||||
SafeInternalError(c, "Failed to update trader", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -854,7 +854,7 @@ func (s *Server) handleDeleteTrader(c *gin.Context) {
|
||||
// Delete from database
|
||||
err := s.store.Trader().Delete(userID, traderID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to delete trader: %v", err)})
|
||||
SafeInternalError(c, "Failed to delete trader", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1012,14 +1012,14 @@ func (s *Server) handleUpdateTraderPrompt(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid request parameters")
|
||||
return
|
||||
}
|
||||
|
||||
// Update database
|
||||
err := s.store.Trader().UpdateCustomPrompt(userID, traderID, req.CustomPrompt, req.OverrideBasePrompt)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to update custom prompt: %v", err)})
|
||||
SafeInternalError(c, "Failed to update custom prompt", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1044,14 +1044,14 @@ func (s *Server) handleToggleCompetition(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid request parameters")
|
||||
return
|
||||
}
|
||||
|
||||
// Update database
|
||||
err := s.store.Trader().UpdateShowInCompetition(userID, traderID, req.ShowInCompetition)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to update competition visibility: %v", err)})
|
||||
SafeInternalError(c, "Update competition visibility", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1150,7 +1150,7 @@ func (s *Server) handleSyncBalance(c *gin.Context) {
|
||||
|
||||
if createErr != nil {
|
||||
logger.Infof("⚠️ Failed to create temporary trader: %v", createErr)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to connect to exchange: %v", createErr)})
|
||||
SafeInternalError(c, "Failed to connect to exchange", createErr)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1158,7 +1158,7 @@ func (s *Server) handleSyncBalance(c *gin.Context) {
|
||||
balanceInfo, balanceErr := tempTrader.GetBalance()
|
||||
if balanceErr != nil {
|
||||
logger.Infof("⚠️ Failed to query exchange balance: %v", balanceErr)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to query balance: %v", balanceErr)})
|
||||
SafeInternalError(c, "Failed to query balance", balanceErr)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1302,7 +1302,7 @@ func (s *Server) handleClosePosition(c *gin.Context) {
|
||||
|
||||
if createErr != nil {
|
||||
logger.Infof("⚠️ Failed to create temporary trader: %v", createErr)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to connect to exchange: %v", createErr)})
|
||||
SafeInternalError(c, "Failed to connect to exchange", createErr)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1344,7 +1344,7 @@ func (s *Server) handleClosePosition(c *gin.Context) {
|
||||
|
||||
if closeErr != nil {
|
||||
logger.Infof("❌ Close position failed: symbol=%s, side=%s, error=%v", req.Symbol, req.Side, closeErr)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to close position: %v", closeErr)})
|
||||
SafeInternalError(c, "Failed to close position", closeErr)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1582,7 +1582,7 @@ func (s *Server) handleGetModelConfigs(c *gin.Context) {
|
||||
models, err := s.store.AIModel().List(userID)
|
||||
if err != nil {
|
||||
logger.Infof("❌ Failed to get AI model configs: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to get AI model configs: %v", err)})
|
||||
SafeInternalError(c, "Failed to get AI model configs", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1684,7 +1684,7 @@ func (s *Server) handleUpdateModelConfigs(c *gin.Context) {
|
||||
for modelID, modelData := range req.Models {
|
||||
err := s.store.AIModel().Update(userID, modelID, modelData.Enabled, modelData.APIKey, modelData.CustomAPIURL, modelData.CustomModelName)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to update model %s: %v", modelID, err)})
|
||||
SafeInternalError(c, fmt.Sprintf("Update model %s", modelID), err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -1706,8 +1706,7 @@ func (s *Server) handleGetExchangeConfigs(c *gin.Context) {
|
||||
logger.Infof("🔍 Querying exchange configs for user %s", userID)
|
||||
exchanges, err := s.store.Exchange().List(userID)
|
||||
if err != nil {
|
||||
logger.Infof("❌ Failed to get exchange configs: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to get exchange configs: %v", err)})
|
||||
SafeInternalError(c, "Failed to get exchange configs", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1805,7 +1804,7 @@ func (s *Server) handleUpdateExchangeConfigs(c *gin.Context) {
|
||||
for exchangeID, exchangeData := range req.Exchanges {
|
||||
err := s.store.Exchange().Update(userID, exchangeID, exchangeData.Enabled, exchangeData.APIKey, exchangeData.SecretKey, exchangeData.Passphrase, exchangeData.Testnet, exchangeData.HyperliquidWalletAddr, exchangeData.AsterUser, exchangeData.AsterSigner, exchangeData.AsterPrivateKey, exchangeData.LighterWalletAddr, exchangeData.LighterPrivateKey, exchangeData.LighterAPIKeyPrivateKey, exchangeData.LighterAPIKeyIndex)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to update exchange %s: %v", exchangeID, err)})
|
||||
SafeInternalError(c, fmt.Sprintf("Update exchange %s", exchangeID), err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -1910,7 +1909,7 @@ func (s *Server) handleCreateExchange(c *gin.Context) {
|
||||
)
|
||||
if err != nil {
|
||||
logger.Infof("❌ Failed to create exchange account: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to create exchange account: %v", err)})
|
||||
SafeInternalError(c, "Failed to create exchange account", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1953,7 +1952,7 @@ func (s *Server) handleDeleteExchange(c *gin.Context) {
|
||||
err = s.store.Exchange().Delete(userID, exchangeID)
|
||||
if err != nil {
|
||||
logger.Infof("❌ Failed to delete exchange account: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to delete exchange account: %v", err)})
|
||||
SafeInternalError(c, "Failed to delete exchange account", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1966,7 +1965,7 @@ func (s *Server) handleTraderList(c *gin.Context) {
|
||||
userID := c.GetString("user_id")
|
||||
traders, err := s.store.Trader().List(userID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to get trader list: %v", err)})
|
||||
SafeInternalError(c, "Failed to get trader list", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2019,7 +2018,7 @@ func (s *Server) handleGetTraderConfig(c *gin.Context) {
|
||||
|
||||
fullCfg, err := s.store.Trader().GetFullConfig(userID, traderID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": fmt.Sprintf("Failed to get trader config: %v", err)})
|
||||
SafeNotFound(c, "Trader config")
|
||||
return
|
||||
}
|
||||
traderConfig := fullCfg.Trader
|
||||
@@ -2062,13 +2061,13 @@ func (s *Server) handleGetTraderConfig(c *gin.Context) {
|
||||
func (s *Server) handleStatus(c *gin.Context) {
|
||||
_, traderID, err := s.getTraderFromQuery(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid trader ID")
|
||||
return
|
||||
}
|
||||
|
||||
trader, err := s.traderManager.GetTrader(traderID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||
SafeNotFound(c, "Trader")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2080,23 +2079,20 @@ func (s *Server) handleStatus(c *gin.Context) {
|
||||
func (s *Server) handleAccount(c *gin.Context) {
|
||||
_, traderID, err := s.getTraderFromQuery(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid trader ID")
|
||||
return
|
||||
}
|
||||
|
||||
trader, err := s.traderManager.GetTrader(traderID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||
SafeNotFound(c, "Trader")
|
||||
return
|
||||
}
|
||||
|
||||
logger.Infof("📊 Received account info request [%s]", trader.GetName())
|
||||
account, err := trader.GetAccountInfo()
|
||||
if err != nil {
|
||||
logger.Infof("❌ Failed to get account info [%s]: %v", trader.GetName(), err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get account info: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get account info", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2113,21 +2109,19 @@ func (s *Server) handleAccount(c *gin.Context) {
|
||||
func (s *Server) handlePositions(c *gin.Context) {
|
||||
_, traderID, err := s.getTraderFromQuery(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid trader ID")
|
||||
return
|
||||
}
|
||||
|
||||
trader, err := s.traderManager.GetTrader(traderID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||
SafeNotFound(c, "Trader")
|
||||
return
|
||||
}
|
||||
|
||||
positions, err := trader.GetPositions()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get position list: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get positions", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2138,13 +2132,13 @@ func (s *Server) handlePositions(c *gin.Context) {
|
||||
func (s *Server) handlePositionHistory(c *gin.Context) {
|
||||
_, traderID, err := s.getTraderFromQuery(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid trader ID")
|
||||
return
|
||||
}
|
||||
|
||||
trader, err := s.traderManager.GetTrader(traderID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||
SafeNotFound(c, "Trader")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2165,9 +2159,7 @@ func (s *Server) handlePositionHistory(c *gin.Context) {
|
||||
// Get closed positions
|
||||
positions, err := store.Position().GetClosedPositions(trader.GetID(), limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get position history: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get position history", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2192,13 +2184,13 @@ func (s *Server) handlePositionHistory(c *gin.Context) {
|
||||
func (s *Server) handleTrades(c *gin.Context) {
|
||||
_, traderID, err := s.getTraderFromQuery(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid trader ID")
|
||||
return
|
||||
}
|
||||
|
||||
trader, err := s.traderManager.GetTrader(traderID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||
SafeNotFound(c, "Trader")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2224,9 +2216,7 @@ func (s *Server) handleTrades(c *gin.Context) {
|
||||
|
||||
allTrades, err := store.Position().GetRecentTrades(trader.GetID(), limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get trades: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get trades", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2249,13 +2239,13 @@ func (s *Server) handleTrades(c *gin.Context) {
|
||||
func (s *Server) handleOrders(c *gin.Context) {
|
||||
_, traderID, err := s.getTraderFromQuery(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid trader ID")
|
||||
return
|
||||
}
|
||||
|
||||
trader, err := s.traderManager.GetTrader(traderID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||
SafeNotFound(c, "Trader")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2283,9 +2273,7 @@ func (s *Server) handleOrders(c *gin.Context) {
|
||||
// Get all orders for this trader
|
||||
allOrders, err := store.Order().GetTraderOrders(trader.GetID(), limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get orders: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get orders", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2317,13 +2305,13 @@ func (s *Server) handleOrderFills(c *gin.Context) {
|
||||
|
||||
_, traderID, err := s.getTraderFromQuery(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid trader ID")
|
||||
return
|
||||
}
|
||||
|
||||
trader, err := s.traderManager.GetTrader(traderID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||
SafeNotFound(c, "Trader")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2336,9 +2324,7 @@ func (s *Server) handleOrderFills(c *gin.Context) {
|
||||
// Get fills for this order
|
||||
fills, err := store.Order().GetOrderFills(orderID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get order fills: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get order fills", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2376,30 +2362,21 @@ func (s *Server) handleKlines(c *gin.Context) {
|
||||
// US Stocks via Alpaca
|
||||
klines, err = s.getKlinesFromAlpaca(symbol, interval, limit)
|
||||
if err != nil {
|
||||
logger.Errorf("❌ Alpaca API failed for %s: %v", symbol, err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get klines from Alpaca: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get klines from Alpaca", err)
|
||||
return
|
||||
}
|
||||
case "forex", "metals":
|
||||
// Forex and Metals via Twelve Data
|
||||
klines, err = s.getKlinesFromTwelveData(symbol, interval, limit)
|
||||
if err != nil {
|
||||
logger.Errorf("❌ TwelveData API failed for %s: %v", symbol, err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get klines from TwelveData: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get klines from TwelveData", err)
|
||||
return
|
||||
}
|
||||
case "hyperliquid", "hyperliquid-xyz", "xyz":
|
||||
// Hyperliquid native API - supports both crypto perps and stock perps (xyz dex)
|
||||
klines, err = s.getKlinesFromHyperliquid(symbol, interval, limit)
|
||||
if err != nil {
|
||||
logger.Errorf("❌ Hyperliquid API failed for %s: %v", symbol, err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get klines from Hyperliquid: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get klines from Hyperliquid", err)
|
||||
return
|
||||
}
|
||||
default:
|
||||
@@ -2407,10 +2384,7 @@ func (s *Server) handleKlines(c *gin.Context) {
|
||||
symbol = market.Normalize(symbol)
|
||||
klines, err = s.getKlinesFromCoinank(symbol, interval, exchange, limit)
|
||||
if err != nil {
|
||||
logger.Errorf("❌ CoinAnk API failed for %s on %s: %v", symbol, exchange, err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get klines from CoinAnk: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get klines from CoinAnk", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -2728,22 +2702,20 @@ func (s *Server) handleSymbols(c *gin.Context) {
|
||||
func (s *Server) handleDecisions(c *gin.Context) {
|
||||
_, traderID, err := s.getTraderFromQuery(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid trader ID")
|
||||
return
|
||||
}
|
||||
|
||||
trader, err := s.traderManager.GetTrader(traderID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||
SafeNotFound(c, "Trader")
|
||||
return
|
||||
}
|
||||
|
||||
// Get all historical decision records (unlimited)
|
||||
records, err := trader.GetStore().Decision().GetLatestRecords(trader.GetID(), 10000)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get decision log: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get decision log", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2754,13 +2726,13 @@ func (s *Server) handleDecisions(c *gin.Context) {
|
||||
func (s *Server) handleLatestDecisions(c *gin.Context) {
|
||||
_, traderID, err := s.getTraderFromQuery(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid trader ID")
|
||||
return
|
||||
}
|
||||
|
||||
trader, err := s.traderManager.GetTrader(traderID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||
SafeNotFound(c, "Trader")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2777,9 +2749,7 @@ func (s *Server) handleLatestDecisions(c *gin.Context) {
|
||||
|
||||
records, err := trader.GetStore().Decision().GetLatestRecords(trader.GetID(), limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get decision log: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get decision log", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2796,21 +2766,19 @@ func (s *Server) handleLatestDecisions(c *gin.Context) {
|
||||
func (s *Server) handleStatistics(c *gin.Context) {
|
||||
_, traderID, err := s.getTraderFromQuery(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid trader ID")
|
||||
return
|
||||
}
|
||||
|
||||
trader, err := s.traderManager.GetTrader(traderID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||
SafeNotFound(c, "Trader")
|
||||
return
|
||||
}
|
||||
|
||||
stats, err := trader.GetStore().Decision().GetStatistics(trader.GetID())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get statistics: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get statistics", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2829,9 +2797,7 @@ func (s *Server) handleCompetition(c *gin.Context) {
|
||||
|
||||
competition, err := s.traderManager.GetCompetitionData()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get competition data: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get competition data", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2843,7 +2809,7 @@ func (s *Server) handleCompetition(c *gin.Context) {
|
||||
func (s *Server) handleEquityHistory(c *gin.Context) {
|
||||
_, traderID, err := s.getTraderFromQuery(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid trader ID")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2851,9 +2817,7 @@ func (s *Server) handleEquityHistory(c *gin.Context) {
|
||||
// Every 3 minutes per cycle: 10000 records = about 20 days of data
|
||||
snapshots, err := s.store.Equity().GetLatest(traderID, 10000)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get historical data: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get historical data", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2931,7 +2895,8 @@ func (s *Server) authMiddleware() gin.HandlerFunc {
|
||||
// Validate JWT token
|
||||
claims, err := auth.ValidateJWT(tokenString)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token: " + err.Error()})
|
||||
logger.Errorf("[Auth] Invalid token: %v", err)
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid or expired token"})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
@@ -2999,7 +2964,7 @@ func (s *Server) handleRegister(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid request parameters")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3036,7 +3001,7 @@ func (s *Server) handleRegister(c *gin.Context) {
|
||||
|
||||
err = s.store.User().Create(user)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user: " + err.Error()})
|
||||
SafeInternalError(c, "Failed to create user", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3059,14 +3024,14 @@ func (s *Server) handleCompleteRegistration(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid request parameters")
|
||||
return
|
||||
}
|
||||
|
||||
// Get user information
|
||||
user, err := s.store.User().GetByID(req.UserID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "User does not exist"})
|
||||
SafeNotFound(c, "User")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3112,7 +3077,7 @@ func (s *Server) handleLogin(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid request parameters")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3156,14 +3121,14 @@ func (s *Server) handleVerifyOTP(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid request parameters")
|
||||
return
|
||||
}
|
||||
|
||||
// Get user information
|
||||
user, err := s.store.User().GetByID(req.UserID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "User does not exist"})
|
||||
SafeNotFound(c, "User")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3197,7 +3162,7 @@ func (s *Server) handleResetPassword(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
SafeBadRequest(c, "Invalid request parameters")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3326,9 +3291,7 @@ func (s *Server) handlePublicTraderList(c *gin.Context) {
|
||||
// Get trader information from all users
|
||||
competition, err := s.traderManager.GetCompetitionData()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get trader list: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get trader list", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3371,9 +3334,7 @@ func (s *Server) handlePublicTraderList(c *gin.Context) {
|
||||
func (s *Server) handlePublicCompetition(c *gin.Context) {
|
||||
competition, err := s.traderManager.GetCompetitionData()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get competition data: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get competition data", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3384,9 +3345,7 @@ func (s *Server) handlePublicCompetition(c *gin.Context) {
|
||||
func (s *Server) handleTopTraders(c *gin.Context) {
|
||||
topTraders, err := s.traderManager.GetTopTradersData()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get top 10 trader data: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get top traders data", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3409,9 +3368,7 @@ func (s *Server) handleEquityHistoryBatch(c *gin.Context) {
|
||||
// If no trader_ids specified, return historical data for top 5
|
||||
topTraders, err := s.traderManager.GetTopTradersData()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": fmt.Sprintf("Failed to get top 5 traders: %v", err),
|
||||
})
|
||||
SafeInternalError(c, "Get top traders", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3506,7 +3463,8 @@ func (s *Server) getEquityHistoryForTraders(traderIDs []string, hours int) map[s
|
||||
snapshots, err = s.store.Equity().GetLatest(traderID, 500)
|
||||
}
|
||||
if err != nil {
|
||||
errors[traderID] = fmt.Sprintf("Failed to get historical data: %v", err)
|
||||
logger.Errorf("[API] Failed to get equity history for %s: %v", traderID, err)
|
||||
errors[traderID] = "Failed to get historical data"
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user