From 99bbeadc2d32b6161c6bab159d516463ee979175 Mon Sep 17 00:00:00 2001 From: Miguel Mota Date: Sun, 14 Feb 2021 22:14:26 -0800 Subject: [PATCH] Support multiple coins for price command --- Makefile | 3 +++ cmd/commands/price.go | 8 +++--- cointop/cointop.go | 4 --- cointop/error.go | 9 +++++++ cointop/price.go | 59 +++++++++++++++++++++++++++++++++++-------- 5 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 cointop/error.go diff --git a/Makefile b/Makefile index 15d6f53..a4b9494 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,9 @@ build-multiple: clean install: build sudo mv bin/cointop /usr/local/bin +uninstall: + sudo rm /usr/local/bin/cointop + clean-mac: go clean && \ rm -rf bin/mac diff --git a/cmd/commands/price.go b/cmd/commands/price.go index 4fa02f1..a0f6c7a 100644 --- a/cmd/commands/price.go +++ b/cmd/commands/price.go @@ -8,7 +8,7 @@ import ( // PriceCmd ... func PriceCmd() *cobra.Command { var apiChoice string - var coin string + var coins []string var currency string priceCmd := &cobra.Command{ @@ -16,15 +16,15 @@ func PriceCmd() *cobra.Command { Short: "Displays the current price of a coin", Long: `The price command display the current price of a coin`, RunE: func(cmd *cobra.Command, args []string) error { - return cointop.PrintPrice(&cointop.PriceConfig{ - Coin: coin, + return cointop.PrintPrices(&cointop.PricesConfig{ + Coins: coins, Currency: currency, APIChoice: apiChoice, }) }, } - priceCmd.Flags().StringVarP(&coin, "coin", "c", "bitcoin", "Full name of the coin") + priceCmd.Flags().StringSliceVarP(&coins, "coins", "c", nil, "Name or symbol of coin(s), comma separated. E.g. \"Bitcoin\" Eg. \"btc,eth,doge\"") priceCmd.Flags().StringVarP(¤cy, "currency", "f", "USD", "The currency to convert to") priceCmd.Flags().StringVarP(&apiChoice, "api", "a", cointop.CoinGecko, "API choice. Available choices are \"coinmarketcap\" and \"coingecko\"") diff --git a/cointop/cointop.go b/cointop/cointop.go index 80154dd..27d2b60 100644 --- a/cointop/cointop.go +++ b/cointop/cointop.go @@ -1,7 +1,6 @@ package cointop import ( - "errors" "fmt" "io/ioutil" "os" @@ -21,9 +20,6 @@ import ( // TODO: clean up and optimize codebase -// ErrInvalidAPIChoice is error for invalid API choice -var ErrInvalidAPIChoice = errors.New("invalid API choice") - // Views are all views in cointop type Views struct { Chart *ChartView diff --git a/cointop/error.go b/cointop/error.go new file mode 100644 index 0000000..92d37b4 --- /dev/null +++ b/cointop/error.go @@ -0,0 +1,9 @@ +package cointop + +import "errors" + +// ErrInvalidAPIChoice is error for invalid API choice +var ErrInvalidAPIChoice = errors.New("invalid API choice") + +// ErrCoinNameOrSymbolRequired is error for when coin name or symbol is required +var ErrCoinNameOrSymbolRequired = errors.New("coin name or symbol is required") diff --git a/cointop/price.go b/cointop/price.go index c600ef1..c24059a 100644 --- a/cointop/price.go +++ b/cointop/price.go @@ -2,37 +2,76 @@ package cointop import ( "fmt" + "strings" "github.com/miguelmota/cointop/pkg/api" "github.com/miguelmota/cointop/pkg/humanize" ) -// PriceConfig is the config options for the price command +// PriceConfig is the config options for the coin price method type PriceConfig struct { Coin string Currency string APIChoice string } +// PricesConfig is the config options for the coin prices method +type PricesConfig struct { + Coins []string + Currency string + APIChoice string +} + +// PrintPrices outputs the current price of the coins +func PrintPrices(config *PricesConfig) error { + prices, err := GetCoinPrices(config) + if err != nil { + return err + } + fmt.Println(strings.Join(prices, "\n")) + return nil +} + // PrintPrice outputs the current price of the coin func PrintPrice(config *PriceConfig) error { + prices, err := GetCoinPrices(&PricesConfig{ + Coins: []string{config.Coin}, + Currency: config.Currency, + APIChoice: config.APIChoice, + }) + if err != nil { + return err + } + + fmt.Println(prices[0]) + return nil +} + +// GetCoinPrices returns the current price of the specified coins +func GetCoinPrices(config *PricesConfig) ([]string, error) { + if len(config.Coins) == 0 { + return nil, ErrCoinNameOrSymbolRequired + } var priceAPI api.Interface if config.APIChoice == CoinMarketCap { priceAPI = api.NewCMC("") } else if config.APIChoice == CoinGecko { priceAPI = api.NewCG() } else { - return ErrInvalidAPIChoice + return nil, ErrInvalidAPIChoice } - price, err := priceAPI.Price(config.Coin, config.Currency) - if err != nil { - return err - } + var prices []string + for _, coin := range config.Coins { + price, err := priceAPI.Price(coin, config.Currency) + if err != nil { + return nil, err + } - symbol := CurrencySymbol(config.Currency) - value := fmt.Sprintf("%s%s", symbol, humanize.Commaf(price)) - fmt.Println(value) + symbol := CurrencySymbol(config.Currency) + value := fmt.Sprintf("%s%s", symbol, humanize.Commaf(price)) + prices = append(prices, value) + } - return nil + return prices, nil }