package v1 import ( "strconv" "strings" "github.com/gofiber/fiber/v2" "cryptoHermes/internal/entity" "cryptoHermes/internal/usecase" ) type MarketDeps struct { MarketContext *usecase.MarketContextUsecase MarketData usecase.MarketDataProvider Derivatives usecase.DerivativesProvider KlineRepo usecase.KlineRepository FundingRepo usecase.FundingRepository OIRepo usecase.OpenInterestRepository LSRepo usecase.LongShortRatioRepository } var allowedIntervals = map[string]bool{ "15m": true, "1h": true, "4h": true, "1d": true, "1w": true, } func RegisterMarket(r fiber.Router, d MarketDeps) { g := r.Group("/market") g.Get("/context", func(c *fiber.Ctx) error { symbol := strings.ToUpper(c.Query("symbol")) if symbol == "" { return fiber.NewError(fiber.StatusBadRequest, "symbol is required") } out, err := d.MarketContext.Build(c.UserContext(), symbol) if err != nil && out == nil { return fiber.NewError(fiber.StatusBadRequest, err.Error()) } return c.JSON(out) }) g.Get("/klines", func(c *fiber.Ctx) error { symbol := strings.ToUpper(c.Query("symbol")) interval := c.Query("interval") if symbol == "" || interval == "" { return fiber.NewError(fiber.StatusBadRequest, "symbol and interval are required") } if !allowedIntervals[interval] { return fiber.NewError(fiber.StatusBadRequest, "interval must be one of 15m/1h/4h/1d/1w") } limit := 300 if l := c.Query("limit"); l != "" { if v, err := strconv.Atoi(l); err == nil && v > 0 && v <= 1000 { limit = v } } rows, err := d.KlineRepo.FindRecent(c.UserContext(), symbol, interval, limit) if err != nil { return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } return c.JSON(rows) }) g.Get("/snapshot", func(c *fiber.Ctx) error { symbol := strings.ToUpper(c.Query("symbol")) if symbol == "" { return fiber.NewError(fiber.StatusBadRequest, "symbol is required") } t, err := d.MarketData.GetTicker24h(c.UserContext(), symbol) if err != nil { return fiber.NewError(fiber.StatusBadGateway, err.Error()) } return c.JSON(t) }) g.Get("/derivatives", func(c *fiber.Ctx) error { symbol := strings.ToUpper(c.Query("symbol")) period := c.Query("period", "1h") if symbol == "" { return fiber.NewError(fiber.StatusBadRequest, "symbol is required") } fundCur, ferr := d.Derivatives.GetCurrentFunding(c.UserContext(), symbol) oiCur, oerr := d.Derivatives.GetCurrentOpenInterest(c.UserContext(), symbol) fundHist, _ := d.FundingRepo.FindRecent(c.UserContext(), symbol, 100) oiHist, _ := d.OIRepo.FindRecent(c.UserContext(), symbol, period, 200) globalLS, _ := d.LSRepo.FindRecent(c.UserContext(), symbol, period, entity.RatioTypeGlobalAccount, 200) topLS, _ := d.LSRepo.FindRecent(c.UserContext(), symbol, period, entity.RatioTypeTopTraderPosition, 200) resp := fiber.Map{ "symbol": symbol, "funding": fiber.Map{ "current": fundCur, "history": fundHist, "error": errString(ferr), }, "openInterest": fiber.Map{ "current": oiCur, "history": oiHist, "error": errString(oerr), }, "longShortRatio": fiber.Map{ "global": globalLS, "topTraderPosition": topLS, }, "takerBuySellVolume": []any{}, } return c.JSON(resp) }) } func errString(e error) string { if e == nil { return "" } return e.Error() }