Compare commits

..

No commits in common. '409479636d26b88a57c1265e584c07ff4debb5af' and '6a17ed2d3caeb9c07d6bf7e3eaf659f5b1eb9cfc' have entirely different histories.

@ -94,7 +94,7 @@ Cointop has been mentioned in:
[![BTC Tip Jar](https://img.shields.io/badge/BTC-tip-yellow.svg?logo=bitcoin&style=flat)](https://www.blockchain.com/btc/address/3KdMW53vUMLPEC33xhHAUx4EFtvmXQF8Kf) `3KdMW53vUMLPEC33xhHAUx4EFtvmXQF8Kf`
[![ETH Tip Jar](https://img.shields.io/badge/ETH-tip-blue.svg?logo=ethereum&style=flat)](https://etherscan.io/address/0xC014b8F6F43f467922E93De62C9216F0538E0F8f) `0xC014b8F6F43f467922E93De62C9216F0538E0F8f`
[![ETH Tip Jar](https://img.shields.io/badge/ETH-tip-blue.svg?logo=ethereum&style=flat)](https://etherscan.io/address/0x9ed3D6793a6b74d8c9A998f5C4b50a25947D53aF) `0x9ed3D6793a6b74d8c9A998f5C4b50a25947D53aF`
Thank you for tips! 🙏

@ -31,7 +31,6 @@ func RootCmd() *cobra.Command {
config := os.Getenv("COINTOP_CONFIG")
apiChoice := os.Getenv("COINTOP_API")
cmcAPIKey := os.Getenv("CMC_PRO_API_KEY")
coingeckoAPIKey := os.Getenv("COINGECKO_PRO_API_KEY")
perPage := cointop.DefaultPerPage
maxPages := cointop.DefaultMaxPages
@ -103,7 +102,6 @@ See git.io/cointop for more info.`,
NoCache: noCache,
ConfigFilepath: config,
CoinMarketCapAPIKey: cmcAPIKey,
CoinGeckoAPIKey: coingeckoAPIKey,
APIChoice: apiChoice,
Colorscheme: colorscheme,
HideMarketbar: hideMarketbar,
@ -142,8 +140,7 @@ See git.io/cointop for more info.`,
rootCmd.Flags().UintVarP(&perPage, "per-page", "", perPage, "Per page")
rootCmd.Flags().UintVarP(&maxPages, "max-pages", "", maxPages, "Max number of pages")
rootCmd.Flags().StringVarP(&config, "config", "c", config, fmt.Sprintf("Config filepath. (default %s)", cointop.DefaultConfigFilepath))
rootCmd.Flags().StringVarP(&cmcAPIKey, "coinmarketcap-api-key", "", cmcAPIKey, "Set the CoinMarketCap Pro API key")
rootCmd.Flags().StringVarP(&coingeckoAPIKey, "coingecko-api-key", "", coingeckoAPIKey, "Set the CoinGecko Pro API key")
rootCmd.Flags().StringVarP(&cmcAPIKey, "coinmarketcap-api-key", "", cmcAPIKey, "Set the CoinMarketCap API key")
rootCmd.Flags().StringVarP(&apiChoice, "api", "", apiChoice, "API choice. Available choices are \"coinmarketcap\" and \"coingecko\"")
rootCmd.Flags().StringVarP(&colorscheme, "colorscheme", "", colorscheme, fmt.Sprintf("Colorscheme to use (default \"cointop\").\n%s", cointop.ColorschemeHelpString()))
rootCmd.Flags().StringVarP(&cacheDir, "cache-dir", "", cacheDir, fmt.Sprintf("Cache directory (default %s)", cointop.DefaultCacheDir))

@ -169,7 +169,6 @@ type Config struct {
Colorscheme string
ConfigFilepath string
CoinMarketCapAPIKey string
CoinGeckoAPIKey string
NoPrompts bool
HideMarketbar bool
HideChart bool
@ -186,8 +185,7 @@ type Config struct {
// APIKeys is api keys structure
type APIKeys struct {
cmc string
coingecko string
cmc string
}
// DefaultCurrency ...
@ -385,14 +383,6 @@ func NewCointop(config *Config) (*Cointop, error) {
}
}
// prompt for CoinGecko api key if not found
if config.CoinGeckoAPIKey != "" {
ct.apiKeys.coingecko = config.CoinGeckoAPIKey
if err := ct.SaveConfig(); err != nil {
return nil, err
}
}
if config.Colorscheme != "" {
ct.colorschemeName = config.Colorscheme
}
@ -430,34 +420,10 @@ func NewCointop(config *Config) (*Cointop, error) {
}
}
if ct.apiChoice == CoinGecko && ct.apiKeys.coingecko == "" {
apiKey := os.Getenv("COINGECKO_PRO_API_KEY")
if apiKey == "" {
// if !config.NoPrompts {
// apiKey, err = ct.ReadAPIKeyFromStdin("CoinGecko Pro")
// if err != nil {
// return nil, err
// }
// ct.apiKeys.coingecko = apiKey
// }
} else {
ct.apiKeys.coingecko = apiKey
}
if err := ct.SaveConfig(); err != nil {
return nil, err
}
}
if ct.apiChoice == CoinMarketCap {
ct.api = api.NewCMC(ct.apiKeys.cmc)
} else if ct.apiChoice == CoinGecko {
ct.api = api.NewCG(&api.CoinGeckoConfig{
PerPage: perPage,
MaxPages: maxPages,
ApiKey: ct.apiKeys.coingecko,
})
ct.api = api.NewCG(perPage, maxPages)
} else {
return nil, ErrInvalidAPIChoice
}

@ -44,7 +44,6 @@ type ConfigFileConfig struct {
DefaultView interface{} `toml:"default_view"`
DefaultChartRange interface{} `toml:"default_chart_range"`
CoinMarketCap map[string]interface{} `toml:"coinmarketcap"`
CoinGecko map[string]interface{} `toml:"coingecko"`
API interface{} `toml:"api"`
Colorscheme interface{} `toml:"colorscheme"`
RefreshRate interface{} `toml:"refresh_rate"`
@ -254,10 +253,6 @@ func (ct *Cointop) ConfigToToml() ([]byte, error) {
"pro_api_key": ct.apiKeys.cmc,
}
coingeckoIfc := map[string]interface{}{
"pro_api_key": ct.apiKeys.coingecko,
}
var priceAlertsIfc []interface{}
for _, priceAlert := range ct.State.priceAlerts.Entries {
if priceAlert.Expired {
@ -292,7 +287,6 @@ func (ct *Cointop) ConfigToToml() ([]byte, error) {
API: ct.apiChoice,
Colorscheme: ct.colorschemeName,
CoinMarketCap: cmcIfc,
CoinGecko: coingeckoIfc,
Currency: ct.State.currencyConversion,
DefaultView: ct.State.defaultView,
DefaultChartRange: ct.State.defaultChartRange,
@ -482,12 +476,6 @@ func (ct *Cointop) loadAPIKeysFromConfig() error {
ct.apiKeys.cmc = value.(string)
}
}
for key, value := range ct.config.CoinGecko {
k := strings.TrimSpace(strings.ToLower(key))
if k == "pro_api_key" {
ct.apiKeys.coingecko = value.(string)
}
}
return nil
}
@ -553,7 +541,7 @@ func (ct *Cointop) loadAltCoinLinkFromConfig() error {
// LoadAPIChoiceFromConfig loads API choices from config file to struct
func (ct *Cointop) loadAPIChoiceFromConfig() error {
log.Debug("loadAPIChoiceFromConfig()")
log.Debug("loadAPIKeysFromConfig()")
apiChoice, ok := ct.config.API.(string)
if ok {
apiChoice = strings.TrimSpace(strings.ToLower(apiChoice))

@ -2,7 +2,6 @@ package cointop
import (
"fmt"
"os"
"github.com/cointop-sh/cointop/pkg/api"
)
@ -23,9 +22,7 @@ func PrintBitcoinDominance(config *DominanceConfig) error {
if config.APIChoice == CoinMarketCap {
coinAPI = api.NewCMC("")
} else if config.APIChoice == CoinGecko {
coinAPI = api.NewCG(&api.CoinGeckoConfig{
ApiKey: os.Getenv("COINGECKO_PRO_API_KEY"),
})
coinAPI = api.NewCG(0, 0)
} else {
return ErrInvalidAPIChoice
}

@ -3,7 +3,6 @@ package cointop
import (
"fmt"
"math"
"os"
"strings"
"github.com/cointop-sh/cointop/pkg/api"
@ -58,9 +57,7 @@ func GetCoinPrices(config *PricesConfig) ([]string, error) {
if config.APIChoice == CoinMarketCap {
priceAPI = api.NewCMC("")
} else if config.APIChoice == CoinGecko {
priceAPI = api.NewCG(&api.CoinGeckoConfig{
ApiKey: os.Getenv("COINGECKO_PRO_API_KEY"),
})
priceAPI = api.NewCG(0, 0)
} else {
return nil, ErrInvalidAPIChoice
}

@ -3,14 +3,6 @@ title: "Intro"
date: 2020-01-01T00:00:00-00:00
draft: false
---
<h3 align="center">
<br />
<img src="https://user-images.githubusercontent.com/168240/39561871-51cda852-4e5d-11e8-926b-7692d43143e8.png" alt="logo" width="400" />
<br />
<br />
<br />
</h3>
[`cointop`](https://github.com/cointop-sh/cointop) is a fast and lightweight interactive terminal based UI application for tracking and monitoring cryptocurrency coin stats in real-time.
The interface is inspired by [`htop`](https://en.wikipedia.org/wiki/Htop) and shortcut keys are inspired by [`vim`](https://en.wikipedia.org/wiki/Vim_(text_editor)).

@ -122,27 +122,6 @@ draft: false
cointop --coinmarketcap-api-key=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```
## How do I add my CoinGecko Pro API key?
Add the API key in the cointop config file:
```toml
[coingecko]
pro_api_key = "CG-xxxxxxxxxxxxxxxxxxxxxxxx"
```
Alternatively, you can export the environment variable `COINGECKO_PRO_API_KEY` containing the API key in your `~/.bashrc`
```bash
export COINGECKO_PRO_API_KEY=CG-xxxxxxxxxxxxxxxxxxxxxxxx
```
You may also set the API key on start:
```bash
cointop --coingecko-api-key=CG-xxxxxxxxxxxxxxxxxxxxxxxx
```
## I can I add my own API to cointop?
Fork cointop and add the API that implements the API [interface](https://github.com/cointop-sh/cointop/blob/master/cointop/common/api/interface.go) to [`cointop/cointop/common/api/impl/`](https://github.com/cointop-sh/cointop/tree/master/cointop/common/api/impl). You can use the CoinGecko [implementation](https://github.com/cointop-sh/cointop/blob/master/cointop/common/api/impl/coingecko/coingecko.go) as reference.

@ -7,6 +7,6 @@ draft: false
[![BTC Tip Jar](https://img.shields.io/badge/BTC-tip-yellow.svg?logo=bitcoin&style=flat)](https://www.blockchain.com/btc/address/3KdMW53vUMLPEC33xhHAUx4EFtvmXQF8Kf) `3KdMW53vUMLPEC33xhHAUx4EFtvmXQF8Kf`
[![ETH Tip Jar](https://img.shields.io/badge/ETH-tip-blue.svg?logo=ethereum&style=flat)](https://etherscan.io/address/0xC014b8F6F43f467922E93De62C9216F0538E0F8f) `0xC014b8F6F43f467922E93De62C9216F0538E0F8f`
[![ETH Tip Jar](https://img.shields.io/badge/ETH-tip-blue.svg?logo=ethereum&style=flat)](https://etherscan.io/address/0x0072cdd7c3d9963ba69506ECf50e16E963B35bb1) `0x0072cdd7c3d9963ba69506ECf50e16E963B35bb1`
Thank you for tips! 🙏

@ -5,12 +5,6 @@ import (
cmc "github.com/cointop-sh/cointop/pkg/api/impl/coinmarketcap"
)
type CoinGeckoConfig struct {
PerPage uint
MaxPages uint
ApiKey string
}
// NewCMC new CoinMarketCap API
func NewCMC(apiKey string) Interface {
return cmc.NewCMC(apiKey)
@ -22,10 +16,9 @@ func NewCC() {
}
// NewCG new CoinGecko API
func NewCG(config *CoinGeckoConfig) Interface {
func NewCG(perPage, maxPages uint) Interface {
return cg.NewCoinGecko(&cg.Config{
PerPage: config.PerPage,
MaxPages: config.MaxPages,
ApiKey: config.ApiKey,
PerPage: perPage,
MaxPages: maxPages,
})
}

@ -26,7 +26,6 @@ var ErrNotFound = errors.New("not found")
type Config struct {
PerPage uint
MaxPages uint
ApiKey string
}
// Service service
@ -53,7 +52,7 @@ func NewCoinGecko(config *Config) *Service {
maxPages = uint(math.Ceil(math.Max(float64(maxResults)/float64(maxResultsPerPage), 1)))
}
client := gecko.NewClient(nil, config.ApiKey)
client := gecko.NewClient(nil)
svc := &Service{
client: client,
maxResultsPerPage: uint(math.Min(float64(maxResults), float64(maxResultsPerPage))),

@ -16,18 +16,19 @@ import (
log "github.com/sirupsen/logrus"
)
var baseURL = "https://api.coingecko.com/api/v3"
// Client struct
type Client struct {
httpClient *http.Client
apiKey string
}
// NewClient create new client object
func NewClient(httpClient *http.Client, apiKey string) *Client {
func NewClient(httpClient *http.Client) *Client {
if httpClient == nil {
httpClient = http.DefaultClient
}
return &Client{httpClient: httpClient, apiKey: apiKey}
return &Client{httpClient: httpClient}
}
// helper
@ -47,7 +48,7 @@ func doReq(req *http.Request, client *http.Client) ([]byte, error) {
if err != nil {
return nil, err
}
if resp.StatusCode != 200 {
if 200 != resp.StatusCode {
if debugHttp {
log.Warnf("doReq Got Status '%s' from %s %s", resp.Status, req.Method, req.URL)
log.Debugf("doReq Got Body: %s", body)
@ -57,20 +58,6 @@ func doReq(req *http.Request, client *http.Client) ([]byte, error) {
return body, nil
}
func (c *Client) getApiUrl(path string, params *url.Values) string {
urlParams := url.Values{}
subdomain := "api"
if params != nil {
urlParams = *params
}
if c.apiKey != "" {
subdomain = "pro-api"
urlParams.Add("x_cg_pro_api_key", c.apiKey)
}
url := fmt.Sprintf("https://%s.coingecko.com/api/v3%s?%s", subdomain, path, urlParams.Encode())
return url
}
// MakeReq HTTP request helper
func (c *Client) MakeReq(url string) ([]byte, error) {
req, err := http.NewRequest("GET", url, nil)
@ -89,7 +76,7 @@ func (c *Client) MakeReq(url string) ([]byte, error) {
// Ping /ping endpoint
func (c *Client) Ping() (*types.Ping, error) {
url := c.getApiUrl("/ping", nil)
url := fmt.Sprintf("%s/ping", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
@ -118,14 +105,14 @@ func (c *Client) SimpleSinglePrice(id string, vsCurrency string) (*types.SimpleS
// SimplePrice /simple/price Multiple ID and Currency (ids, vs_currencies)
func (c *Client) SimplePrice(ids []string, vsCurrencies []string) (*map[string]map[string]float32, error) {
params := &url.Values{}
params := url.Values{}
idsParam := strings.Join(ids[:], ",")
vsCurrenciesParam := strings.Join(vsCurrencies[:], ",")
params.Add("ids", idsParam)
params.Add("vs_currencies", vsCurrenciesParam)
url := c.getApiUrl("/simple/price", params)
url := fmt.Sprintf("%s/simple/price?%s", baseURL, params.Encode())
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
@ -142,7 +129,7 @@ func (c *Client) SimplePrice(ids []string, vsCurrencies []string) (*map[string]m
// SimpleSupportedVSCurrencies /simple/supported_vs_currencies
func (c *Client) SimpleSupportedVSCurrencies() (*types.SimpleSupportedVSCurrencies, error) {
url := c.getApiUrl("/simple/supported_vs_currencies", nil)
url := fmt.Sprintf("%s/simple/supported_vs_currencies", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
@ -158,7 +145,7 @@ func (c *Client) SimpleSupportedVSCurrencies() (*types.SimpleSupportedVSCurrenci
// CoinsList /coins/list
func (c *Client) CoinsList() (*types.CoinList, error) {
url := c.getApiUrl("/coins/list", nil)
url := fmt.Sprintf("%s/coins/list", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
@ -177,7 +164,7 @@ func (c *Client) CoinsMarket(vsCurrency string, ids []string, order string, perP
if len(vsCurrency) == 0 {
return nil, fmt.Errorf("vsCurrency is required")
}
params := &url.Values{}
params := url.Values{}
// vsCurrency
params.Add("vs_currency", vsCurrency)
// order
@ -203,7 +190,7 @@ func (c *Client) CoinsMarket(vsCurrency string, ids []string, order string, perP
priceChangePercentageParam := strings.Join(priceChangePercentage[:], ",")
params.Add("price_change_percentage", priceChangePercentageParam)
}
url := c.getApiUrl("/coins/markets", params)
url := fmt.Sprintf("%s/coins/markets?%s", baseURL, params.Encode())
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
@ -222,14 +209,14 @@ func (c *Client) CoinsID(id string, localization bool, tickers bool, marketData
if len(id) == 0 {
return nil, fmt.Errorf("id is required")
}
params := &url.Values{}
params := url.Values{}
params.Add("localization", format.Bool2String(localization))
params.Add("tickers", format.Bool2String(tickers))
params.Add("market_data", format.Bool2String(marketData))
params.Add("community_data", format.Bool2String(communityData))
params.Add("developer_data", format.Bool2String(developerData))
params.Add("sparkline", format.Bool2String(sparkline))
url := c.getApiUrl(fmt.Sprintf("/coins/%s", id), params)
url := fmt.Sprintf("%s/coins/%s?%s", baseURL, id, params.Encode())
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
@ -248,11 +235,11 @@ func (c *Client) CoinsIDTickers(id string, page int) (*types.CoinsIDTickers, err
if len(id) == 0 {
return nil, fmt.Errorf("id is required")
}
params := &url.Values{}
params := url.Values{}
if page > 0 {
params.Add("page", format.Int2String(page))
}
url := c.getApiUrl(fmt.Sprintf("/coins/%s/tickers", id), params)
url := fmt.Sprintf("%s/coins/%s/tickers?%s", baseURL, id, params.Encode())
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
@ -270,11 +257,11 @@ func (c *Client) CoinsIDHistory(id string, date string, localization bool) (*typ
if len(id) == 0 || len(date) == 0 {
return nil, fmt.Errorf("id and date is required")
}
params := &url.Values{}
params := url.Values{}
params.Add("date", date)
params.Add("localization", format.Bool2String(localization))
url := c.getApiUrl(fmt.Sprintf("/coins/%s/history", id), params)
url := fmt.Sprintf("%s/coins/%s/history?%s", baseURL, id, params.Encode())
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
@ -293,11 +280,11 @@ func (c *Client) CoinsIDMarketChart(id string, vsCurrency string, days string) (
return nil, fmt.Errorf("id, vsCurrency, and days is required")
}
params := &url.Values{}
params := url.Values{}
params.Add("vs_currency", vsCurrency)
params.Add("days", days)
url := c.getApiUrl(fmt.Sprintf("/coins/%s/market_chart", id), params)
url := fmt.Sprintf("%s/coins/%s/market_chart?%s", baseURL, id, params.Encode())
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
@ -316,7 +303,7 @@ func (c *Client) CoinsIDMarketChart(id string, vsCurrency string, days string) (
// CoinsIDContractAddress https://api.coingecko.com/api/v3/coins/{id}/contract/{contract_address}
// func CoinsIDContractAddress(id string, address string) (nil, error) {
// url := c.getApiUrl(fmt.Sprintf("/coins/%s/contract/%s", id, address), nil)
// url := fmt.Sprintf("%s/coins/%s/contract/%s", baseURL, id, address)
// resp, err := request.MakeReq(url)
// if err != nil {
// return nil, err
@ -325,7 +312,7 @@ func (c *Client) CoinsIDMarketChart(id string, vsCurrency string, days string) (
// EventsCountries https://api.coingecko.com/api/v3/events/countries
func (c *Client) EventsCountries() ([]types.EventCountryItem, error) {
url := c.getApiUrl("/events/countries", nil)
url := fmt.Sprintf("%s/events/countries", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
@ -341,7 +328,7 @@ func (c *Client) EventsCountries() ([]types.EventCountryItem, error) {
// EventsTypes https://api.coingecko.com/api/v3/events/types
func (c *Client) EventsTypes() (*types.EventsTypes, error) {
url := c.getApiUrl("/events/types", nil)
url := fmt.Sprintf("%s/events/types", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
@ -357,7 +344,7 @@ func (c *Client) EventsTypes() (*types.EventsTypes, error) {
// ExchangeRates https://api.coingecko.com/api/v3/exchange_rates
func (c *Client) ExchangeRates() (*types.ExchangeRatesItem, error) {
url := c.getApiUrl("/exchange_rates", nil)
url := fmt.Sprintf("%s/exchange_rates", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
@ -372,7 +359,7 @@ func (c *Client) ExchangeRates() (*types.ExchangeRatesItem, error) {
// Global https://api.coingecko.com/api/v3/global
func (c *Client) Global() (*types.Global, error) {
url := c.getApiUrl("/global", nil)
url := fmt.Sprintf("%s/global", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err

Loading…
Cancel
Save