package usecase import ( "context" "sync" "golang.org/x/sync/errgroup" "cryptoHermes/internal/entity" ) const ( derivativesFundingHistoryLen = 100 derivativesOIHistoryLen = 200 derivativesLongShortLen = 200 ) type MarketQueryUsecase struct { derivatives DerivativesProvider fundingRepo FundingRepository oiRepo OpenInterestRepository lsRepo LongShortRatioRepository } func NewMarketQueryUsecase( derivatives DerivativesProvider, fundingRepo FundingRepository, oiRepo OpenInterestRepository, lsRepo LongShortRatioRepository, ) *MarketQueryUsecase { return &MarketQueryUsecase{ derivatives: derivatives, fundingRepo: fundingRepo, oiRepo: oiRepo, lsRepo: lsRepo, } } func (u *MarketQueryUsecase) GetDerivatives(ctx context.Context, symbol, period string) (*entity.DerivativesBundle, []string, error) { var ( currentFund *entity.FundingRate currentOI *entity.OpenInterest warnMu sync.Mutex warnings []string ) addWarn := func(w string) { warnMu.Lock() warnings = append(warnings, w) warnMu.Unlock() } g, gctx := errgroup.WithContext(ctx) g.Go(func() error { f, err := u.derivatives.GetCurrentFunding(gctx, symbol) if err != nil { addWarn("current funding fetch failed: " + err.Error()) return nil } currentFund = f return nil }) g.Go(func() error { oi, err := u.derivatives.GetCurrentOpenInterest(gctx, symbol) if err != nil { addWarn("current OI fetch failed: " + err.Error()) return nil } currentOI = oi return nil }) _ = g.Wait() fundingHist, err := u.fundingRepo.FindRecent(ctx, symbol, derivativesFundingHistoryLen) if err != nil { addWarn("funding history query failed: " + err.Error()) } oiHist, err := u.oiRepo.FindRecent(ctx, symbol, period, derivativesOIHistoryLen) if err != nil { addWarn("OI history query failed: " + err.Error()) } globalLS, err := u.lsRepo.FindRecent(ctx, symbol, period, entity.RatioTypeGlobalAccount, derivativesLongShortLen) if err != nil { addWarn("global long/short query failed: " + err.Error()) } topLS, err := u.lsRepo.FindRecent(ctx, symbol, period, entity.RatioTypeTopTraderPosition, derivativesLongShortLen) if err != nil { addWarn("top trader position long/short query failed: " + err.Error()) } bundle := &entity.DerivativesBundle{ Funding: entity.FundingBundle{ Current: currentFund, History: fundingHist, }, OpenInterest: entity.OpenInterestBundle{ Current: currentOI, History: oiHist, }, LongShortRatio: entity.LongShortBundle{ Global: globalLS, TopTraderPosition: topLS, }, TakerBuySellVolume: []entity.TakerBuySellVolume{}, } if warnings == nil { warnings = []string{} } return bundle, warnings, nil }