Skip to content

Commit

Permalink
feat: use custom coingecko client (#9)
Browse files Browse the repository at this point in the history
* feat: use custom coingecko client

* chore: fixed linting errors

* chore: pass chain to args
  • Loading branch information
freak12techno authored Apr 10, 2023
1 parent 783ebde commit 49012a9
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 57 deletions.
2 changes: 1 addition & 1 deletion pkg/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (

type App struct {
Config *config.Config
Logger *zerolog.Logger
Logger zerolog.Logger
Queriers []types.Querier
}

Expand Down
29 changes: 19 additions & 10 deletions pkg/coingecko/coingecko.go
Original file line number Diff line number Diff line change
@@ -1,47 +1,56 @@
package coingecko

import (
"fmt"
"main/pkg/config"
"main/pkg/http"
"main/pkg/types"
"strings"

"github.com/rs/zerolog"
gecko "github.com/superoo7/go-gecko/v3"
)

type Response map[string]map[string]float64

type Coingecko struct {
Client *gecko.Client
Client *http.Client
Config *config.Config
Logger zerolog.Logger
}

func NewCoingecko(appConfig *config.Config, logger *zerolog.Logger) *Coingecko {
func NewCoingecko(appConfig *config.Config, logger zerolog.Logger) *Coingecko {
return &Coingecko{
Config: appConfig,
Client: gecko.NewClient(nil),
Client: http.NewClient(logger, "coingecko"),
Logger: logger.With().Str("component", "coingecko").Logger(),
}
}

func (c *Coingecko) FetchPrices(currencies []string) map[string]float64 {
result, err := c.Client.SimplePrice(currencies, []string{"USD"})
func (c *Coingecko) FetchPrices(currencies []string) (map[string]float64, types.QueryInfo) {
ids := strings.Join(currencies, ",")
url := fmt.Sprintf("https://api.coingecko.com/api/v3/simple/price?ids=%s&vs_currencies=usd", ids)

var response Response
queryInfo, err := c.Client.Get(url, &response)
if err != nil {
c.Logger.Error().Err(err).Msg("Could not get rate")
return map[string]float64{}
return nil, queryInfo
}

prices := map[string]float64{}

for currencyKey, currencyValue := range *result {
for currencyKey, currencyValue := range response {
for _, baseCurrencyValue := range currencyValue {
chain, found := c.Config.FindChainByCoingeckoCurrency(currencyKey)
if !found {
c.Logger.Warn().
Str("currency", currencyKey).
Msg("Could not find chain by coingecko currency, which should never happen.")
} else {
prices[chain.Name] = float64(baseCurrencyValue)
prices[chain.Name] = baseCurrencyValue
}
}
}

return prices
return prices, queryInfo
}
57 changes: 57 additions & 0 deletions pkg/http/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package http

import (
"encoding/json"
"main/pkg/types"

Check failure on line 5 in pkg/http/http.go

View workflow job for this annotation

GitHub Actions / lint

import 'main/pkg/types' is not allowed from list 'Main' (depguard)
"net/http"
"time"

"github.com/rs/zerolog"

Check failure on line 9 in pkg/http/http.go

View workflow job for this annotation

GitHub Actions / lint

import 'github.com/rs/zerolog' is not allowed from list 'Main' (depguard)
)

type Client struct {
logger zerolog.Logger
chain string
}

func NewClient(logger zerolog.Logger, chain string) *Client {
return &Client{
logger: logger.With().Str("component", "http").Logger(),
chain: chain,
}
}

func (c *Client) Get(url string, target interface{}) (types.QueryInfo, error) {
client := &http.Client{Timeout: 10 * 1000000000}
start := time.Now()

queryInfo := types.QueryInfo{
Success: false,
Chain: c.chain,
URL: url,
}

req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return queryInfo, err
}

req.Header.Set("User-Agent", "cosmos-wallets-exporter")

c.logger.Debug().Str("url", url).Msg("Doing a query...")

res, err := client.Do(req)
queryInfo.Duration = time.Since(start)
if err != nil {
c.logger.Warn().Str("url", url).Err(err).Msg("Query failed")
return queryInfo, err
}
defer res.Body.Close()

c.logger.Debug().Str("url", url).Dur("duration", time.Since(start)).Msg("Query is finished")

err = json.NewDecoder(res.Body).Decode(target)
queryInfo.Success = err == nil

return queryInfo, err
}
4 changes: 2 additions & 2 deletions pkg/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func GetDefaultLogger() *zerolog.Logger {
return &log
}

func GetLogger(config config.LogConfig) *zerolog.Logger {
func GetLogger(config config.LogConfig) zerolog.Logger {
log := zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout}).With().Timestamp().Logger()

if config.JSONOutput {
Expand All @@ -25,5 +25,5 @@ func GetLogger(config config.LogConfig) *zerolog.Logger {
}

zerolog.SetGlobalLevel(logLevel)
return &log
return log
}
2 changes: 1 addition & 1 deletion pkg/queriers/balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type BalanceQuerier struct {
Logger zerolog.Logger
}

func NewBalanceQuerier(config *config.Config, logger *zerolog.Logger) *BalanceQuerier {
func NewBalanceQuerier(config *config.Config, logger zerolog.Logger) *BalanceQuerier {
return &BalanceQuerier{
Config: config,
Logger: logger.With().Str("component", "balance_querier").Logger(),
Expand Down
4 changes: 2 additions & 2 deletions pkg/queriers/price.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ func (q *PriceQuerier) GetMetrics() ([]prometheus.Collector, []types.QueryInfo)
)

currenciesList := q.Config.GetCoingeckoCurrencies()
currenciesRates := q.Coingecko.FetchPrices(currenciesList)
currenciesRates, queryInfo := q.Coingecko.FetchPrices(currenciesList)

for chain, price := range currenciesRates {
priceGauge.With(prometheus.Labels{
"chain": chain,
}).Set(price)
}

return []prometheus.Collector{priceGauge}, []types.QueryInfo{}
return []prometheus.Collector{priceGauge}, []types.QueryInfo{queryInfo}
}
45 changes: 4 additions & 41 deletions pkg/tendermint/tendermint.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
package tendermint

import (
"encoding/json"
"fmt"
"main/pkg/config"
"main/pkg/http"
"main/pkg/types"
"net/http"
"time"

"github.com/rs/zerolog"
)

type RPC struct {
Chain string
Client *http.Client
URL string
Logger zerolog.Logger
}

func NewRPC(chain config.Chain, logger zerolog.Logger) *RPC {
return &RPC{
Chain: chain.Name,
Client: http.NewClient(logger, chain.Name),
URL: chain.LCDEndpoint,
Logger: logger.With().Str("component", "rpc").Logger(),
}
Expand All @@ -33,45 +31,10 @@ func (rpc *RPC) GetWalletBalances(address string) (*types.BalanceResponse, types
)

var response *types.BalanceResponse
queryInfo, err := rpc.Get(url, &response)
queryInfo, err := rpc.Client.Get(url, &response)
if err != nil {
return nil, queryInfo, err
}

return response, queryInfo, nil
}

func (rpc *RPC) Get(url string, target interface{}) (types.QueryInfo, error) {
client := &http.Client{Timeout: 10 * 1000000000}
start := time.Now()

queryInfo := types.QueryInfo{
Success: false,
Chain: rpc.Chain,
URL: url,
}

req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return queryInfo, err
}

req.Header.Set("User-Agent", "cosmos-wallets-exporter")

rpc.Logger.Debug().Str("url", url).Msg("Doing a query...")

res, err := client.Do(req)
queryInfo.Duration = time.Since(start)
if err != nil {
rpc.Logger.Warn().Str("url", url).Err(err).Msg("Query failed")
return queryInfo, err
}
defer res.Body.Close()

rpc.Logger.Debug().Str("url", url).Dur("duration", time.Since(start)).Msg("Query is finished")

err = json.NewDecoder(res.Body).Decode(target)
queryInfo.Success = err == nil

return queryInfo, err
}

0 comments on commit 49012a9

Please sign in to comment.