From 33cf09e7fe3ca73f9e0ed5182712f967df06d77c Mon Sep 17 00:00:00 2001 From: tinkle-community Date: Tue, 13 Jan 2026 13:28:18 +0800 Subject: [PATCH] fix: correct Lighter API response parsing for GetOpenOrders - Changed response field from 'data' to 'orders' to match Lighter API - Updated OrderResponse struct to match Lighter's actual field names - Fixed field types: price/quantity as strings, is_ask for side --- trader/lighter_trader_v2_orders.go | 10 +++++----- trader/lighter_trader_v2_trading.go | 26 +++++++++++++++++--------- trader/lighter_types.go | 28 +++++++++++++++++----------- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/trader/lighter_trader_v2_orders.go b/trader/lighter_trader_v2_orders.go index 1c6acea7..e89a99ac 100644 --- a/trader/lighter_trader_v2_orders.go +++ b/trader/lighter_trader_v2_orders.go @@ -148,7 +148,7 @@ func (t *LighterTraderV2) GetOrderStatus(symbol string, orderID string) (map[str "orderId": order.OrderID, "status": unifiedStatus, "avgPrice": order.Price, - "executedQty": order.FilledQty, + "executedQty": order.FilledBaseAmount, "commission": 0.0, }, nil } @@ -239,11 +239,11 @@ func (t *LighterTraderV2) GetActiveOrders(symbol string) ([]OrderResponse, error logger.Infof("📋 LIGHTER GetActiveOrders raw response: %s", string(body)) - // Parse response + // Parse response - Lighter API uses "orders" field, not "data" var apiResp struct { Code int `json:"code"` Message string `json:"message"` - Data []OrderResponse `json:"data"` + Orders []OrderResponse `json:"orders"` } if err := json.Unmarshal(body, &apiResp); err != nil { @@ -254,8 +254,8 @@ func (t *LighterTraderV2) GetActiveOrders(symbol string) ([]OrderResponse, error return nil, fmt.Errorf("failed to get active orders (code %d): %s", apiResp.Code, apiResp.Message) } - logger.Infof("✓ LIGHTER - Retrieved %d active orders", len(apiResp.Data)) - return apiResp.Data, nil + logger.Infof("✓ LIGHTER - Retrieved %d active orders", len(apiResp.Orders)) + return apiResp.Orders, nil } // CancelOrder Cancel a single order diff --git a/trader/lighter_trader_v2_trading.go b/trader/lighter_trader_v2_trading.go index 2f08ef8a..88d31b7e 100644 --- a/trader/lighter_trader_v2_trading.go +++ b/trader/lighter_trader_v2_trading.go @@ -697,19 +697,19 @@ func (t *LighterTraderV2) GetOpenOrders(symbol string) ([]OpenOrder, error) { var result []OpenOrder for _, order := range activeOrders { - // Convert side: Lighter uses "bid"/"ask", we need "BUY"/"SELL" + // Convert side: Lighter uses is_ask (true=sell, false=buy) side := "BUY" - if order.Side == "ask" || order.Side == "SELL" || order.Side == "sell" { + if order.IsAsk { side = "SELL" } - // Determine order type + // Determine order type from Lighter's type field orderType := "LIMIT" - if order.OrderType == "market" { + if order.Type == "market" { orderType = "MARKET" - } else if order.OrderType == "stop_loss" { + } else if order.Type == "stop_loss" || order.Type == "stop" { orderType = "STOP_MARKET" - } else if order.OrderType == "take_profit" { + } else if order.Type == "take_profit" { orderType = "TAKE_PROFIT_MARKET" } @@ -719,15 +719,23 @@ func (t *LighterTraderV2) GetOpenOrders(symbol string) ([]OpenOrder, error) { positionSide = "SHORT" } + // Parse price and quantity from string fields + price, _ := strconv.ParseFloat(order.Price, 64) + quantity, _ := strconv.ParseFloat(order.RemainingBaseAmount, 64) + if quantity == 0 { + quantity, _ = strconv.ParseFloat(order.InitialBaseAmount, 64) + } + triggerPrice, _ := strconv.ParseFloat(order.TriggerPrice, 64) + openOrder := OpenOrder{ OrderID: order.OrderID, Symbol: symbol, Side: side, PositionSide: positionSide, Type: orderType, - Price: order.Price, - StopPrice: order.Price, // For stop orders, price is the trigger price - Quantity: order.Quantity, + Price: price, + StopPrice: triggerPrice, + Quantity: quantity, Status: "NEW", } result = append(result, openOrder) diff --git a/trader/lighter_types.go b/trader/lighter_types.go index 3a76b7c4..e4670cdd 100644 --- a/trader/lighter_types.go +++ b/trader/lighter_types.go @@ -41,18 +41,24 @@ type CreateOrderRequest struct { PostOnly bool `json:"post_only"` // Post-only (maker only) } -// OrderResponse Order response (Lighter) +// OrderResponse Order response (Lighter API) +// Field names must match Lighter API response exactly type OrderResponse struct { - OrderID string `json:"order_id"` - Symbol string `json:"symbol"` - Side string `json:"side"` - OrderType string `json:"order_type"` - Quantity float64 `json:"quantity"` - Price float64 `json:"price"` - Status string `json:"status"` // "open", "filled", "cancelled" - FilledQty float64 `json:"filled_qty"` - RemainingQty float64 `json:"remaining_qty"` - CreateTime int64 `json:"create_time"` + OrderID string `json:"order_id"` + OrderIndex int64 `json:"order_index"` + MarketIndex int `json:"market_index"` + Side string `json:"side"` // "bid" or "ask" + Type string `json:"type"` // "limit", "market", etc. + IsAsk bool `json:"is_ask"` // true = sell, false = buy + Price string `json:"price"` // Price as string + InitialBaseAmount string `json:"initial_base_amount"` // Original quantity + RemainingBaseAmount string `json:"remaining_base_amount"` // Remaining quantity + FilledBaseAmount string `json:"filled_base_amount"` // Filled quantity + Status string `json:"status"` // "open", "filled", "cancelled" + TriggerPrice string `json:"trigger_price"` // For stop orders + ReduceOnly bool `json:"reduce_only"` + Timestamp int64 `json:"timestamp"` + CreatedAt int64 `json:"created_at"` } // LighterTradeResponse represents the response from Lighter trades API