this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(api) add average price endpoint handler

eagleusb 768f24ed b93e75ae

+89 -1
+80
internal/handlers/average.go
··· 1 + package handlers 2 + 3 + import ( 4 + "encoding/json" 5 + "log/slog" 6 + "net/http" 7 + "strconv" 8 + "time" 9 + 10 + "github.com/eagleusb/proxycon/internal/types" 11 + ) 12 + 13 + // averageEndpoint is the handler function for `GET /average?start=<timestamp>&end=<timestamp>` 14 + func (h *HttpServer) averageEndpoint(w http.ResponseWriter, r *http.Request) { 15 + startStr := r.URL.Query().Get("start") 16 + endStr := r.URL.Query().Get("end") 17 + 18 + if startStr == "" || endStr == "" { 19 + http.Error(w, "missing query parameters: start and end are required", http.StatusBadRequest) 20 + return 21 + } 22 + 23 + startTime, err := time.Parse(time.RFC3339, startStr) 24 + if err != nil { 25 + http.Error(w, "invalid start timestamp: must be RFC3339 format", http.StatusBadRequest) 26 + return 27 + } 28 + 29 + endTime, err := time.Parse(time.RFC3339, endStr) 30 + if err != nil { 31 + http.Error(w, "invalid end timestamp: must be RFC3339 format", http.StatusBadRequest) 32 + return 33 + } 34 + 35 + if startTime.After(endTime) { 36 + http.Error(w, "start timestamp must be before end timestamp", http.StatusBadRequest) 37 + return 38 + } 39 + 40 + prices := h.datasource.GetPrices() 41 + 42 + var matched []types.Price 43 + for _, p := range prices { 44 + t, err := time.Parse(time.RFC3339, p.Timestamp) 45 + if err != nil { 46 + continue 47 + } 48 + if (t.Equal(startTime) || t.After(startTime)) && (t.Equal(endTime) || t.Before(endTime)) { 49 + matched = append(matched, p) 50 + } 51 + } 52 + 53 + if len(matched) == 0 { 54 + http.Error(w, "no prices found in the given range", http.StatusNotFound) 55 + return 56 + } 57 + 58 + entries := make([]types.Entry, len(matched)) 59 + var sum int64 60 + for i, p := range matched { 61 + val, _ := strconv.ParseInt(p.Price, 10, 64) 62 + sum += val 63 + entries[i] = types.Entry{ 64 + Amount: p.Price, 65 + Timestamp: p.Timestamp, 66 + } 67 + } 68 + 69 + avg := sum / int64(len(matched)) 70 + 71 + w.Header().Set("Content-Type", "application/json") 72 + if err := json.NewEncoder(w).Encode(types.AverageResponse{ 73 + Start: matched[0].Timestamp, 74 + End: matched[len(matched)-1].Timestamp, 75 + Avg: strconv.FormatInt(avg, 10), 76 + Data: entries, 77 + }); err != nil { 78 + slog.Error("encode average response", "error", err) 79 + } 80 + }
+1 -1
internal/handlers/list.go
··· 9 9 "github.com/eagleusb/proxycon/internal/types" 10 10 ) 11 11 12 - // listEndpoint is the handler function for `/list` 12 + // listEndpoint is the handler function for `GET /list` 13 13 func (h *HttpServer) listEndpoint(w http.ResponseWriter, r *http.Request) { 14 14 cursor := 0 15 15
+1
internal/handlers/server.go
··· 47 47 func (h *HttpServer) registerHandler() { 48 48 h.serveMux.HandleFunc("GET /list", h.listEndpoint) 49 49 h.serveMux.HandleFunc("GET /price", h.priceEndpoint) 50 + h.serveMux.HandleFunc("GET /average", h.averageEndpoint) 50 51 }
+7
internal/types/model.go
··· 28 28 type PriceResponse struct { 29 29 Data []Entry `json:"data"` 30 30 } 31 + 32 + type AverageResponse struct { 33 + Start string `json:"start"` 34 + End string `json:"end"` 35 + Avg string `json:"avg"` 36 + Data []Entry `json:"data"` 37 + }