From fdc96648425e168f21b96092555861c70d0397d2 Mon Sep 17 00:00:00 2001 From: Vuong <3168632+vuon9@users.noreply.github.com> Date: Wed, 17 Nov 2021 03:42:29 +0700 Subject: [PATCH] Fix/coin link (#275) --- cointop/coin.go | 45 ++++++++++++++++++++- cointop/list.go | 8 +++- cointop/table.go | 11 ++++- pkg/api/impl/coingecko/coingecko.go | 9 ++--- pkg/api/impl/coinmarketcap/coinmarketcap.go | 8 ++-- pkg/api/interface.go | 2 +- pkg/api/types/types.go | 2 + pkg/api/util/util.go | 4 ++ 8 files changed, 75 insertions(+), 14 deletions(-) diff --git a/cointop/coin.go b/cointop/coin.go index 861f7cb..8d2526e 100644 --- a/cointop/coin.go +++ b/cointop/coin.go @@ -1,6 +1,10 @@ package cointop -import log "github.com/sirupsen/logrus" +import ( + "errors" + + log "github.com/sirupsen/logrus" +) // Coin is the row structure type Coin struct { @@ -92,3 +96,42 @@ func (ct *Cointop) CoinByID(id string) *Coin { } return nil } + +// UpdateCoin updates coin info after fetching from API +func (ct *Cointop) UpdateCoin(coin *Coin) error { + log.Debug("UpdateCoin()") + v, err := ct.api.GetCoinData(coin.Name, ct.State.currencyConversion) + if err != nil { + log.Debugf("UpdateCoin() could not fetch coin data %s", coin.Name) + return err + } + + k, found := ct.State.allCoinsSlugMap.Load(coin.Name) + if !found { + log.Debugf("UpdateCoin() could not found coin %s in the slug map", coin.Name) + return errors.New("could not find coin index in allCoinsSlugMap") + } + + coin = &Coin{ + ID: v.ID, + Name: v.Name, + Symbol: v.Symbol, + Rank: v.Rank, + Price: v.Price, + Volume24H: v.Volume24H, + MarketCap: v.MarketCap, + AvailableSupply: v.AvailableSupply, + TotalSupply: v.TotalSupply, + PercentChange1H: v.PercentChange1H, + PercentChange24H: v.PercentChange24H, + PercentChange7D: v.PercentChange7D, + PercentChange30D: v.PercentChange30D, + PercentChange1Y: v.PercentChange1Y, + LastUpdated: v.LastUpdated, + Slug: v.Slug, + } + + ct.State.allCoinsSlugMap.Store(k, coin) + + return nil +} diff --git a/cointop/list.go b/cointop/list.go index ff66e6a..12081d5 100644 --- a/cointop/list.go +++ b/cointop/list.go @@ -8,8 +8,10 @@ import ( log "github.com/sirupsen/logrus" ) -var coinslock sync.Mutex -var updatecoinsmux sync.Mutex +var ( + coinslock sync.Mutex + updatecoinsmux sync.Mutex +) // UpdateCoins updates coins view func (ct *Cointop) UpdateCoins() error { @@ -110,6 +112,7 @@ func (ct *Cointop) processCoins(coins []types.Coin) { PercentChange30D: v.PercentChange30D, PercentChange1Y: v.PercentChange1Y, LastUpdated: v.LastUpdated, + Slug: v.Slug, }) if ilast != nil { last, _ := ilast.(*Coin) @@ -162,6 +165,7 @@ func (ct *Cointop) processCoins(coins []types.Coin) { c.PercentChange1Y = cm.PercentChange1Y c.LastUpdated = cm.LastUpdated c.Favorite = cm.Favorite + c.Slug = cm.Slug } } diff --git a/cointop/table.go b/cointop/table.go index bfdf8ab..b8477d6 100644 --- a/cointop/table.go +++ b/cointop/table.go @@ -197,7 +197,16 @@ func (ct *Cointop) RowLink() string { return "" } - return ct.api.CoinLink(coin.Name) + // TODO: Can remove this one after some releases + // because it is a way to force old client refresh coin to have a slug + if coin.Slug == "" { + if err := ct.UpdateCoin(coin); err != nil { + log.Debugf("RowLink() Update coin got err %s", err.Error()) + return "" + } + } + + return ct.api.CoinLink(coin.Slug) } // RowLinkShort returns a shortened version of the row url link diff --git a/pkg/api/impl/coingecko/coingecko.go b/pkg/api/impl/coingecko/coingecko.go index 5f548b3..049d062 100644 --- a/pkg/api/impl/coingecko/coingecko.go +++ b/pkg/api/impl/coingecko/coingecko.go @@ -267,15 +267,13 @@ func (s *Service) Price(name string, convert string) (float64, error) { return 0, ErrNotFound } -// CoinLink returns the URL link for the coin -func (s *Service) CoinLink(name string) string { - ID := s.coinNameToID(name) - return fmt.Sprintf("https://www.coingecko.com/en/coins/%s", ID) +func (s *Service) CoinLink(slug string) string { + // slug is API ID of coin + return fmt.Sprintf("https://www.coingecko.com/en/coins/%s", slug) } // SupportedCurrencies returns a list of supported currencies func (s *Service) SupportedCurrencies() []string { - // keep these in alphabetical order return []string{ "AED", @@ -462,6 +460,7 @@ func (s *Service) getPaginatedCoinData(convert string, offset int, names []strin PercentChange1Y: util.FormatPercentChange(percentChange1Y), Volume24H: util.FormatVolume(item.TotalVolume), LastUpdated: util.FormatLastUpdated(item.LastUpdated), + Slug: util.FormatSlug(item.ID), }) } } diff --git a/pkg/api/impl/coinmarketcap/coinmarketcap.go b/pkg/api/impl/coinmarketcap/coinmarketcap.go index 71a7b73..0aa28bd 100644 --- a/pkg/api/impl/coinmarketcap/coinmarketcap.go +++ b/pkg/api/impl/coinmarketcap/coinmarketcap.go @@ -77,6 +77,7 @@ func (s *Service) getPaginatedCoinData(convert string, offset int) ([]apitypes.C } ret = append(ret, apitypes.Coin{ + // TODO: Fix ID ID: util.FormatID(v.Name), Name: util.FormatName(v.Name), Symbol: util.FormatSymbol(v.Symbol), @@ -90,6 +91,7 @@ func (s *Service) getPaginatedCoinData(convert string, offset int) ([]apitypes.C PercentChange7D: util.FormatPercentChange(quote.PercentChange7D), Volume24H: util.FormatVolume(v.Quote[convert].Volume24H), LastUpdated: util.FormatLastUpdated(v.LastUpdated), + Slug: util.FormatSlug(v.Slug), }) } return ret, nil @@ -297,7 +299,6 @@ func (s *Service) GetGlobalMarketData(convert string) (apitypes.GlobalMarketData market, err := s.client.GlobalMetrics.LatestQuotes(&cmc.QuoteOptions{ Convert: convert, }) - if err != nil { return ret, err } @@ -332,9 +333,8 @@ func (s *Service) Price(name string, convert string) (float64, error) { } // CoinLink returns the URL link for the coin -func (s *Service) CoinLink(name string) string { - slug := util.NameToSlug(name) - return fmt.Sprintf("https://coinmarketcap.com/currencies/%s", slug) +func (s *Service) CoinLink(slug string) string { + return fmt.Sprintf("https://coinmarketcap.com/currencies/%s/", slug) } // SupportedCurrencies returns a list of supported currencies diff --git a/pkg/api/interface.go b/pkg/api/interface.go index 55ffcf2..206b549 100644 --- a/pkg/api/interface.go +++ b/pkg/api/interface.go @@ -13,7 +13,7 @@ type Interface interface { GetGlobalMarketData(convert string) (types.GlobalMarketData, error) GetCoinData(name string, convert string) (types.Coin, error) GetCoinDataBatch(names []string, convert string) ([]types.Coin, error) - CoinLink(name string) string + CoinLink(slug string) string SupportedCurrencies() []string Price(name string, convert string) (float64, error) GetExchangeRate(convertFrom, convertTo string, cached bool) (float64, error) // I don't love this caching diff --git a/pkg/api/types/types.go b/pkg/api/types/types.go index 3e4bf37..a5fb5f7 100644 --- a/pkg/api/types/types.go +++ b/pkg/api/types/types.go @@ -17,6 +17,8 @@ type Coin struct { PercentChange30D float64 `json:"percentChange30D"` PercentChange1Y float64 `json:"percentChange1Y"` LastUpdated string `json:"lastUpdated"` + // Slug uses to access the coin's info web page + Slug string `json:"slug"` } // GlobalMarketData struct diff --git a/pkg/api/util/util.go b/pkg/api/util/util.go index ffb52db..f0af4d7 100644 --- a/pkg/api/util/util.go +++ b/pkg/api/util/util.go @@ -29,6 +29,10 @@ func FormatName(name string) string { return name } +func FormatSlug(slug string) string { + return slug +} + // FormatRank formats the rank value func FormatRank(rank interface{}) int { switch v := rank.(type) {