package market import ( "sync" "time" "github.com/adshao/go-binance/v2" "github.com/adshao/go-binance/v2/futures" "github.com/rs/zerolog/log" ) type MarketData struct { // Trading pair caches spotPairs map[string]bool futuresPairs map[string]bool spotToken2Symbol map[string]string futureToken2Symbol map[string]string pairCacheMutex sync.RWMutex lastPairCacheUpdate time.Time // Alpha token cache alphaTokens map[string]AlphaTokenInfo alphaCacheMutex sync.RWMutex lastAlphaCacheUpdate time.Time // Binance REST clients spotClient *binance.Client futuresClient *futures.Client } func NewMarketData() *MarketData { log.Info().Msg("Start market service") ms := &MarketData{ spotPairs: make(map[string]bool), futuresPairs: make(map[string]bool), spotToken2Symbol: make(map[string]string), futureToken2Symbol: make(map[string]string), alphaTokens: make(map[string]AlphaTokenInfo), spotClient: binance.NewClient("", ""), futuresClient: futures.NewClient("", ""), } ms.refreshAllCaches() go ms.cacheRefreshLoop() return ms } func (ms *MarketData) alphaCacheRefreshLoop() { ms.refreshAlphaTokenCache() ticker := time.NewTicker(time.Hour) defer ticker.Stop() for range ticker.C { ms.refreshAlphaTokenCache() } } func (ms *MarketData) refreshTradingPairCache() error { if err := ms.refreshSpotPairCache(); err != nil { return err } if err := ms.refreshFuturePairCache(); err != nil { return err } ms.pairCacheMutex.RLock() spotCount := len(ms.spotPairs) futureCount := len(ms.futuresPairs) ms.pairCacheMutex.RUnlock() log.Info(). Int("spot", spotCount). Int("futures", futureCount). Msg("Trading pair cache refreshed") return nil } func (ms *MarketData) cacheRefreshLoop() { ms.refreshAllCaches() ticker := time.NewTicker(time.Hour) defer ticker.Stop() for range ticker.C { ms.refreshAllCaches() } } func (ms *MarketData) refreshAllCaches() { if err := ms.refreshSpotPairCache(); err != nil { log.Error().Err(err).Msg("Failed spot pair refresh") } if err := ms.refreshFuturePairCache(); err != nil { log.Error().Err(err).Msg("Failed futures pair refresh") } ms.refreshAlphaTokenCache() } func (ms *MarketData) RefreshTradingPairCache() error { return ms.refreshTradingPairCache() }