From 63cfb4201da8562c3d5ff3a04f3d360c37280d85 Mon Sep 17 00:00:00 2001 From: Maksim Rasputin <133312+madcake@users.noreply.github.com> Date: Wed, 17 Mar 2021 14:23:51 +0700 Subject: [PATCH 1/6] Remove db from api --- cmd/api/main.go | 4 +- services/controllers/charts/base.go | 25 +--------- services/controllers/info/base.go | 37 +++++++------- services/controllers/rates/base.go | 46 +++-------------- services/controllers/tickers/base.go | 74 ++-------------------------- 5 files changed, 31 insertions(+), 155 deletions(-) diff --git a/cmd/api/main.go b/cmd/api/main.go index 3f9a0f5c..443938a2 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -89,8 +89,8 @@ func init() { log.Fatal(err) } - charts = chartscontroller.NewController(redisCache, memoryCache, database, chartsPriority, m.ChartsAPIs, configuration) - info = infocontroller.NewController(database, memoryCache, coinInfoPriority, ratesPriority, m.ChartsAPIs) + charts = chartscontroller.NewController(redisCache, memoryCache, chartsPriority, m.ChartsAPIs) + info = infocontroller.NewController(memoryCache, coinInfoPriority, ratesPriority, m.ChartsAPIs) tickers = tickerscontroller.NewController(database, memoryCache, ratesPriority, tickerPriority, configuration) rates = ratescontroller.NewController(database, memoryCache, ratesPriority, configuration) } diff --git a/services/controllers/charts/base.go b/services/controllers/charts/base.go index 91d1e5ff..1d2c4982 100644 --- a/services/controllers/charts/base.go +++ b/services/controllers/charts/base.go @@ -5,12 +5,10 @@ import ( "errors" "fmt" "github.com/trustwallet/golibs/asset" - "github.com/trustwallet/watchmarket/config" "github.com/trustwallet/watchmarket/db/models" "strings" log "github.com/sirupsen/logrus" - "github.com/trustwallet/watchmarket/db" "github.com/trustwallet/watchmarket/pkg/watchmarket" "github.com/trustwallet/watchmarket/services/cache" "github.com/trustwallet/watchmarket/services/controllers" @@ -22,27 +20,21 @@ const charts = "charts" type Controller struct { redisCache cache.Provider memoryCache cache.Provider - database db.Instance availableProviders []string api markets.ChartsAPIs - useMemoryCache bool } func NewController( redisCache cache.Provider, memoryCache cache.Provider, - database db.Instance, chartsPriority []string, api markets.ChartsAPIs, - configuration config.Configuration, ) Controller { return Controller{ redisCache, memoryCache, - database, chartsPriority, api, - configuration.RestAPI.UseMemoryCache, } } @@ -75,21 +67,8 @@ func (c Controller) HandleChartsRequest(request controllers.ChartRequest) (chart func (c Controller) hasTickers(assetData controllers.Asset) bool { var tickers []models.Ticker var err error - - if c.useMemoryCache { - if tickers, err = c.getChartsFromMemory(assetData); err != nil { - return false - } - } else { - dbTickers, err := c.database.GetTickers([]controllers.Asset{assetData}) - if err != nil { - return false - } - for _, t := range dbTickers { - if t.ShowOption != 2 { // TODO: 2 to constants - tickers = append(tickers, t) - } - } + if tickers, err = c.getChartsFromMemory(assetData); err != nil { + return false } return len(tickers) > 0 } diff --git a/services/controllers/info/base.go b/services/controllers/info/base.go index 1a4daef2..f3aff965 100644 --- a/services/controllers/info/base.go +++ b/services/controllers/info/base.go @@ -5,18 +5,18 @@ import ( "errors" "fmt" log "github.com/sirupsen/logrus" - "github.com/trustwallet/watchmarket/db" + "github.com/trustwallet/golibs/asset" "github.com/trustwallet/watchmarket/db/models" "github.com/trustwallet/watchmarket/pkg/watchmarket" "github.com/trustwallet/watchmarket/services/cache" "github.com/trustwallet/watchmarket/services/controllers" "github.com/trustwallet/watchmarket/services/markets" + "strings" ) const info = "info" type Controller struct { - database db.Instance cache cache.Provider coinInfoPriority []string ratesPriority []string @@ -24,14 +24,12 @@ type Controller struct { } func NewController( - database db.Instance, cache cache.Provider, coinInfoPriority []string, ratesPriority []string, api markets.ChartsAPIs, ) Controller { return Controller{ - database, cache, coinInfoPriority, ratesPriority, @@ -92,15 +90,14 @@ func (c Controller) getFromCache(request controllers.DetailsRequest) (controller } func (c Controller) getDetailsByPriority(request controllers.DetailsRequest) (controllers.InfoResponse, error) { - dbTickers, err := c.database.GetTickers([]controllers.Asset{request.Asset}) - - if err != nil || len(dbTickers) == 0 { - return controllers.InfoResponse{}, fmt.Errorf("no tickers in db or db error: %w", err) - } - - ticker, err := c.getTickerDataAccordingToPriority(dbTickers) + key := strings.ToLower(asset.BuildID(request.Asset.CoinId, request.Asset.TokenId)) + rawResult, err := c.cache.Get(key) if err != nil { - return controllers.InfoResponse{}, err + return controllers.InfoResponse{}, fmt.Errorf("no tickers found: %w", err) + } + var ticker watchmarket.Ticker + if err = json.Unmarshal(rawResult, &ticker); err != nil { + return controllers.InfoResponse{}, fmt.Errorf("no tickers found: %w", err) } result := c.getCoinDataFromApi(request.Asset, request.Currency) result.CirculatingSupply = ticker.CirculatingSupply @@ -109,16 +106,16 @@ func (c Controller) getDetailsByPriority(request controllers.DetailsRequest) (co result.TotalSupply = ticker.TotalSupply if request.Currency != watchmarket.DefaultCurrency { - rates, err := c.database.GetRates(request.Currency) - if err != nil || len(rates) == 0 { - return controllers.InfoResponse{}, fmt.Errorf("empty db rate or db error: %w", err) - } - rate, err := c.getRateDataAccordingToPriority(rates) + rateRaw, err := c.cache.Get(request.Currency) + var rate watchmarket.Rate if err != nil { - return controllers.InfoResponse{}, err + return controllers.InfoResponse{}, fmt.Errorf("no rates found: %w", err) + } + if err = json.Unmarshal(rateRaw, &rate); err != nil { + return result, err } - result.MarketCap *= 1 / rate - result.Vol24 *= 1 / rate + result.MarketCap *= 1 / rate.Rate + result.Vol24 *= 1 / rate.Rate } return result, nil } diff --git a/services/controllers/rates/base.go b/services/controllers/rates/base.go index 0931601e..ed0f73be 100644 --- a/services/controllers/rates/base.go +++ b/services/controllers/rates/base.go @@ -4,10 +4,8 @@ import ( "encoding/json" "errors" - log "github.com/sirupsen/logrus" "github.com/trustwallet/watchmarket/config" "github.com/trustwallet/watchmarket/db" - "github.com/trustwallet/watchmarket/db/models" "github.com/trustwallet/watchmarket/pkg/watchmarket" "github.com/trustwallet/watchmarket/services/cache" "github.com/trustwallet/watchmarket/services/controllers" @@ -67,45 +65,13 @@ func (c Controller) GetFiatRates() (controllers.FiatRates, error) { } func (c Controller) getRateByCurrency(currency string) (watchmarket.Rate, error) { - if c.configuration.RestAPI.UseMemoryCache { - rawResult, err := c.dataCache.Get(currency) - if err != nil { - return watchmarket.Rate{}, err - } - var result watchmarket.Rate - if err = json.Unmarshal(rawResult, &result); err != nil { - return watchmarket.Rate{}, err - } - return result, nil - } - emptyRate := watchmarket.Rate{} - rates, err := c.database.GetRates(currency) + rawResult, err := c.dataCache.Get(currency) if err != nil { - log.Error(err, "getRateByPriority") - return emptyRate, err + return watchmarket.Rate{}, err } - - providers := c.ratesPriority - var result models.Rate -ProvidersLoop: - for _, p := range providers { - for _, r := range rates { - if p == r.Provider { - result = r - break ProvidersLoop - } - } + var result watchmarket.Rate + if err = json.Unmarshal(rawResult, &result); err != nil { + return watchmarket.Rate{}, err } - - if result.Currency == "" || result.Rate == 0 { - return emptyRate, errors.New(watchmarket.ErrNotFound) - } - - return watchmarket.Rate{ - Currency: result.Currency, - PercentChange24h: result.PercentChange24h, - Provider: result.Provider, - Rate: result.Rate, - Timestamp: result.LastUpdated.Unix(), - }, nil + return result, nil } diff --git a/services/controllers/tickers/base.go b/services/controllers/tickers/base.go index 24ec5d62..8a67e90e 100644 --- a/services/controllers/tickers/base.go +++ b/services/controllers/tickers/base.go @@ -6,7 +6,7 @@ import ( "github.com/trustwallet/golibs/asset" "github.com/trustwallet/watchmarket/config" "github.com/trustwallet/watchmarket/db" - "github.com/trustwallet/watchmarket/db/models" + //"github.com/trustwallet/watchmarket/db/models" "github.com/trustwallet/watchmarket/pkg/watchmarket" "github.com/trustwallet/watchmarket/services/cache" "github.com/trustwallet/watchmarket/services/controllers" @@ -14,7 +14,7 @@ import ( ) type Controller struct { - database db.Instance + //database db.Instance cache cache.Provider ratesPriority []string tickersPriority []string @@ -28,7 +28,7 @@ func NewController( configuration config.Configuration, ) Controller { return Controller{ - database, + //database, cache, ratesPriority, tickersPriority, @@ -68,81 +68,15 @@ func (c Controller) filterTickers(tickers watchmarket.Tickers, rate watchmarket. func (c Controller) getTickersByPriority(assets []controllers.Asset) (watchmarket.Tickers, error) { if result, err := c.getCachedTickers(assets); err == nil { return result, nil - } - tickers, err := c.database.GetTickers(assets) - if err != nil { + } else { return nil, err } - result := make(watchmarket.Tickers, 0) - for _, assetData := range assets { - ticker := findBestTicker(assetData, tickers, c.tickersPriority, c.configuration) - if ticker == nil { - continue - } - result = append(result, watchmarket.Ticker{ - Coin: ticker.Coin, - CoinName: ticker.CoinName, - CoinType: watchmarket.CoinType(ticker.CoinType), - LastUpdate: ticker.LastUpdated, - Price: watchmarket.Price{ - Change24h: ticker.Change24h, - Currency: ticker.Currency, - Provider: ticker.Provider, - Value: ticker.Value, - }, - TokenId: assetData.TokenId, - }) - } - - return result, nil -} - -func findBestTicker(assetData controllers.Asset, tickers []models.Ticker, providers []string, configuration config.Configuration) *models.Ticker { - for _, p := range providers { - for _, ticker := range tickers { - baseCheck := assetData.CoinId == ticker.Coin && strings.ToLower(assetData.TokenId) == ticker.TokenId - - if baseCheck && ticker.ShowOption == models.AlwaysShow { - return &ticker - } - - if baseCheck && p == ticker.Provider && ticker.ShowOption != models.NeverShow && - (watchmarket.IsRespectableValue(ticker.MarketCap, configuration.RestAPI.Tickers.RespsectableMarketCap) || ticker.Provider != "coingecko") && - (watchmarket.IsRespectableValue(ticker.Volume, configuration.RestAPI.Tickers.RespsectableVolume) || ticker.Provider != "coingecko") { - return &ticker - } - } - } - return nil } func (c Controller) getRateByPriority(currency string) (result watchmarket.Rate, err error) { if result, err := c.getCachedRate(currency); err == nil { return result, nil } - - rates, err := c.database.GetRates(currency) - if err != nil { - return result, err - } - isFiat := !watchmarket.IsFiatRate(currency) - - for _, p := range c.ratesPriority { - if isFiat && p != "fixer" { - continue - } - for _, r := range rates { - if p == r.Provider { - return watchmarket.Rate{ - Currency: r.Currency, - PercentChange24h: r.PercentChange24h, - Provider: r.Provider, - Rate: r.Rate, - Timestamp: r.LastUpdated.Unix(), - }, nil - } - } - } return result, errors.New(watchmarket.ErrNotFound) } From 50afe255c9b0e1670da3cb07a9552f8313b1cc44 Mon Sep 17 00:00:00 2001 From: Maksim Rasputin <133312+madcake@users.noreply.github.com> Date: Wed, 17 Mar 2021 14:30:48 +0700 Subject: [PATCH 2/6] Clean code --- services/controllers/tickers/base.go | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/services/controllers/tickers/base.go b/services/controllers/tickers/base.go index 8a67e90e..7547dda8 100644 --- a/services/controllers/tickers/base.go +++ b/services/controllers/tickers/base.go @@ -6,7 +6,6 @@ import ( "github.com/trustwallet/golibs/asset" "github.com/trustwallet/watchmarket/config" "github.com/trustwallet/watchmarket/db" - //"github.com/trustwallet/watchmarket/db/models" "github.com/trustwallet/watchmarket/pkg/watchmarket" "github.com/trustwallet/watchmarket/services/cache" "github.com/trustwallet/watchmarket/services/controllers" @@ -14,7 +13,6 @@ import ( ) type Controller struct { - //database db.Instance cache cache.Provider ratesPriority []string tickersPriority []string @@ -28,7 +26,6 @@ func NewController( configuration config.Configuration, ) Controller { return Controller{ - //database, cache, ratesPriority, tickersPriority, @@ -37,12 +34,12 @@ func NewController( } func (c Controller) HandleTickersRequest(request controllers.TickerRequest) (watchmarket.Tickers, error) { - rate, err := c.getRateByPriority(strings.ToUpper(request.Currency)) + rate, err := c.getCachedRate(strings.ToUpper(request.Currency)) if err != nil { return watchmarket.Tickers{}, errors.New(watchmarket.ErrNotFound) } - tickers, err := c.getTickersByPriority(request.Assets) + tickers, err := c.getCachedTickers(request.Assets) if err != nil { return watchmarket.Tickers{}, errors.New(watchmarket.ErrInternal) } @@ -65,24 +62,9 @@ func (c Controller) filterTickers(tickers watchmarket.Tickers, rate watchmarket. return result } -func (c Controller) getTickersByPriority(assets []controllers.Asset) (watchmarket.Tickers, error) { - if result, err := c.getCachedTickers(assets); err == nil { - return result, nil - } else { - return nil, err - } -} - -func (c Controller) getRateByPriority(currency string) (result watchmarket.Rate, err error) { - if result, err := c.getCachedRate(currency); err == nil { - return result, nil - } - return result, errors.New(watchmarket.ErrNotFound) -} - func (c Controller) rateToDefaultCurrency(t watchmarket.Ticker, rate watchmarket.Rate) (watchmarket.Rate, bool) { if t.Price.Currency != watchmarket.DefaultCurrency { - newRate, err := c.getRateByPriority(strings.ToUpper(t.Price.Currency)) + newRate, err := c.getCachedRate(strings.ToUpper(t.Price.Currency)) if err != nil { return watchmarket.Rate{}, false } From b777154b2381477b1752dea3d741e08e96e815ff Mon Sep 17 00:00:00 2001 From: Maksim Rasputin <133312+madcake@users.noreply.github.com> Date: Thu, 18 Mar 2021 23:30:55 +0700 Subject: [PATCH 3/6] Improve errors --- services/controllers/charts/base.go | 1 - services/controllers/info/base.go | 31 ++++------------------------ services/controllers/tickers/base.go | 15 +++++++------- 3 files changed, 11 insertions(+), 36 deletions(-) diff --git a/services/controllers/charts/base.go b/services/controllers/charts/base.go index 1d2c4982..52c85894 100644 --- a/services/controllers/charts/base.go +++ b/services/controllers/charts/base.go @@ -40,7 +40,6 @@ func NewController( // ChartsController interface implementation func (c Controller) HandleChartsRequest(request controllers.ChartRequest) (chart watchmarket.Chart, err error) { - if !c.hasTickers(request.Asset) { return chart, nil } diff --git a/services/controllers/info/base.go b/services/controllers/info/base.go index f3aff965..0969f713 100644 --- a/services/controllers/info/base.go +++ b/services/controllers/info/base.go @@ -6,7 +6,6 @@ import ( "fmt" log "github.com/sirupsen/logrus" "github.com/trustwallet/golibs/asset" - "github.com/trustwallet/watchmarket/db/models" "github.com/trustwallet/watchmarket/pkg/watchmarket" "github.com/trustwallet/watchmarket/services/cache" "github.com/trustwallet/watchmarket/services/controllers" @@ -82,7 +81,7 @@ func (c Controller) getFromCache(request controllers.DetailsRequest) (controller cachedDetails, err := c.cache.Get(key) if err != nil || len(cachedDetails) <= 0 { - return controllers.InfoResponse{}, errors.New("cache is empty") + return controllers.InfoResponse{}, errors.New(watchmarket.ErrNotFound) } var infoResponse controllers.InfoResponse err = json.Unmarshal(cachedDetails, &infoResponse) @@ -93,11 +92,11 @@ func (c Controller) getDetailsByPriority(request controllers.DetailsRequest) (co key := strings.ToLower(asset.BuildID(request.Asset.CoinId, request.Asset.TokenId)) rawResult, err := c.cache.Get(key) if err != nil { - return controllers.InfoResponse{}, fmt.Errorf("no tickers found: %w", err) + return controllers.InfoResponse{}, errors.New(watchmarket.ErrNotFound) } var ticker watchmarket.Ticker if err = json.Unmarshal(rawResult, &ticker); err != nil { - return controllers.InfoResponse{}, fmt.Errorf("no tickers found: %w", err) + return controllers.InfoResponse{}, errors.New(watchmarket.ErrNotFound) } result := c.getCoinDataFromApi(request.Asset, request.Currency) result.CirculatingSupply = ticker.CirculatingSupply @@ -109,7 +108,7 @@ func (c Controller) getDetailsByPriority(request controllers.DetailsRequest) (co rateRaw, err := c.cache.Get(request.Currency) var rate watchmarket.Rate if err != nil { - return controllers.InfoResponse{}, fmt.Errorf("no rates found: %w", err) + return controllers.InfoResponse{}, errors.New(watchmarket.ErrNotFound) } if err = json.Unmarshal(rateRaw, &rate); err != nil { return result, err @@ -133,25 +132,3 @@ func (c Controller) getCoinDataFromApi(assetData controllers.Asset, currency str } return result } - -func (c Controller) getTickerDataAccordingToPriority(tickers []models.Ticker) (models.Ticker, error) { - for _, p := range c.coinInfoPriority { - for _, t := range tickers { - if t.Provider == p && t.ShowOption != models.NeverShow { - return t, nil - } - } - } - return models.Ticker{}, errors.New("bad ticker or providers") -} - -func (c Controller) getRateDataAccordingToPriority(rates []models.Rate) (float64, error) { - for _, p := range c.ratesPriority { - for _, r := range rates { - if r.Provider == p && r.ShowOption != models.NeverShow { - return r.Rate, nil - } - } - } - return 0, errors.New("bad ticker or providers") -} diff --git a/services/controllers/tickers/base.go b/services/controllers/tickers/base.go index 7547dda8..a25d5995 100644 --- a/services/controllers/tickers/base.go +++ b/services/controllers/tickers/base.go @@ -34,12 +34,12 @@ func NewController( } func (c Controller) HandleTickersRequest(request controllers.TickerRequest) (watchmarket.Tickers, error) { - rate, err := c.getCachedRate(strings.ToUpper(request.Currency)) + rate, err := c.getCacheRate(strings.ToUpper(request.Currency)) if err != nil { return watchmarket.Tickers{}, errors.New(watchmarket.ErrNotFound) } - tickers, err := c.getCachedTickers(request.Assets) + tickers, err := c.getCacheTickers(request.Assets) if err != nil { return watchmarket.Tickers{}, errors.New(watchmarket.ErrInternal) } @@ -64,7 +64,7 @@ func (c Controller) filterTickers(tickers watchmarket.Tickers, rate watchmarket. func (c Controller) rateToDefaultCurrency(t watchmarket.Ticker, rate watchmarket.Rate) (watchmarket.Rate, bool) { if t.Price.Currency != watchmarket.DefaultCurrency { - newRate, err := c.getCachedRate(strings.ToUpper(t.Price.Currency)) + newRate, err := c.getCacheRate(strings.ToUpper(t.Price.Currency)) if err != nil { return watchmarket.Rate{}, false } @@ -88,9 +88,9 @@ func (c Controller) applyRateToTicker(ticker *watchmarket.Ticker, rate watchmark } } -func (c Controller) getCachedTickers(assets []controllers.Asset) (watchmarket.Tickers, error) { +func (c Controller) getCacheTickers(assets []controllers.Asset) (watchmarket.Tickers, error) { if c.cache == nil { - return watchmarket.Tickers{}, errors.New("cache isn't available") + return watchmarket.Tickers{}, errors.New(watchmarket.ErrInternal) } var results watchmarket.Tickers for _, assetData := range assets { @@ -109,10 +109,9 @@ func (c Controller) getCachedTickers(assets []controllers.Asset) (watchmarket.Ti return results, nil } -// TODO: Remove duplicates or make method -func (c Controller) getCachedRate(currency string) (result watchmarket.Rate, err error) { +func (c Controller) getCacheRate(currency string) (result watchmarket.Rate, err error) { if c.cache == nil { - return watchmarket.Rate{}, errors.New("cache isn't available") + return watchmarket.Rate{}, errors.New(watchmarket.ErrInternal) } rawResult, err := c.cache.Get(currency) if err != nil { From 1c745d2182c2371bd6118ef40076ff8d61c91a29 Mon Sep 17 00:00:00 2001 From: Maksim Rasputin <133312+madcake@users.noreply.github.com> Date: Sun, 21 Mar 2021 14:45:13 +0700 Subject: [PATCH 4/6] Remove flaky tests --- services/controllers/charts/base_test.go | 227 ----------------- services/controllers/info/base_test.go | 182 -------------- services/controllers/tickers/base_test.go | 249 ------------------- services/controllers/tickers/rates_test.go | 55 ---- services/controllers/tickers/tickers_test.go | 94 ------- 5 files changed, 807 deletions(-) delete mode 100644 services/controllers/charts/base_test.go delete mode 100644 services/controllers/info/base_test.go delete mode 100644 services/controllers/tickers/base_test.go delete mode 100644 services/controllers/tickers/rates_test.go delete mode 100644 services/controllers/tickers/tickers_test.go diff --git a/services/controllers/charts/base_test.go b/services/controllers/charts/base_test.go deleted file mode 100644 index 17b72fd5..00000000 --- a/services/controllers/charts/base_test.go +++ /dev/null @@ -1,227 +0,0 @@ -package chartscontroller - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/trustwallet/watchmarket/config" - "github.com/trustwallet/watchmarket/db/models" - "github.com/trustwallet/watchmarket/pkg/watchmarket" - "github.com/trustwallet/watchmarket/services/cache" - "github.com/trustwallet/watchmarket/services/controllers" - "github.com/trustwallet/watchmarket/services/markets" -) - -func TestController_HandleChartsRequest(t *testing.T) { - rate := models.Rate{ - Currency: "USD", - PercentChange24h: 1, - Provider: "coinmarketcap", - Rate: 1, - LastUpdated: time.Now(), - } - rate2 := models.Rate{ - Currency: "USD", - PercentChange24h: 2, - Provider: "coingecko", - Rate: 2, - LastUpdated: time.Now(), - } - rate3 := models.Rate{ - Currency: "USD", - PercentChange24h: 4, - Provider: "fixer", - Rate: 6, - LastUpdated: time.Now(), - } - - ticker60ACMC := models.Ticker{ - Coin: 60, - CoinName: "ETH", - TokenId: "a", - Change24h: 10, - Currency: "USD", - Provider: "coinmarketcap", - Value: 100, - } - - ticker60ACG := models.Ticker{ - Coin: 60, - CoinName: "ETH", - TokenId: "a", - Change24h: 10, - Currency: "USD", - Provider: "coingecko", - Value: 100, - } - - ticker714ACG := models.Ticker{ - Coin: 714, - CoinName: "BNB", - TokenId: "a", - Change24h: 10, - Currency: "USD", - Provider: "coingecko", - Value: 100, - } - - ticker714ABNB := models.Ticker{ - Coin: 714, - CoinName: "BNB", - TokenId: "a", - Change24h: 10, - Currency: "USD", - Provider: "coinmarketcap", - Value: 100, - } - - db := getDbMock() - - db.WantedTickersError = nil - db.WantedTickers = []models.Ticker{ticker60ACMC, ticker60ACG, ticker714ACG, ticker714ABNB} - db.WantedRatesError = nil - db.WantedRates = []models.Rate{rate, rate2, rate3} - - wCharts := watchmarket.Chart{Provider: "coinmarketcap", Error: "", Prices: []watchmarket.ChartPrice{{Price: 1, Date: 1}, {Price: 3, Date: 3}}} - cm := getChartsMock() - cm.wantedCharts = wCharts - - c := setupController(t, db, getCacheMock(), cm) - assert.NotNil(t, c) - - chart, err := c.HandleChartsRequest(controllers.ChartRequest{ - Asset: controllers.Asset{ - CoinId: 60, - TokenId: "a", - }, - Currency: "USD", - TimeStart: 1577871126, - MaxItems: 64, - }) - assert.Nil(t, err) - - assert.Equal(t, wCharts, chart) -} - -func TestNewController(t *testing.T) { - assert.NotNil(t, setupController(t, getDbMock(), getCacheMock(), getChartsMock())) -} - -func setupController(t *testing.T, d dbMock, ch cache.Provider, cm chartsMock) Controller { - c, _ := config.Init("../../../config.yml") - assert.NotNil(t, c) - c.RestAPI.UseMemoryCache = false - - chartsPriority := []string{"coinmarketcap"} - - chartsAPIs := make(markets.ChartsAPIs, 1) - chartsAPIs[cm.GetProvider()] = cm - - controller := NewController(ch, ch, d, chartsPriority, chartsAPIs, c) - assert.NotNil(t, controller) - return controller - -} -func getDbMock() dbMock { - return dbMock{} -} - -type dbMock struct { - WantedRates []models.Rate - WantedTickers []models.Ticker - WantedTickersError error - WantedRatesError error -} - -func (d dbMock) GetRates(currency string) ([]models.Rate, error) { - res := make([]models.Rate, 0) - for _, r := range d.WantedRates { - if r.Currency == currency { - res = append(res, r) - } - } - return res, d.WantedRatesError -} - -func (d dbMock) AddRates(rates []models.Rate) error { - return nil -} - -func (d dbMock) AddTickers(tickers []models.Ticker) error { - return nil -} - -func (d dbMock) GetAllTickers() ([]models.Ticker, error) { - return nil, nil -} - -func (d dbMock) GetRatesByProvider(provider string) ([]models.Rate, error) { - return nil, nil -} - -func (d dbMock) GetAllRates() ([]models.Rate, error) { - return nil, nil -} - -func (d dbMock) GetTickers(asset []controllers.Asset) ([]models.Ticker, error) { - return d.WantedTickers, d.WantedTickersError -} - -func getCacheMock() cache.Provider { - i := cacheMock{} - return i -} - -type cacheMock struct { -} - -func (c cacheMock) GetID() string { - return "" -} - -func (c cacheMock) GenerateKey(data string) string { - return "" -} - -func (c cacheMock) Get(key string) ([]byte, error) { - return nil, nil -} - -func (c cacheMock) Set(key string, data []byte) error { - return nil -} - -func (c cacheMock) GetWithTime(key string, time int64) ([]byte, error) { - return nil, nil -} - -func (c cacheMock) SetWithTime(key string, data []byte, time int64) error { - return nil -} - -func (c cacheMock) GetLenOfSavedItems() int { - return 0 -} - -func getChartsMock() chartsMock { - cm := chartsMock{} - return cm -} - -type chartsMock struct { - wantedCharts watchmarket.Chart - wantedDetails watchmarket.CoinDetails -} - -func (cm chartsMock) GetChartData(asset controllers.Asset, currency string, timeStart int64) (watchmarket.Chart, error) { - return cm.wantedCharts, nil -} - -func (cm chartsMock) GetCoinData(asset controllers.Asset, currency string) (watchmarket.CoinDetails, error) { - return cm.wantedDetails, nil -} - -func (cm chartsMock) GetProvider() string { - return "coinmarketcap" -} diff --git a/services/controllers/info/base_test.go b/services/controllers/info/base_test.go deleted file mode 100644 index 6433193e..00000000 --- a/services/controllers/info/base_test.go +++ /dev/null @@ -1,182 +0,0 @@ -package infocontroller - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/trustwallet/watchmarket/config" - "github.com/trustwallet/watchmarket/db/models" - "github.com/trustwallet/watchmarket/pkg/watchmarket" - "github.com/trustwallet/watchmarket/services/cache" - "github.com/trustwallet/watchmarket/services/controllers" - "github.com/trustwallet/watchmarket/services/markets" -) - -func TestController_HandleDetailsRequest(t *testing.T) { - cm := getChartsMock() - wantedD := watchmarket.CoinDetails{ - Provider: "coinmarketcap", - Info: &watchmarket.Info{ - Name: "2", - Website: "2", - SourceCode: "2", - WhitePaper: "2", - Description: "2", - ShortDescription: "2", - Research: "2", - Explorer: "2", - Socials: nil, - }, - } - cm.wantedDetails = wantedD - - db := getDbMock() - db.WantedTickers = []models.Ticker{{CirculatingSupply: 1, TotalSupply: 1, MarketCap: 1, Volume: 1, Provider: "coinmarketcap"}} - db.WantedRates = []models.Rate{{Currency: "RUB", Rate: 10, Provider: "coinmarketcap"}} - c := setupController(t, db, getCacheMock(), cm) - assert.NotNil(t, c) - details, err := c.HandleInfoRequest(controllers.DetailsRequest{ - Asset: controllers.Asset{ - CoinId: 0, - TokenId: "2", - }, - Currency: "RUB", - }) - assert.Nil(t, err) - assert.Equal(t, controllers.InfoResponse{ - Provider: wantedD.Provider, - ProviderURL: wantedD.ProviderURL, - Vol24: 0.1, - MarketCap: 0.1, - CirculatingSupply: 1, - TotalSupply: 1, - Info: wantedD.Info, - }, details) -} - -func TestNewController(t *testing.T) { - assert.NotNil(t, setupController(t, getDbMock(), getCacheMock(), getChartsMock())) -} - -func setupController(t *testing.T, db dbMock, ch cache.Provider, cm chartsMock) Controller { - c, _ := config.Init("../../../config.yml") - assert.NotNil(t, c) - - ratesPriority := []string{"coinmarketcap"} - coinInfoPriority := []string{"coinmarketcap"} - - chartsAPIs := make(markets.ChartsAPIs, 1) - chartsAPIs[cm.GetProvider()] = cm - - controller := NewController(db, ch, coinInfoPriority, ratesPriority, chartsAPIs) - assert.NotNil(t, controller) - return controller - -} - -func getCacheMock() cache.Provider { - i := cacheMock{} - return i -} - -type cacheMock struct { -} - -func (c cacheMock) GetID() string { - return "" -} - -func (c cacheMock) GenerateKey(data string) string { - return "" -} - -func (c cacheMock) Get(key string) ([]byte, error) { - return nil, nil -} - -func (c cacheMock) Set(key string, data []byte) error { - return nil -} - -func (c cacheMock) GetWithTime(key string, time int64) ([]byte, error) { - return nil, nil -} - -func (c cacheMock) SetWithTime(key string, data []byte, time int64) error { - return nil -} - -func (c cacheMock) GetLenOfSavedItems() int { - return 0 -} - -func getChartsMock() chartsMock { - cm := chartsMock{} - return cm -} - -type chartsMock struct { - wantedCharts watchmarket.Chart - wantedDetails watchmarket.CoinDetails -} - -func (cm chartsMock) GetChartData(asset controllers.Asset, currency string, timeStart int64) (watchmarket.Chart, error) { - return cm.wantedCharts, nil -} - -func (cm chartsMock) GetCoinData(asset controllers.Asset, currency string) (watchmarket.CoinDetails, error) { - return cm.wantedDetails, nil -} - -func (cm chartsMock) GetProvider() string { - return "coinmarketcap" -} - -func getDbMock() dbMock { - return dbMock{} -} - -type dbMock struct { - WantedRates []models.Rate - WantedTickers []models.Ticker - WantedTickersError error - WantedRatesError error -} - -func (d dbMock) GetRates(currency string) ([]models.Rate, error) { - res := make([]models.Rate, 0) - for _, r := range d.WantedRates { - if r.Currency == currency { - res = append(res, r) - } - } - return res, d.WantedRatesError -} - -func (d dbMock) AddRates(rates []models.Rate) error { - return nil -} - -func (d dbMock) AddTickers(tickers []models.Ticker) error { - return nil -} - -func (d dbMock) GetRatesByProvider(provider string) ([]models.Rate, error) { - return nil, nil -} - -func (d dbMock) GetAllTickers() ([]models.Ticker, error) { - return nil, nil -} - -func (d dbMock) GetAllRates() ([]models.Rate, error) { - return nil, nil -} - -func (d dbMock) GetTickers(asset []controllers.Asset) ([]models.Ticker, error) { - return d.WantedTickers, d.WantedTickersError -} - -func (d dbMock) GetTickersByQueries(tickerQueries []models.TickerQuery) ([]models.Ticker, error) { - return d.WantedTickers, d.WantedTickersError -} diff --git a/services/controllers/tickers/base_test.go b/services/controllers/tickers/base_test.go deleted file mode 100644 index 8fa3aed4..00000000 --- a/services/controllers/tickers/base_test.go +++ /dev/null @@ -1,249 +0,0 @@ -package tickerscontroller - -import ( - "encoding/json" - "errors" - "sort" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/trustwallet/watchmarket/config" - "github.com/trustwallet/watchmarket/db/models" - "github.com/trustwallet/watchmarket/pkg/watchmarket" - "github.com/trustwallet/watchmarket/services/cache" - "github.com/trustwallet/watchmarket/services/cache/memory" - "github.com/trustwallet/watchmarket/services/controllers" -) - -func TestController_HandleTickersRequest(t *testing.T) { - timeUPD := time.Now() - rate := models.Rate{ - Currency: "USD", - PercentChange24h: 1, - Provider: "coinmarketcap", - Rate: 1, - LastUpdated: timeUPD, - } - rate2 := models.Rate{ - Currency: "USD", - PercentChange24h: 2, - Provider: "coingecko", - Rate: 2, - LastUpdated: timeUPD, - } - rate3 := models.Rate{ - Currency: "USD", - PercentChange24h: 4, - Provider: "fixer", - Rate: 6, - LastUpdated: timeUPD, - } - - ticker60ACMC := models.Ticker{ - Coin: 60, - CoinName: "ETH", - TokenId: "a", - Change24h: 10, - Currency: "USD", - Provider: "coinmarketcap", - Value: 100, - LastUpdated: timeUPD, - } - - ticker60ACG := models.Ticker{ - Coin: 60, - CoinName: "ETH", - TokenId: "a", - Change24h: 10, - Currency: "USD", - Provider: "coingecko", - Value: 100, - LastUpdated: timeUPD, - } - - ticker714ACG := models.Ticker{ - Coin: 714, - CoinName: "BNB", - TokenId: "a", - Change24h: 10, - Currency: "USD", - Provider: "coingecko", - Value: 100, - LastUpdated: timeUPD, - } - - ticker714ABNB := models.Ticker{ - Coin: 714, - CoinName: "BNB", - TokenId: "a", - Change24h: 10, - Currency: "USD", - Provider: "binancedex", - Value: 100, - LastUpdated: timeUPD, - } - - db := getDbMock() - - db.WantedTickersError = nil - db.WantedTickers = []models.Ticker{ticker60ACMC, ticker60ACG, ticker714ACG, ticker714ABNB} - db.WantedRatesError = nil - db.WantedRates = []models.Rate{rate, rate2, rate3} - c := setupController(t, db, false) - assert.NotNil(t, c) - - response, err := c.HandleTickersRequest(controllers.TickerRequest{Currency: "USD", Assets: []controllers.Asset{{CoinId: 60, TokenId: "a"}, {CoinId: 714, TokenId: "a"}}}) - assert.Nil(t, err) - - wantedTicker1 := watchmarket.Ticker{ - Coin: 60, - CoinName: "ETH", - CoinType: "", - Price: watchmarket.Price{ - Change24h: 10, - Currency: "USD", - Provider: "coinmarketcap", - Value: 100, - }, - TokenId: "a", - LastUpdate: timeUPD, - } - wantedTicker2 := watchmarket.Ticker{ - Coin: 714, - CoinName: "BNB", - CoinType: "", - Price: watchmarket.Price{ - Change24h: 10, - Currency: "USD", - Provider: "coingecko", - Value: 100, - }, - TokenId: "a", - LastUpdate: timeUPD, - } - - wantedResp := controllers.TickerResponse{ - Currency: "USD", - Tickers: []watchmarket.Ticker{wantedTicker2, wantedTicker1}, - } - - sort.Slice(wantedResp.Tickers, func(i, j int) bool { - return wantedResp.Tickers[i].Coin < wantedResp.Tickers[j].Coin - }) - sort.Slice(response, func(i, j int) bool { - return response[i].Coin < response[j].Coin - }) - - assert.Equal(t, wantedResp.Tickers, response) - - controllerWithCache := setupController(t, db, true) - assert.NotNil(t, controllerWithCache) - wantedTicker1Raw, err := json.Marshal(&wantedTicker1) - assert.Nil(t, err) - wantedTicker2Raw, err := json.Marshal(&wantedTicker2) - assert.Nil(t, err) - rateRaw, err := json.Marshal(&watchmarket.Rate{ - Currency: "USD", - PercentChange24h: 4, - Provider: "fixer", - Rate: 6, - Timestamp: timeUPD.Unix(), - }) - assert.Nil(t, err) - err = controllerWithCache.cache.Set("c60_ta", wantedTicker1Raw) - assert.Nil(t, err) - err = controllerWithCache.cache.Set("c714_ta", wantedTicker2Raw) - assert.Nil(t, err) - err = controllerWithCache.cache.Set("USD", rateRaw) - assert.Nil(t, err) - - response2, err := controllerWithCache.HandleTickersRequest(controllers.TickerRequest{Currency: "USD", Assets: []controllers.Asset{{CoinId: 60, TokenId: "a"}, {CoinId: 714, TokenId: "a"}}}) - assert.Nil(t, err) - - sort.Slice(response2, func(i, j int) bool { - return response2[i].Coin < response2[j].Coin - }) - for i := range wantedResp.Tickers { - assert.True(t, wantedResp.Tickers[i].LastUpdate.Equal(response2[i].LastUpdate)) - wantedResp.Tickers[i].LastUpdate = response2[i].LastUpdate - } - assert.Equal(t, wantedResp.Tickers, response2) -} - -func TestController_HandleTickersRequest_Negative(t *testing.T) { - db := getDbMock() - - db.WantedTickersError = nil - db.WantedRatesError = errors.New("not found") - c := setupController(t, db, false) - assert.NotNil(t, c) - - _, err := c.HandleTickersRequest(controllers.TickerRequest{}) - assert.Equal(t, err, errors.New(watchmarket.ErrNotFound)) -} - -func TestNewController(t *testing.T) { - assert.NotNil(t, setupController(t, getDbMock(), false)) -} - -func setupController(t *testing.T, d dbMock, useMemoryCache bool) Controller { - c, _ := config.Init("../../../config.yml") - assert.NotNil(t, c) - c.RestAPI.UseMemoryCache = useMemoryCache - - ratesPriority := c.Markets.Priority.Rates - tickerPriority := c.Markets.Priority.Tickers - var ch cache.Provider - if useMemoryCache { - ch = memory.Init() - } - controller := NewController(d, ch, ratesPriority, tickerPriority, c) - assert.NotNil(t, controller) - return controller - -} -func getDbMock() dbMock { - return dbMock{} -} - -type dbMock struct { - WantedRates []models.Rate - WantedTickers []models.Ticker - WantedTickersError error - WantedRatesError error -} - -func (d dbMock) GetRates(currency string) ([]models.Rate, error) { - res := make([]models.Rate, 0) - for _, r := range d.WantedRates { - if r.Currency == currency { - res = append(res, r) - } - } - return res, d.WantedRatesError -} - -func (d dbMock) AddRates(rates []models.Rate) error { - return nil -} - -func (d dbMock) GetRatesByProvider(provider string) ([]models.Rate, error) { - return nil, nil -} - -func (d dbMock) AddTickers(tickers []models.Ticker) error { - return nil -} - -func (d dbMock) GetAllTickers() ([]models.Ticker, error) { - return nil, nil -} - -func (d dbMock) GetAllRates() ([]models.Rate, error) { - return nil, nil -} - -func (d dbMock) GetTickers(assets []controllers.Asset) ([]models.Ticker, error) { - return d.WantedTickers, d.WantedTickersError -} diff --git a/services/controllers/tickers/rates_test.go b/services/controllers/tickers/rates_test.go deleted file mode 100644 index 1823ce9c..00000000 --- a/services/controllers/tickers/rates_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package tickerscontroller - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/trustwallet/watchmarket/db/models" - "github.com/trustwallet/watchmarket/pkg/watchmarket" -) - -func TestController_getRateByPriority(t *testing.T) { - now := time.Now() - rate := models.Rate{ - Currency: "USD", - PercentChange24h: 1, - Provider: "coinmarketcap", - Rate: 1, - LastUpdated: now, - } - rate2 := models.Rate{ - Currency: "USD", - PercentChange24h: 2, - Provider: "coingecko", - Rate: 2, - LastUpdated: now, - } - rate3 := models.Rate{ - Currency: "USD", - PercentChange24h: 4, - Provider: "fixer", - Rate: 6, - LastUpdated: now, - } - - db := getDbMock() - - db.WantedTickersError = nil - db.WantedRatesError = nil - db.WantedRates = []models.Rate{rate, rate2, rate3} - - c := setupController(t, db, false) - assert.NotNil(t, c) - - r, err := c.getRateByPriority("USD") - assert.Nil(t, err) - - assert.Equal(t, watchmarket.Rate{ - Currency: "USD", - PercentChange24h: 4, - Provider: "fixer", - Rate: 6, - Timestamp: now.Unix(), - }, r) -} diff --git a/services/controllers/tickers/tickers_test.go b/services/controllers/tickers/tickers_test.go deleted file mode 100644 index fac6cbd8..00000000 --- a/services/controllers/tickers/tickers_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package tickerscontroller - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/trustwallet/watchmarket/db/models" - "github.com/trustwallet/watchmarket/pkg/watchmarket" - "github.com/trustwallet/watchmarket/services/controllers" -) - -func TestController_getTickersByPriority(t *testing.T) { - ticker60ACMC := models.Ticker{ - Coin: 60, - CoinName: "ETH", - TokenId: "a", - Change24h: 10, - Currency: "USD", - Provider: "coinmarketcap", - Value: 100, - } - - ticker60ACG := models.Ticker{ - Coin: 60, - CoinName: "ETH", - TokenId: "a", - Change24h: 10, - Currency: "USD", - Provider: "coingecko", - Value: 100, - } - - ticker714ACG := models.Ticker{ - Coin: 714, - CoinName: "BNB", - TokenId: "a", - Change24h: 10, - Currency: "USD", - Provider: "coingecko", - Value: 100, - } - - db := getDbMock() - - db.WantedTickersError = nil - db.WantedTickers = []models.Ticker{ticker60ACMC, ticker60ACG, ticker714ACG} - c := setupController(t, db, false) - assert.NotNil(t, c) - - tickers, err := c.getTickersByPriority([]controllers.Asset{{CoinId: 60, TokenId: "A"}, {CoinId: 714, TokenId: "A"}}) - assert.Nil(t, err) - assert.NotNil(t, tickers) - assert.Equal(t, 2, len(tickers)) - - wantedTicker1 := watchmarket.Ticker{ - Coin: 60, - CoinName: "ETH", - CoinType: "", - Price: watchmarket.Price{ - Change24h: 10, - Currency: "USD", - Provider: "coinmarketcap", - Value: 100, - }, - TokenId: "A", - } - wantedTicker2 := watchmarket.Ticker{ - Coin: 714, - CoinName: "BNB", - CoinType: "", - Price: watchmarket.Price{ - Change24h: 10, - Currency: "USD", - Provider: "coingecko", - Value: 100, - }, - TokenId: "a", - } - var counter int - for _, t := range tickers { - if t == wantedTicker1 || t == wantedTicker2 { - counter++ - } - } - assert.Equal(t, 1, counter) - db2 := getDbMock() - db2.WantedTickers = []models.Ticker{ticker60ACMC, ticker60ACG} - c2 := setupController(t, db2, false) - tickers2, err := c2.getTickersByPriority([]controllers.Asset{{CoinId: 60, TokenId: "A"}}) - assert.Nil(t, err) - assert.NotNil(t, tickers2) - assert.Equal(t, 1, len(tickers2)) - assert.Equal(t, wantedTicker1, tickers2[0]) -} From 2cff93603146736f19fcfeca3149d7630905a08f Mon Sep 17 00:00:00 2001 From: Maksim Rasputin <133312+madcake@users.noreply.github.com> Date: Mon, 22 Mar 2021 12:46:57 +0700 Subject: [PATCH 5/6] Clean code --- services/controllers/charts/base.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/services/controllers/charts/base.go b/services/controllers/charts/base.go index 52c85894..61e417aa 100644 --- a/services/controllers/charts/base.go +++ b/services/controllers/charts/base.go @@ -64,12 +64,11 @@ func (c Controller) HandleChartsRequest(request controllers.ChartRequest) (chart } func (c Controller) hasTickers(assetData controllers.Asset) bool { - var tickers []models.Ticker - var err error - if tickers, err = c.getChartsFromMemory(assetData); err != nil { + if tickers, err := c.getChartsFromMemory(assetData); err != nil { return false + } else { + return len(tickers) > 0 } - return len(tickers) > 0 } func (c Controller) getChartsFromApi(data controllers.ChartRequest) (ch watchmarket.Chart, err error) { From 5d7cb30b14ef9dcaa1d78b1d33dcd51a452f8a4e Mon Sep 17 00:00:00 2001 From: Maksim Rasputin <133312+madcake@users.noreply.github.com> Date: Sun, 28 Mar 2021 10:10:59 +0700 Subject: [PATCH 6/6] Return db to Info calls --- cmd/api/main.go | 2 +- services/controllers/info/base.go | 60 +++++--- services/controllers/info/base_test.go | 182 +++++++++++++++++++++++++ 3 files changed, 226 insertions(+), 18 deletions(-) create mode 100644 services/controllers/info/base_test.go diff --git a/cmd/api/main.go b/cmd/api/main.go index 443938a2..9d04c32d 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -90,7 +90,7 @@ func init() { } charts = chartscontroller.NewController(redisCache, memoryCache, chartsPriority, m.ChartsAPIs) - info = infocontroller.NewController(memoryCache, coinInfoPriority, ratesPriority, m.ChartsAPIs) + info = infocontroller.NewController(database, memoryCache, coinInfoPriority, ratesPriority, m.ChartsAPIs) tickers = tickerscontroller.NewController(database, memoryCache, ratesPriority, tickerPriority, configuration) rates = ratescontroller.NewController(database, memoryCache, ratesPriority, configuration) } diff --git a/services/controllers/info/base.go b/services/controllers/info/base.go index 0969f713..8527bda6 100644 --- a/services/controllers/info/base.go +++ b/services/controllers/info/base.go @@ -5,17 +5,18 @@ import ( "errors" "fmt" log "github.com/sirupsen/logrus" - "github.com/trustwallet/golibs/asset" + "github.com/trustwallet/watchmarket/db" + "github.com/trustwallet/watchmarket/db/models" "github.com/trustwallet/watchmarket/pkg/watchmarket" "github.com/trustwallet/watchmarket/services/cache" "github.com/trustwallet/watchmarket/services/controllers" "github.com/trustwallet/watchmarket/services/markets" - "strings" ) const info = "info" type Controller struct { + database db.Instance cache cache.Provider coinInfoPriority []string ratesPriority []string @@ -23,12 +24,14 @@ type Controller struct { } func NewController( + database db.Instance, cache cache.Provider, coinInfoPriority []string, ratesPriority []string, api markets.ChartsAPIs, ) Controller { return Controller{ + database, cache, coinInfoPriority, ratesPriority, @@ -89,14 +92,15 @@ func (c Controller) getFromCache(request controllers.DetailsRequest) (controller } func (c Controller) getDetailsByPriority(request controllers.DetailsRequest) (controllers.InfoResponse, error) { - key := strings.ToLower(asset.BuildID(request.Asset.CoinId, request.Asset.TokenId)) - rawResult, err := c.cache.Get(key) - if err != nil { - return controllers.InfoResponse{}, errors.New(watchmarket.ErrNotFound) + dbTickers, err := c.database.GetTickers([]controllers.Asset{request.Asset}) + + if err != nil || len(dbTickers) == 0 { + return controllers.InfoResponse{}, fmt.Errorf("no tickers in db or db error: %w", err) } - var ticker watchmarket.Ticker - if err = json.Unmarshal(rawResult, &ticker); err != nil { - return controllers.InfoResponse{}, errors.New(watchmarket.ErrNotFound) + + ticker, err := c.getTickerDataAccordingToPriority(dbTickers) + if err != nil { + return controllers.InfoResponse{}, err } result := c.getCoinDataFromApi(request.Asset, request.Currency) result.CirculatingSupply = ticker.CirculatingSupply @@ -105,16 +109,16 @@ func (c Controller) getDetailsByPriority(request controllers.DetailsRequest) (co result.TotalSupply = ticker.TotalSupply if request.Currency != watchmarket.DefaultCurrency { - rateRaw, err := c.cache.Get(request.Currency) - var rate watchmarket.Rate - if err != nil { - return controllers.InfoResponse{}, errors.New(watchmarket.ErrNotFound) + rates, err := c.database.GetRates(request.Currency) + if err != nil || len(rates) == 0 { + return controllers.InfoResponse{}, fmt.Errorf("empty db rate or db error: %w", err) } - if err = json.Unmarshal(rateRaw, &rate); err != nil { - return result, err + rate, err := c.getRateDataAccordingToPriority(rates) + if err != nil { + return controllers.InfoResponse{}, err } - result.MarketCap *= 1 / rate.Rate - result.Vol24 *= 1 / rate.Rate + result.MarketCap *= 1 / rate + result.Vol24 *= 1 / rate } return result, nil } @@ -132,3 +136,25 @@ func (c Controller) getCoinDataFromApi(assetData controllers.Asset, currency str } return result } + +func (c Controller) getTickerDataAccordingToPriority(tickers []models.Ticker) (models.Ticker, error) { + for _, p := range c.coinInfoPriority { + for _, t := range tickers { + if t.Provider == p && t.ShowOption != models.NeverShow { + return t, nil + } + } + } + return models.Ticker{}, errors.New("bad ticker or providers") +} + +func (c Controller) getRateDataAccordingToPriority(rates []models.Rate) (float64, error) { + for _, p := range c.ratesPriority { + for _, r := range rates { + if r.Provider == p && r.ShowOption != models.NeverShow { + return r.Rate, nil + } + } + } + return 0, errors.New("bad ticker or providers") +} diff --git a/services/controllers/info/base_test.go b/services/controllers/info/base_test.go new file mode 100644 index 00000000..6433193e --- /dev/null +++ b/services/controllers/info/base_test.go @@ -0,0 +1,182 @@ +package infocontroller + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/trustwallet/watchmarket/config" + "github.com/trustwallet/watchmarket/db/models" + "github.com/trustwallet/watchmarket/pkg/watchmarket" + "github.com/trustwallet/watchmarket/services/cache" + "github.com/trustwallet/watchmarket/services/controllers" + "github.com/trustwallet/watchmarket/services/markets" +) + +func TestController_HandleDetailsRequest(t *testing.T) { + cm := getChartsMock() + wantedD := watchmarket.CoinDetails{ + Provider: "coinmarketcap", + Info: &watchmarket.Info{ + Name: "2", + Website: "2", + SourceCode: "2", + WhitePaper: "2", + Description: "2", + ShortDescription: "2", + Research: "2", + Explorer: "2", + Socials: nil, + }, + } + cm.wantedDetails = wantedD + + db := getDbMock() + db.WantedTickers = []models.Ticker{{CirculatingSupply: 1, TotalSupply: 1, MarketCap: 1, Volume: 1, Provider: "coinmarketcap"}} + db.WantedRates = []models.Rate{{Currency: "RUB", Rate: 10, Provider: "coinmarketcap"}} + c := setupController(t, db, getCacheMock(), cm) + assert.NotNil(t, c) + details, err := c.HandleInfoRequest(controllers.DetailsRequest{ + Asset: controllers.Asset{ + CoinId: 0, + TokenId: "2", + }, + Currency: "RUB", + }) + assert.Nil(t, err) + assert.Equal(t, controllers.InfoResponse{ + Provider: wantedD.Provider, + ProviderURL: wantedD.ProviderURL, + Vol24: 0.1, + MarketCap: 0.1, + CirculatingSupply: 1, + TotalSupply: 1, + Info: wantedD.Info, + }, details) +} + +func TestNewController(t *testing.T) { + assert.NotNil(t, setupController(t, getDbMock(), getCacheMock(), getChartsMock())) +} + +func setupController(t *testing.T, db dbMock, ch cache.Provider, cm chartsMock) Controller { + c, _ := config.Init("../../../config.yml") + assert.NotNil(t, c) + + ratesPriority := []string{"coinmarketcap"} + coinInfoPriority := []string{"coinmarketcap"} + + chartsAPIs := make(markets.ChartsAPIs, 1) + chartsAPIs[cm.GetProvider()] = cm + + controller := NewController(db, ch, coinInfoPriority, ratesPriority, chartsAPIs) + assert.NotNil(t, controller) + return controller + +} + +func getCacheMock() cache.Provider { + i := cacheMock{} + return i +} + +type cacheMock struct { +} + +func (c cacheMock) GetID() string { + return "" +} + +func (c cacheMock) GenerateKey(data string) string { + return "" +} + +func (c cacheMock) Get(key string) ([]byte, error) { + return nil, nil +} + +func (c cacheMock) Set(key string, data []byte) error { + return nil +} + +func (c cacheMock) GetWithTime(key string, time int64) ([]byte, error) { + return nil, nil +} + +func (c cacheMock) SetWithTime(key string, data []byte, time int64) error { + return nil +} + +func (c cacheMock) GetLenOfSavedItems() int { + return 0 +} + +func getChartsMock() chartsMock { + cm := chartsMock{} + return cm +} + +type chartsMock struct { + wantedCharts watchmarket.Chart + wantedDetails watchmarket.CoinDetails +} + +func (cm chartsMock) GetChartData(asset controllers.Asset, currency string, timeStart int64) (watchmarket.Chart, error) { + return cm.wantedCharts, nil +} + +func (cm chartsMock) GetCoinData(asset controllers.Asset, currency string) (watchmarket.CoinDetails, error) { + return cm.wantedDetails, nil +} + +func (cm chartsMock) GetProvider() string { + return "coinmarketcap" +} + +func getDbMock() dbMock { + return dbMock{} +} + +type dbMock struct { + WantedRates []models.Rate + WantedTickers []models.Ticker + WantedTickersError error + WantedRatesError error +} + +func (d dbMock) GetRates(currency string) ([]models.Rate, error) { + res := make([]models.Rate, 0) + for _, r := range d.WantedRates { + if r.Currency == currency { + res = append(res, r) + } + } + return res, d.WantedRatesError +} + +func (d dbMock) AddRates(rates []models.Rate) error { + return nil +} + +func (d dbMock) AddTickers(tickers []models.Ticker) error { + return nil +} + +func (d dbMock) GetRatesByProvider(provider string) ([]models.Rate, error) { + return nil, nil +} + +func (d dbMock) GetAllTickers() ([]models.Ticker, error) { + return nil, nil +} + +func (d dbMock) GetAllRates() ([]models.Rate, error) { + return nil, nil +} + +func (d dbMock) GetTickers(asset []controllers.Asset) ([]models.Ticker, error) { + return d.WantedTickers, d.WantedTickersError +} + +func (d dbMock) GetTickersByQueries(tickerQueries []models.TickerQuery) ([]models.Ticker, error) { + return d.WantedTickers, d.WantedTickersError +}