mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
Coinmarketcap implementation (#243)
* Updates requester package to allow unpacking of zipped files and defaults to warn if no JSON is present * Initial addition of coinmarketcap functionality * fix requested changes * Fix issue with displaying false positive in request.go && reorder plan list * Rename CurrencyProvider -> CryptocurrencyProvider Skip seeding currency data if not enabled Rm line in main.go * Update test procedures and relevant json files * Fix const issue within config.go
This commit is contained in:
committed by
Adrian Gallagher
parent
f7810e7eca
commit
82a622294c
@@ -56,8 +56,16 @@ const (
|
||||
WarningExchangeAuthAPIDefaultOrEmptyValues = "WARNING -- Exchange %s: Authenticated API support disabled due to default/empty APIKey/Secret/ClientID values."
|
||||
WarningCurrencyExchangeProvider = "WARNING -- Currency exchange provider invalid valid. Reset to Fixer."
|
||||
WarningPairsLastUpdatedThresholdExceeded = "WARNING -- Exchange %s: Last manual update of available currency pairs has exceeded %d days. Manual update required!"
|
||||
APIURLNonDefaultMessage = "NON_DEFAULT_HTTP_LINK_TO_EXCHANGE_API"
|
||||
WebsocketURLNonDefaultMessage = "NON_DEFAULT_HTTP_LINK_TO_WEBSOCKET_EXCHANGE_API"
|
||||
)
|
||||
|
||||
// Constants here define unset default values displayed in the config.json
|
||||
// file
|
||||
const (
|
||||
APIURLNonDefaultMessage = "NON_DEFAULT_HTTP_LINK_TO_EXCHANGE_API"
|
||||
WebsocketURLNonDefaultMessage = "NON_DEFAULT_HTTP_LINK_TO_WEBSOCKET_EXCHANGE_API"
|
||||
DefaultUnsetAPIKey = "Key"
|
||||
DefaultUnsetAPISecret = "Secret"
|
||||
DefaultUnsetAccountPlan = "accountPlan"
|
||||
)
|
||||
|
||||
// Variables here are used for configuration
|
||||
@@ -169,10 +177,20 @@ type BankTransaction struct {
|
||||
|
||||
// CurrencyConfig holds all the information needed for currency related manipulation
|
||||
type CurrencyConfig struct {
|
||||
ForexProviders []base.Settings `json:"forexProviders"`
|
||||
Cryptocurrencies string `json:"cryptocurrencies"`
|
||||
CurrencyPairFormat *CurrencyPairFormatConfig `json:"currencyPairFormat"`
|
||||
FiatDisplayCurrency string `json:"fiatDisplayCurrency"`
|
||||
ForexProviders []base.Settings `json:"forexProviders"`
|
||||
CryptocurrencyProvider CryptocurrencyProvider `json:"cryptocurrencyProvider"`
|
||||
Cryptocurrencies string `json:"cryptocurrencies"`
|
||||
CurrencyPairFormat *CurrencyPairFormatConfig `json:"currencyPairFormat"`
|
||||
FiatDisplayCurrency string `json:"fiatDisplayCurrency"`
|
||||
}
|
||||
|
||||
// CryptocurrencyProvider defines coinmarketcap tools
|
||||
type CryptocurrencyProvider struct {
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Verbose bool `json:"verbose"`
|
||||
APIkey string `json:"apiKey"`
|
||||
AccountPlan string `json:"accountPlan"`
|
||||
}
|
||||
|
||||
// CommunicationsConfig holds all the information needed for each
|
||||
@@ -365,6 +383,20 @@ func (c *Config) UpdateCommunicationsConfig(config CommunicationsConfig) {
|
||||
m.Unlock()
|
||||
}
|
||||
|
||||
// GetCryptocurrencyProviderConfig returns the communications configuration
|
||||
func (c *Config) GetCryptocurrencyProviderConfig() CryptocurrencyProvider {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return c.Currency.CryptocurrencyProvider
|
||||
}
|
||||
|
||||
// UpdateCryptocurrencyProviderConfig returns the communications configuration
|
||||
func (c *Config) UpdateCryptocurrencyProviderConfig(config CryptocurrencyProvider) {
|
||||
m.Lock()
|
||||
c.Currency.CryptocurrencyProvider = config
|
||||
m.Unlock()
|
||||
}
|
||||
|
||||
// CheckCommunicationsConfig checks to see if the variables are set correctly
|
||||
// from config.json
|
||||
func (c *Config) CheckCommunicationsConfig() {
|
||||
@@ -732,7 +764,9 @@ func (c *Config) CheckExchangeConfigValues() error {
|
||||
return fmt.Errorf(ErrExchangeBaseCurrenciesEmpty, exch.Name)
|
||||
}
|
||||
if exch.AuthenticatedAPISupport { // non-fatal error
|
||||
if exch.APIKey == "" || exch.APISecret == "" || exch.APIKey == "Key" || exch.APISecret == "Secret" {
|
||||
if exch.APIKey == "" || exch.APISecret == "" ||
|
||||
exch.APIKey == DefaultUnsetAPIKey ||
|
||||
exch.APISecret == DefaultUnsetAPISecret {
|
||||
c.Exchanges[i].AuthenticatedAPISupport = false
|
||||
log.Warn(WarningExchangeAuthAPIDefaultOrEmptyValues, exch.Name)
|
||||
} else if exch.Name == "ITBIT" || exch.Name == "Bitstamp" || exch.Name == "COINUT" || exch.Name == "CoinbasePro" {
|
||||
@@ -844,7 +878,7 @@ func (c *Config) CheckCurrencyConfigValues() error {
|
||||
Enabled: false,
|
||||
Verbose: false,
|
||||
RESTPollingDelay: 600,
|
||||
APIKey: "Key",
|
||||
APIKey: DefaultUnsetAPIKey,
|
||||
APIKeyLvl: -1,
|
||||
PrimaryProvider: false,
|
||||
},
|
||||
@@ -856,7 +890,7 @@ func (c *Config) CheckCurrencyConfigValues() error {
|
||||
count := 0
|
||||
for i := range c.Currency.ForexProviders {
|
||||
if c.Currency.ForexProviders[i].Enabled {
|
||||
if c.Currency.ForexProviders[i].APIKey == "Key" {
|
||||
if c.Currency.ForexProviders[i].APIKey == DefaultUnsetAPIKey {
|
||||
log.Warnf("%s forex provider API key not set. Please set this in your config.json file", c.Currency.ForexProviders[i].Name)
|
||||
c.Currency.ForexProviders[i].Enabled = false
|
||||
c.Currency.ForexProviders[i].PrimaryProvider = false
|
||||
@@ -881,6 +915,32 @@ func (c *Config) CheckCurrencyConfigValues() error {
|
||||
}
|
||||
}
|
||||
|
||||
if c.Currency.CryptocurrencyProvider == (CryptocurrencyProvider{}) {
|
||||
c.Currency.CryptocurrencyProvider.Name = "CoinMarketCap"
|
||||
c.Currency.CryptocurrencyProvider.Enabled = false
|
||||
c.Currency.CryptocurrencyProvider.Verbose = false
|
||||
c.Currency.CryptocurrencyProvider.AccountPlan = DefaultUnsetAccountPlan
|
||||
c.Currency.CryptocurrencyProvider.APIkey = DefaultUnsetAPIKey
|
||||
}
|
||||
|
||||
if c.Currency.CryptocurrencyProvider.Enabled {
|
||||
if c.Currency.CryptocurrencyProvider.APIkey == "" ||
|
||||
c.Currency.CryptocurrencyProvider.APIkey == DefaultUnsetAPIKey {
|
||||
log.Warnf("CryptocurrencyProvider enabled but api key is unset please set this in your config.json file")
|
||||
}
|
||||
if c.Currency.CryptocurrencyProvider.AccountPlan == "" ||
|
||||
c.Currency.CryptocurrencyProvider.AccountPlan == DefaultUnsetAccountPlan {
|
||||
log.Warnf("CryptocurrencyProvider enabled but account plan is unset please set this in your config.json file")
|
||||
}
|
||||
} else {
|
||||
if c.Currency.CryptocurrencyProvider.APIkey == "" {
|
||||
c.Currency.CryptocurrencyProvider.APIkey = DefaultUnsetAPIKey
|
||||
}
|
||||
if c.Currency.CryptocurrencyProvider.AccountPlan == "" {
|
||||
c.Currency.CryptocurrencyProvider.AccountPlan = DefaultUnsetAccountPlan
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.Currency.Cryptocurrencies) == 0 {
|
||||
if len(c.Cryptocurrencies) != 0 {
|
||||
c.Currency.Cryptocurrencies = c.Cryptocurrencies
|
||||
|
||||
@@ -181,6 +181,31 @@ func TestUpdateCommunicationsConfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCryptocurrencyProviderConfig(t *testing.T) {
|
||||
cfg := GetConfig()
|
||||
err := cfg.LoadConfig(ConfigTestFile)
|
||||
if err != nil {
|
||||
t.Error("Test failed. GetCryptocurrencyProviderConfig LoadConfig error", err)
|
||||
}
|
||||
_ = cfg.GetCryptocurrencyProviderConfig()
|
||||
}
|
||||
|
||||
func TestUpdateCryptocurrencyProviderConfig(t *testing.T) {
|
||||
cfg := GetConfig()
|
||||
err := cfg.LoadConfig(ConfigTestFile)
|
||||
if err != nil {
|
||||
t.Error("Test failed. UpdateCryptocurrencyProviderConfig LoadConfig error", err)
|
||||
}
|
||||
|
||||
orig := cfg.GetCryptocurrencyProviderConfig()
|
||||
cfg.UpdateCryptocurrencyProviderConfig(CryptocurrencyProvider{Name: "SERIOUS TESTING PROCEDURE!"})
|
||||
if cfg.Currency.CryptocurrencyProvider.Name != "SERIOUS TESTING PROCEDURE!" {
|
||||
t.Error("Test failed. UpdateCurrencyProviderConfig LoadConfig error")
|
||||
}
|
||||
|
||||
cfg.UpdateCryptocurrencyProviderConfig(orig)
|
||||
}
|
||||
|
||||
func TestCheckCommunicationsConfig(t *testing.T) {
|
||||
cfg := GetConfig()
|
||||
err := cfg.LoadConfig(ConfigTestFile)
|
||||
|
||||
@@ -48,6 +48,13 @@
|
||||
"primaryProvider": false
|
||||
}
|
||||
],
|
||||
"cryptocurrencyProvider": {
|
||||
"name": "CoinMarketCap",
|
||||
"enabled": false,
|
||||
"verbose": false,
|
||||
"apiKey": "Key",
|
||||
"accountPlan": "accountPlan"
|
||||
},
|
||||
"cryptocurrencies": "BTC,LTC,ETH,XRP,NMC,NVC,PPC,XBT,DOGE,DASH",
|
||||
"currencyPairFormat": {
|
||||
"uppercase": true,
|
||||
|
||||
764
currency/coinmarketcap/coinmarketcap.go
Normal file
764
currency/coinmarketcap/coinmarketcap.go
Normal file
@@ -0,0 +1,764 @@
|
||||
// Package coinmarketcap connects to a suite of high-performance RESTful JSON
|
||||
// endpoints that are specifically designed to meet the mission-critical demands
|
||||
// of application developers, data scientists, and enterprise business
|
||||
// platforms. Please see https://coinmarketcap.com/api/documentation/v1/# for
|
||||
// API documentation
|
||||
package coinmarketcap
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
)
|
||||
|
||||
// Coinmarketcap account plan bitmasks, url and enpoint consts
|
||||
const (
|
||||
Basic uint8 = 1 << iota
|
||||
Hobbyist
|
||||
Startup
|
||||
Standard
|
||||
Professional
|
||||
Enterprise
|
||||
|
||||
baseURL = "https://pro-api.coinmarketcap.com"
|
||||
sandboxURL = "https://sandbox-api.coinmarketcap.com"
|
||||
version = "/v1/"
|
||||
|
||||
endpointCryptocurrencyInfo = "cryptocurrency/info"
|
||||
endpointCryptocurrencyMap = "cryptocurrency/map"
|
||||
endpointCryptocurrencyHistoricalListings = "cryptocurrency/listings/historical"
|
||||
endpointCryptocurrencyLatestListings = "cryptocurrency/listings/latest"
|
||||
endpointCryptocurrencyMarketPairs = "cryptocurrency/market-pairs/latest"
|
||||
endpointOHLCVHistorical = "cryptocurrency/ohlcv/historical"
|
||||
endpointOHLCVLatest = "cryptocurrency/ohlcv/latest"
|
||||
endpointGetMarketQuotesHistorical = "cryptocurrency/quotes/historical"
|
||||
endpointGetMarketQuotesLatest = "cryptocurrency/quotes/latest"
|
||||
endpointExchangeInfo = "exchange/info"
|
||||
endpointExchangeMap = "exchange/map"
|
||||
endpointExchangeMarketPairsLatest = "exchange/market-pairs/latest"
|
||||
endpointExchangeMarketQuoteHistorical = "exchange/quotes/historical"
|
||||
endpointExchangeMarketQuoteLatest = "exchange/quotes/latest"
|
||||
endpointGlobalQuoteHistorical = "global-metrics/quotes/historical"
|
||||
endpointGlobalQuoteLatest = "global-metrics/quotes/latest"
|
||||
endpointPriceConversion = "tools/price-conversion"
|
||||
|
||||
authrate = 0
|
||||
defaultTimeOut = time.Second * 15
|
||||
)
|
||||
|
||||
// Coinmarketcap is the overarching type across this package
|
||||
type Coinmarketcap struct {
|
||||
Verbose bool
|
||||
Enabled bool
|
||||
Name string
|
||||
APIkey string
|
||||
APIUrl string
|
||||
APIVersion string
|
||||
Plan uint8
|
||||
Requester *request.Requester
|
||||
}
|
||||
|
||||
// SetDefaults sets default values for the exchange
|
||||
func (c *Coinmarketcap) SetDefaults() {
|
||||
c.Name = "CoinMarketCap"
|
||||
c.Enabled = false
|
||||
c.Verbose = false
|
||||
c.APIUrl = baseURL
|
||||
c.APIVersion = version
|
||||
c.Requester = request.New(c.Name,
|
||||
request.NewRateLimit(time.Second*10, authrate),
|
||||
request.NewRateLimit(time.Second*10, authrate),
|
||||
common.NewHTTPClientWithTimeout(defaultTimeOut))
|
||||
}
|
||||
|
||||
// Setup sets user configuration
|
||||
func (c *Coinmarketcap) Setup(conf Settings) {
|
||||
if !conf.Enabled {
|
||||
c.Enabled = false
|
||||
} else {
|
||||
c.Enabled = true
|
||||
c.Verbose = conf.Verbose
|
||||
c.APIkey = conf.APIkey
|
||||
err := c.SetAccountPlan(conf.AccountPlan)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetCryptocurrencyInfo returns all static metadata for one or more
|
||||
// cryptocurrencies including name, symbol, logo, and its various registered
|
||||
// URLs
|
||||
//
|
||||
// currencyID = digit code generated by coinmarketcap
|
||||
func (c *Coinmarketcap) GetCryptocurrencyInfo(currencyID ...int64) (CryptoCurrencyInfo, error) {
|
||||
resp := struct {
|
||||
Data CryptoCurrencyInfo `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Basic)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
var currStr []string
|
||||
for _, d := range currencyID {
|
||||
currStr = append(currStr, strconv.FormatInt(d, 10))
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("id", strings.Join(currStr, ","))
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointCryptocurrencyInfo, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetCryptocurrencyIDMap returns a paginated list of all cryptocurrencies by
|
||||
// CoinMarketCap ID.
|
||||
func (c *Coinmarketcap) GetCryptocurrencyIDMap() ([]CryptoCurrencyMap, error) {
|
||||
resp := struct {
|
||||
Data []CryptoCurrencyMap `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Basic)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointCryptocurrencyMap, nil, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetCryptocurrencyHistoricalListings returns a paginated list of all
|
||||
// cryptocurrencies with market data for a given historical time.
|
||||
func (c *Coinmarketcap) GetCryptocurrencyHistoricalListings() ([]CryptocurrencyHistoricalListings, error) {
|
||||
return nil, errors.New("this endpoint is not yet available")
|
||||
// NOTE unreachable code but will be utilised at a later date
|
||||
// resp := struct {
|
||||
// Data []CryptocurrencyHistoricalListings `json:"data"`
|
||||
// Status Status `json:"status"`
|
||||
// }{}
|
||||
|
||||
// err := c.CheckAccountPlan(0)
|
||||
// if err != nil {
|
||||
// return resp.Data, err
|
||||
// }
|
||||
|
||||
// err = c.SendHTTPRequest("GET", endpointCryptocurrencyHistoricalListings, nil, &resp)
|
||||
// if err != nil {
|
||||
// return resp.Data, err
|
||||
// }
|
||||
|
||||
// if resp.Status.ErrorCode != 0 {
|
||||
// return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
// }
|
||||
|
||||
// return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetCryptocurrencyLatestListing returns a paginated list of all
|
||||
// cryptocurrencies with latest market data.
|
||||
//
|
||||
// Start - optionally offsets the paginated items
|
||||
// limit - optionally sets return limit on items [1..5000]
|
||||
func (c *Coinmarketcap) GetCryptocurrencyLatestListing(start, limit int64) ([]CryptocurrencyLatestListings, error) {
|
||||
resp := struct {
|
||||
Data []CryptocurrencyLatestListings `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Basic)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
if start >= 1 {
|
||||
val.Set("start", strconv.FormatInt(start, 10))
|
||||
}
|
||||
|
||||
if limit > 0 {
|
||||
val.Set("limit", strconv.FormatInt(limit, 10))
|
||||
}
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointCryptocurrencyLatestListings, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetCryptocurrencyLatestMarketPairs returns all market pairs across all
|
||||
// exchanges for the specified cryptocurrency with associated stats.
|
||||
//
|
||||
// currencyID - refers to the coinmarketcap currency id
|
||||
// Start - optionally offsets the paginated items
|
||||
// limit - optionally sets return limit on items [1..5000]
|
||||
func (c *Coinmarketcap) GetCryptocurrencyLatestMarketPairs(currencyID, start, limit int64) (CryptocurrencyLatestMarketPairs, error) {
|
||||
resp := struct {
|
||||
Data CryptocurrencyLatestMarketPairs `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Standard)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("id", strconv.FormatInt(currencyID, 10))
|
||||
|
||||
if start >= 1 {
|
||||
val.Set("start", strconv.FormatInt(start, 10))
|
||||
}
|
||||
|
||||
if limit > 0 {
|
||||
val.Set("limit", strconv.FormatInt(limit, 10))
|
||||
}
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointCryptocurrencyMarketPairs, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetCryptocurrencyOHLCHistorical return an interval of historic OHLCV
|
||||
// (Open, High, Low, Close, Volume) market quotes for a cryptocurrency.
|
||||
// Currently daily and hourly OHLCV periods are supported.
|
||||
//
|
||||
// currencyID - refers to the coinmarketcap currency id
|
||||
// tStart - refers to the start time of historic value
|
||||
// tEnd - refers to the end of the time block if zero will default to time.Now()
|
||||
func (c *Coinmarketcap) GetCryptocurrencyOHLCHistorical(currencyID int64, tStart, tEnd time.Time) (CryptocurrencyOHLCHistorical, error) {
|
||||
resp := struct {
|
||||
Data CryptocurrencyOHLCHistorical `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Standard)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("id", strconv.FormatInt(currencyID, 10))
|
||||
val.Set("time_start", strconv.FormatInt(tStart.Unix(), 10))
|
||||
|
||||
if !tEnd.IsZero() {
|
||||
val.Set("time_end", strconv.FormatInt(tEnd.Unix(), 10))
|
||||
}
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointOHLCVHistorical, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetCryptocurrencyOHLCLatest return the latest OHLCV
|
||||
// (Open, High, Low, Close, Volume) market values for one or more
|
||||
// cryptocurrencies in the currently UTC day. Since the current UTC day is still
|
||||
// active these values are updated frequently. You can find the final calculated
|
||||
// OHLCV values for the last completed UTC day along with all historic days
|
||||
// using /cryptocurrency/ohlcv/historical.
|
||||
//
|
||||
// currencyID - refers to the coinmarketcap currency id
|
||||
func (c *Coinmarketcap) GetCryptocurrencyOHLCLatest(currencyID int64) (CryptocurrencyOHLCLatest, error) {
|
||||
resp := struct {
|
||||
Data CryptocurrencyOHLCLatest `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Startup)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("id", strconv.FormatInt(currencyID, 10))
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointOHLCVLatest, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetCryptocurrencyLatestQuotes returns the latest market quote for 1 or more
|
||||
// cryptocurrencies.
|
||||
//
|
||||
// currencyID - refers to the coinmarketcap currency id
|
||||
func (c *Coinmarketcap) GetCryptocurrencyLatestQuotes(currencyID ...int64) (CryptocurrencyLatestQuotes, error) {
|
||||
resp := struct {
|
||||
Data CryptocurrencyLatestQuotes `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Basic)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
var currStr []string
|
||||
for _, d := range currencyID {
|
||||
currStr = append(currStr, strconv.FormatInt(d, 10))
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("id", strings.Join(currStr, ","))
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointGetMarketQuotesLatest, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetCryptocurrencyHistoricalQuotes returns an interval of historic market
|
||||
// quotes for any cryptocurrency based on time and interval parameters.
|
||||
//
|
||||
// currencyID - refers to the coinmarketcap currency id
|
||||
// tStart - refers to the start time of historic value
|
||||
// tEnd - refers to the end of the time block if zero will default to time.Now()
|
||||
func (c *Coinmarketcap) GetCryptocurrencyHistoricalQuotes(currencyID int64, tStart, tEnd time.Time) (CryptocurrencyHistoricalQuotes, error) {
|
||||
resp := struct {
|
||||
Data CryptocurrencyHistoricalQuotes `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Standard)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("id", strconv.FormatInt(currencyID, 10))
|
||||
val.Set("time_start", strconv.FormatInt(tStart.Unix(), 10))
|
||||
|
||||
if !tEnd.IsZero() {
|
||||
val.Set("time_end", strconv.FormatInt(tEnd.Unix(), 10))
|
||||
}
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointGetMarketQuotesHistorical, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetExchangeInfo returns all static metadata for one or more exchanges
|
||||
// including logo and homepage URL.
|
||||
//
|
||||
// exchangeID - refers to coinmarketcap exchange id
|
||||
func (c *Coinmarketcap) GetExchangeInfo(exchangeID ...int64) (ExchangeInfo, error) {
|
||||
resp := struct {
|
||||
Data ExchangeInfo `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Startup)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
var exchStr []string
|
||||
for _, d := range exchangeID {
|
||||
exchStr = append(exchStr, strconv.FormatInt(d, 10))
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("id", strings.Join(exchStr, ","))
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointExchangeInfo, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetExchangeMap returns a paginated list of all cryptocurrency exchanges by
|
||||
// CoinMarketCap ID. Recommend using this convenience endpoint to lookup and
|
||||
// utilize the unique exchange id across all endpoints as typical exchange
|
||||
// identifiers may change over time. ie huobi -> hadax -> global -> who knows
|
||||
// what else
|
||||
//
|
||||
// Start - optionally offsets the paginated items
|
||||
// limit - optionally sets return limit on items [1..5000]
|
||||
func (c *Coinmarketcap) GetExchangeMap(start, limit int64) ([]ExchangeMap, error) {
|
||||
resp := struct {
|
||||
Data []ExchangeMap `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Startup)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
if start >= 1 {
|
||||
val.Set("start", strconv.FormatInt(start, 10))
|
||||
}
|
||||
|
||||
if limit != 0 {
|
||||
val.Set("limit", strconv.FormatInt(start, 10))
|
||||
}
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointExchangeMap, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetExchangeHistoricalListings returns a paginated list of all cryptocurrency
|
||||
// exchanges with historical market data for a given point in time.
|
||||
func (c *Coinmarketcap) GetExchangeHistoricalListings() ([]ExchangeHistoricalListings, error) {
|
||||
resp := struct {
|
||||
Data []ExchangeHistoricalListings `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
return resp.Data, errors.New("this endpoint is not yet available")
|
||||
}
|
||||
|
||||
// GetExchangeLatestListings returns a paginated list of all cryptocurrency
|
||||
// exchanges with historical market data for a given point in time.
|
||||
func (c *Coinmarketcap) GetExchangeLatestListings() ([]ExchangeLatestListings, error) {
|
||||
resp := struct {
|
||||
Data []ExchangeLatestListings `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
return resp.Data, errors.New("this endpoint is not yet available")
|
||||
}
|
||||
|
||||
// GetExchangeLatestMarketPairs returns a list of active market pairs for an
|
||||
// exchange. Active means the market pair is open for trading.
|
||||
//
|
||||
// exchangeID - refers to coinmarketcap exchange id
|
||||
// Start - optionally offsets the paginated items
|
||||
// limit - optionally sets return limit on items [1..5000]
|
||||
func (c *Coinmarketcap) GetExchangeLatestMarketPairs(exchangeID, start, limit int64) (ExchangeLatestMarketPairs, error) {
|
||||
resp := struct {
|
||||
Data ExchangeLatestMarketPairs `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Standard)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("id", strconv.FormatInt(exchangeID, 10))
|
||||
|
||||
if start >= 1 {
|
||||
val.Set("start", strconv.FormatInt(start, 10))
|
||||
}
|
||||
|
||||
if limit != 0 {
|
||||
val.Set("limit", strconv.FormatInt(start, 10))
|
||||
}
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointExchangeMarketPairsLatest, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetExchangeLatestQuotes returns the latest aggregate market data for 1 or
|
||||
// more exchanges.
|
||||
//
|
||||
// exchangeID - refers to coinmarketcap exchange id
|
||||
func (c *Coinmarketcap) GetExchangeLatestQuotes(exchangeID ...int64) (ExchangeLatestQuotes, error) {
|
||||
resp := struct {
|
||||
Data ExchangeLatestQuotes `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Standard)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
var exchStr []string
|
||||
for _, d := range exchangeID {
|
||||
exchStr = append(exchStr, strconv.FormatInt(d, 10))
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("id", strings.Join(exchStr, ","))
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointExchangeMarketQuoteLatest, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetExchangeHistoricalQuotes returns an interval of historic quotes for any
|
||||
// exchange based on time and interval parameters.
|
||||
//
|
||||
// exchangeID - refers to coinmarketcap exchange id
|
||||
// tStart - refers to the start time of historic value
|
||||
// tEnd - refers to the end of the time block if zero will default to time.Now()
|
||||
func (c *Coinmarketcap) GetExchangeHistoricalQuotes(exchangeID int64, tStart, tEnd time.Time) (ExchangeHistoricalQuotes, error) {
|
||||
resp := struct {
|
||||
Data ExchangeHistoricalQuotes `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Standard)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("id", strconv.FormatInt(exchangeID, 10))
|
||||
val.Set("time_start", strconv.FormatInt(tStart.Unix(), 10))
|
||||
|
||||
if !tEnd.IsZero() {
|
||||
val.Set("time_end", strconv.FormatInt(tEnd.Unix(), 10))
|
||||
}
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointExchangeMarketQuoteHistorical, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetGlobalMeticLatestQuotes returns the latest quote of aggregate market
|
||||
// metrics.
|
||||
func (c *Coinmarketcap) GetGlobalMeticLatestQuotes() (GlobalMeticLatestQuotes, error) {
|
||||
resp := struct {
|
||||
Data GlobalMeticLatestQuotes `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Basic)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointGlobalQuoteLatest, nil, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetGlobalMeticHistoricalQuotes returns an interval of aggregate 24 hour
|
||||
// volume and market cap data globally based on time and interval parameters.
|
||||
//
|
||||
// tStart - refers to the start time of historic value
|
||||
// tEnd - refers to the end of the time block if zero will default to time.Now()
|
||||
func (c *Coinmarketcap) GetGlobalMeticHistoricalQuotes(tStart, tEnd time.Time) (GlobalMeticHistoricalQuotes, error) {
|
||||
resp := struct {
|
||||
Data GlobalMeticHistoricalQuotes `json:"data"`
|
||||
Status Status `json:"status"`
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Standard)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("time_start", strconv.FormatInt(tStart.Unix(), 10))
|
||||
|
||||
if !tEnd.IsZero() {
|
||||
val.Set("time_end", strconv.FormatInt(tEnd.Unix(), 10))
|
||||
}
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointGlobalQuoteHistorical, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// GetPriceConversion converts an amount of one currency into multiple
|
||||
// cryptocurrencies or fiat currencies at the same time using the latest market
|
||||
// averages. Optionally pass a historical timestamp to convert values based on
|
||||
// historic averages.
|
||||
//
|
||||
// amount - An amount of currency to convert. Example: 10.43
|
||||
// currencyID - refers to the coinmarketcap currency id
|
||||
// atHistoricTime - [Optional] timestamp to reference historical pricing during
|
||||
// conversion.
|
||||
func (c *Coinmarketcap) GetPriceConversion(amount float64, currencyID int64, atHistoricTime time.Time) (PriceConversion, error) {
|
||||
resp := struct {
|
||||
Data PriceConversion `json:"data"`
|
||||
Status
|
||||
}{}
|
||||
|
||||
err := c.CheckAccountPlan(Hobbyist)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
val.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
val.Set("id", strconv.FormatInt(currencyID, 10))
|
||||
|
||||
if !atHistoricTime.IsZero() {
|
||||
val.Set("time", strconv.FormatInt(atHistoricTime.Unix(), 10))
|
||||
}
|
||||
|
||||
err = c.SendHTTPRequest("GET", endpointPriceConversion, val, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
if resp.Status.ErrorCode != 0 {
|
||||
return resp.Data, errors.New(resp.Status.ErrorMessage)
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends a valid HTTP request
|
||||
func (c *Coinmarketcap) SendHTTPRequest(method, endpoint string, v url.Values, result interface{}) error {
|
||||
headers := make(map[string]string)
|
||||
headers["Accept"] = "application/json"
|
||||
headers["Accept-Encoding"] = "deflate, gzip"
|
||||
headers["X-CMC_PRO_API_KEY"] = c.APIkey
|
||||
|
||||
path := c.APIUrl + c.APIVersion + endpoint
|
||||
if v != nil {
|
||||
path = path + "?" + v.Encode()
|
||||
}
|
||||
|
||||
return c.Requester.SendPayload(method,
|
||||
path,
|
||||
headers,
|
||||
strings.NewReader(""),
|
||||
result,
|
||||
false,
|
||||
c.Verbose)
|
||||
}
|
||||
|
||||
// CheckAccountPlan checks your current account plan to the minimal account
|
||||
// needed to send http request, this is used to minimize requests for lower
|
||||
// account privileges
|
||||
func (c *Coinmarketcap) CheckAccountPlan(minAllowable uint8) error {
|
||||
if c.Plan < minAllowable {
|
||||
return errors.New("function use not allowed, higher plan needed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetAccountPlan sets account plan
|
||||
func (c *Coinmarketcap) SetAccountPlan(s string) error {
|
||||
switch s {
|
||||
case "basic":
|
||||
c.Plan = Basic
|
||||
case "hobbyist":
|
||||
c.Plan = Hobbyist
|
||||
case "startup":
|
||||
c.Plan = Startup
|
||||
case "standard":
|
||||
c.Plan = Standard
|
||||
case "professional":
|
||||
c.Plan = Professional
|
||||
case "enterprise":
|
||||
c.Plan = Enterprise
|
||||
default:
|
||||
return fmt.Errorf("account plan %s not found", s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
415
currency/coinmarketcap/coinmarketcap_test.go
Normal file
415
currency/coinmarketcap/coinmarketcap_test.go
Normal file
@@ -0,0 +1,415 @@
|
||||
package coinmarketcap
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
var c Coinmarketcap
|
||||
|
||||
// Please set API keys to test endpoint
|
||||
const (
|
||||
apikey = ""
|
||||
apiAccountPlanLevel = ""
|
||||
)
|
||||
|
||||
// Checks credentials but also checks to see if the function can take the
|
||||
// required account plan level
|
||||
func areAPICredtionalsSet(minAllowable uint8) bool {
|
||||
if apiAccountPlanLevel != "" && apikey != "" {
|
||||
if err := c.CheckAccountPlan(minAllowable); err != nil {
|
||||
log.Warn("coinmarketpcap test suite - account plan not allowed for function, please review or upgrade plan to test")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
|
||||
cfg := Settings{}
|
||||
cfg.APIkey = apikey
|
||||
cfg.AccountPlan = apiAccountPlanLevel
|
||||
cfg.Enabled = true
|
||||
cfg.AccountPlan = "basic"
|
||||
|
||||
c.Setup(cfg)
|
||||
}
|
||||
|
||||
func TestCheckAccountPlan(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areAPICredtionalsSet(Basic) {
|
||||
err := c.CheckAccountPlan(Enterprise)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CheckAccountPlan() error cannot be nil")
|
||||
}
|
||||
|
||||
err = c.CheckAccountPlan(Professional)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CheckAccountPlan() error cannot be nil")
|
||||
}
|
||||
|
||||
err = c.CheckAccountPlan(Standard)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CheckAccountPlan() error cannot be nil")
|
||||
}
|
||||
|
||||
err = c.CheckAccountPlan(Hobbyist)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CheckAccountPlan() error cannot be nil")
|
||||
}
|
||||
|
||||
err = c.CheckAccountPlan(Startup)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CheckAccountPlan() error cannot be nil")
|
||||
}
|
||||
|
||||
err = c.CheckAccountPlan(Basic)
|
||||
if err != nil {
|
||||
t.Error("Test Failed - CheckAccountPlan() error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCryptocurrencyInfo(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetCryptocurrencyInfo(1)
|
||||
if areAPICredtionalsSet(Basic) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyInfo() error", err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyInfo() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCryptocurrencyIDMap(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetCryptocurrencyIDMap()
|
||||
if areAPICredtionalsSet(Basic) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyIDMap() error", err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyIDMap() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCryptocurrencyHistoricalListings(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetCryptocurrencyHistoricalListings()
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyHistoricalListings() error cannot be nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCryptocurrencyLatestListing(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetCryptocurrencyLatestListing(0, 0)
|
||||
if areAPICredtionalsSet(Basic) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyLatestListing() error", err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyLatestListing() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCryptocurrencyLatestMarketPairs(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetCryptocurrencyLatestMarketPairs(1, 0, 0)
|
||||
if areAPICredtionalsSet(Standard) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyLatestMarketPairs() error",
|
||||
err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyLatestMarketPairs() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCryptocurrencyOHLCHistorical(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetCryptocurrencyOHLCHistorical(1, time.Now(), time.Now())
|
||||
if areAPICredtionalsSet(Standard) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyOHLCHistorical() error",
|
||||
err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyOHLCHistorical() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCryptocurrencyOHLCLatest(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetCryptocurrencyOHLCLatest(1)
|
||||
if areAPICredtionalsSet(Startup) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyOHLCLatest() error",
|
||||
err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyOHLCLatest() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCryptocurrencyLatestQuotes(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetCryptocurrencyLatestQuotes(1)
|
||||
if areAPICredtionalsSet(Basic) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyLatestQuotes() error",
|
||||
err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyLatestQuotes() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCryptocurrencyHistoricalQuotes(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetCryptocurrencyHistoricalQuotes(1, time.Now(), time.Now())
|
||||
if areAPICredtionalsSet(Standard) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyHistoricalQuotes() error",
|
||||
err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptocurrencyHistoricalQuotes() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExchangeInfo(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetExchangeInfo(1)
|
||||
if areAPICredtionalsSet(Startup) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetExchangeInfo() error",
|
||||
err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetExchangeInfo() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExchangeMap(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetExchangeMap(0, 0)
|
||||
if areAPICredtionalsSet(Startup) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetExchangeMap() error",
|
||||
err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetExchangeMap() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExchangeHistoricalListings(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetExchangeHistoricalListings()
|
||||
if areAPICredtionalsSet(Basic) {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetExchangeHistoricalListings() error cannot be nil")
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetExchangeHistoricalListings() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExchangeLatestListings(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetExchangeLatestListings()
|
||||
if areAPICredtionalsSet(Basic) {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetExchangeLatestListings() error cannot be nil")
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetExchangeLatestListings() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExchangeLatestMarketPairs(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetExchangeLatestMarketPairs(1, 0, 0)
|
||||
if areAPICredtionalsSet(Standard) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetExchangeLatestMarketPairs() error",
|
||||
err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetExchangeLatestMarketPairs() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExchangeLatestQuotes(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetExchangeLatestQuotes(1)
|
||||
if areAPICredtionalsSet(Standard) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetExchangeLatestQuotes() error",
|
||||
err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetExchangeLatestQuotes() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetExchangeHistoricalQuotes(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetExchangeHistoricalQuotes(1, time.Now(), time.Now())
|
||||
if areAPICredtionalsSet(Standard) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetExchangeHistoricalQuotes() error",
|
||||
err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetExchangeHistoricalQuotes() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetGlobalMeticLatestQuotes(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetGlobalMeticLatestQuotes()
|
||||
if areAPICredtionalsSet(Basic) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetGlobalMeticLatestQuotes() error",
|
||||
err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetGlobalMeticLatestQuotes() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetGlobalMeticHistoricalQuotes(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetGlobalMeticHistoricalQuotes(time.Now(), time.Now())
|
||||
if areAPICredtionalsSet(Standard) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetGlobalMeticHistoricalQuotes() error",
|
||||
err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetGlobalMeticHistoricalQuotes() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPriceConversion(t *testing.T) {
|
||||
c.SetDefaults()
|
||||
TestSetup(t)
|
||||
_, err := c.GetPriceConversion(0, 1, time.Now())
|
||||
if areAPICredtionalsSet(Hobbyist) {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetPriceConversion() error",
|
||||
err)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetPriceConversion() error cannot be nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetAccountPlan(t *testing.T) {
|
||||
accPlans := []string{"basic", "startup", "hobbyist", "standard", "professional", "enterprise"}
|
||||
for _, plan := range accPlans {
|
||||
err := c.SetAccountPlan(plan)
|
||||
if err != nil {
|
||||
t.Error("Test Failed - SetAccountPlan() error", err)
|
||||
}
|
||||
|
||||
switch plan {
|
||||
case "basic":
|
||||
if c.Plan != Basic {
|
||||
t.Error("Test Failed - SetAccountPlan() error basic plan not set correctly")
|
||||
}
|
||||
case "startup":
|
||||
if c.Plan != Startup {
|
||||
t.Error("Test Failed - SetAccountPlan() error startup plan not set correctly")
|
||||
}
|
||||
case "hobbyist":
|
||||
if c.Plan != Hobbyist {
|
||||
t.Error("Test Failed - SetAccountPlan() error hobbyist plan not set correctly")
|
||||
}
|
||||
case "standard":
|
||||
if c.Plan != Standard {
|
||||
t.Error("Test Failed - SetAccountPlan() error standard plan not set correctly")
|
||||
}
|
||||
case "professional":
|
||||
if c.Plan != Professional {
|
||||
t.Error("Test Failed - SetAccountPlan() error professional plan not set correctly")
|
||||
}
|
||||
case "enterprise":
|
||||
if c.Plan != Enterprise {
|
||||
t.Error("Test Failed - SetAccountPlan() error enterprise plan not set correctly")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := c.SetAccountPlan("bra"); err == nil {
|
||||
t.Error("Test Failed - SetAccountPlan() error cannot be nil")
|
||||
}
|
||||
}
|
||||
363
currency/coinmarketcap/coinmarketcap_types.go
Normal file
363
currency/coinmarketcap/coinmarketcap_types.go
Normal file
@@ -0,0 +1,363 @@
|
||||
package coinmarketcap
|
||||
|
||||
import "time"
|
||||
|
||||
// Settings defines the current settings from configuration file
|
||||
type Settings struct {
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Verbose bool `json:"verbose"`
|
||||
APIkey string `json:"apiKey"`
|
||||
AccountPlan string `json:"accountPlan"`
|
||||
}
|
||||
|
||||
// Status defines a response status JSON struct that is received with every
|
||||
// HTTP request
|
||||
type Status struct {
|
||||
Timestamp string `json:"timestamp"`
|
||||
ErrorCode int64 `json:"error_code"`
|
||||
ErrorMessage string `json:"error_message"`
|
||||
Elapsed int64 `json:"elapsed"`
|
||||
CreditCount int64 `json:"credit_count"`
|
||||
}
|
||||
|
||||
// Currency defines a generic sub type to capture currency data
|
||||
type Currency struct {
|
||||
Price float64 `json:"price"`
|
||||
Volume24H float64 `json:"volume_24h"`
|
||||
Volume24HAdjusted float64 `json:"volume_24h_adjusted"`
|
||||
Volume7D float64 `json:"volume_7d"`
|
||||
Volume30D float64 `json:"volume_30d"`
|
||||
PercentChange1H float64 `json:"percent_change_1h"`
|
||||
PercentChangeVolume24H float64 `json:"percent_change_volume_24h"`
|
||||
PercentChangeVolume7D float64 `json:"percent_change_volume_7d"`
|
||||
PercentChangeVolume30D float64 `json:"percent_change_volume_30d"`
|
||||
MarketCap float64 `json:"market_cap"`
|
||||
TotalMarketCap float64 `json:"total_market_cap"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
}
|
||||
|
||||
// OHLC defines a generic sub type for OHLC currency data
|
||||
type OHLC struct {
|
||||
Open float64 `json:"open"`
|
||||
High float64 `json:"high"`
|
||||
Low float64 `json:"low"`
|
||||
Close float64 `json:"close"`
|
||||
Volume float64 `json:"volume"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
// CryptoCurrencyInfo defines cryptocurrency information
|
||||
type CryptoCurrencyInfo map[string]struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Category string `json:"category"`
|
||||
Slug string `json:"slug"`
|
||||
Logo string `json:"logo"`
|
||||
Tags []string `json:"tags"`
|
||||
Platform interface{} `json:"platform"`
|
||||
Urls struct {
|
||||
Website []string `json:"website"`
|
||||
Explorer []string `json:"explorer"`
|
||||
SourceCode []string `json:"source_code"`
|
||||
MessageBoard []string `json:"message_board"`
|
||||
Chat []interface{} `json:"chat"`
|
||||
Announcement []interface{} `json:"announcement"`
|
||||
Reddit []string `json:"reddit"`
|
||||
Twitter []string `json:"twitter"`
|
||||
} `json:"urls"`
|
||||
}
|
||||
|
||||
// CryptoCurrencyMap defines a cryptocurrency struct
|
||||
type CryptoCurrencyMap struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Slug string `json:"slug"`
|
||||
IsActive int `json:"is_active"`
|
||||
FirstHistoricalData time.Time `json:"first_historical_data"`
|
||||
LastHistoricalData time.Time `json:"last_historical_data"`
|
||||
Platform interface{} `json:"platform"`
|
||||
}
|
||||
|
||||
// CryptocurrencyHistoricalListings defines a historical listing data
|
||||
type CryptocurrencyHistoricalListings struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Slug string `json:"slug"`
|
||||
CmcRank int `json:"cmc_rank"`
|
||||
NumMarketPairs int `json:"num_market_pairs"`
|
||||
CirculatingSupply float64 `json:"circulating_supply"`
|
||||
TotalSupply float64 `json:"total_supply"`
|
||||
MaxSupply float64 `json:"max_supply"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
Quote struct {
|
||||
USD Currency `json:"USD"`
|
||||
BTC Currency `json:"BTC"`
|
||||
} `json:"quote"`
|
||||
}
|
||||
|
||||
// CryptocurrencyLatestListings defines latest cryptocurrency listing data
|
||||
type CryptocurrencyLatestListings struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Slug string `json:"slug"`
|
||||
CmcRank int `json:"cmc_rank"`
|
||||
NumMarketPairs int `json:"num_market_pairs"`
|
||||
CirculatingSupply float64 `json:"circulating_supply"`
|
||||
TotalSupply float64 `json:"total_supply"`
|
||||
MaxSupply float64 `json:"max_supply"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
DateAdded time.Time `json:"date_added"`
|
||||
Tags []string `json:"tags"`
|
||||
Platform interface{} `json:"platform"`
|
||||
Quote struct {
|
||||
USD Currency `json:"USD"`
|
||||
BTC Currency `json:"BTC"`
|
||||
} `json:"quote"`
|
||||
}
|
||||
|
||||
// CryptocurrencyLatestMarketPairs defines the latest cryptocurrency pairs
|
||||
type CryptocurrencyLatestMarketPairs struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
NumMarketPairs int `json:"num_market_pairs"`
|
||||
MarketPairs []struct {
|
||||
Exchange struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
} `json:"exchange"`
|
||||
MarketPair string `json:"market_pair"`
|
||||
MarketPairBase struct {
|
||||
CurrencyID int `json:"currency_id"`
|
||||
CurrencySymbol string `json:"currency_symbol"`
|
||||
CurrencyType string `json:"currency_type"`
|
||||
} `json:"market_pair_base"`
|
||||
MarketPairQuote struct {
|
||||
CurrencyID int `json:"currency_id"`
|
||||
CurrencySymbol string `json:"currency_symbol"`
|
||||
CurrencyType string `json:"currency_type"`
|
||||
} `json:"market_pair_quote"`
|
||||
Quote struct {
|
||||
ExchangeReported struct {
|
||||
Price float64 `json:"price"`
|
||||
Volume24HBase float64 `json:"volume_24h_base"`
|
||||
Volume24HQuote float64 `json:"volume_24h_quote"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
} `json:"exchange_reported"`
|
||||
USD Currency `json:"USD"`
|
||||
} `json:"quote"`
|
||||
} `json:"market_pairs"`
|
||||
}
|
||||
|
||||
// CryptocurrencyOHLCHistorical defines open high low close historical data
|
||||
type CryptocurrencyOHLCHistorical struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Quotes []struct {
|
||||
TimeOpen time.Time `json:"time_open"`
|
||||
TimeClose time.Time `json:"time_close"`
|
||||
Quote struct {
|
||||
USD OHLC `json:"USD"`
|
||||
} `json:"quote"`
|
||||
} `json:"quotes"`
|
||||
}
|
||||
|
||||
// CryptocurrencyOHLCLatest defines open high low close latest data
|
||||
type CryptocurrencyOHLCLatest map[string]struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
TimeOpen time.Time `json:"time_open"`
|
||||
TimeClose interface{} `json:"time_close"`
|
||||
Quote struct {
|
||||
USD OHLC `json:"USD"`
|
||||
} `json:"quote"`
|
||||
}
|
||||
|
||||
// CryptocurrencyLatestQuotes defines latest cryptocurrency quotation data
|
||||
type CryptocurrencyLatestQuotes map[string]struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Slug string `json:"slug"`
|
||||
CirculatingSupply float64 `json:"circulating_supply"`
|
||||
TotalSupply float64 `json:"total_supply"`
|
||||
MaxSupply float64 `json:"max_supply"`
|
||||
DateAdded time.Time `json:"date_added"`
|
||||
NumMarketPairs int `json:"num_market_pairs"`
|
||||
CmcRank int `json:"cmc_rank"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
Tags []string `json:"tags"`
|
||||
Platform interface{} `json:"platform"`
|
||||
Quote struct {
|
||||
USD Currency `json:"USD"`
|
||||
} `json:"quote"`
|
||||
}
|
||||
|
||||
// CryptocurrencyHistoricalQuotes defines historical cryptocurrency quotation
|
||||
// data
|
||||
type CryptocurrencyHistoricalQuotes struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Quotes []struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Quote struct {
|
||||
USD Currency `json:"USD"`
|
||||
} `json:"quote"`
|
||||
} `json:"quotes"`
|
||||
}
|
||||
|
||||
// ExchangeInfo defines exchange information
|
||||
type ExchangeInfo map[string]struct {
|
||||
Urls struct {
|
||||
Website []string `json:"website"`
|
||||
Twitter []string `json:"twitter"`
|
||||
Blog []interface{} `json:"blog"`
|
||||
Chat []string `json:"chat"`
|
||||
Fee []string `json:"fee"`
|
||||
} `json:"urls"`
|
||||
Logo string `json:"logo"`
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
}
|
||||
|
||||
// ExchangeMap defines a data for an exchange
|
||||
type ExchangeMap struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
IsActive int `json:"is_active"`
|
||||
FirstHistoricalData time.Time `json:"first_historical_data"`
|
||||
LastHistoricalData time.Time `json:"last_historical_data"`
|
||||
}
|
||||
|
||||
// ExchangeHistoricalListings defines historical exchange listings
|
||||
type ExchangeHistoricalListings struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
CmcRank int `json:"cmc_rank"`
|
||||
NumMarketPairs int `json:"num_market_pairs"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Quote struct {
|
||||
USD Currency `json:"USD"`
|
||||
} `json:"quote"`
|
||||
}
|
||||
|
||||
// ExchangeLatestListings defines latest exchange listings
|
||||
type ExchangeLatestListings struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
NumMarketPairs int `json:"num_market_pairs"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
Quote struct {
|
||||
USD Currency `json:"USD"`
|
||||
} `json:"quote"`
|
||||
}
|
||||
|
||||
// ExchangeLatestMarketPairs defines latest market pairs
|
||||
type ExchangeLatestMarketPairs struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
NumMarketPairs int `json:"num_market_pairs"`
|
||||
MarketPairs []struct {
|
||||
MarketPair string `json:"market_pair"`
|
||||
MarketPairBase struct {
|
||||
CurrencyID int `json:"currency_id"`
|
||||
CurrencySymbol string `json:"currency_symbol"`
|
||||
CurrencyType string `json:"currency_type"`
|
||||
} `json:"market_pair_base"`
|
||||
MarketPairQuote struct {
|
||||
CurrencyID int `json:"currency_id"`
|
||||
CurrencySymbol string `json:"currency_symbol"`
|
||||
CurrencyType string `json:"currency_type"`
|
||||
} `json:"market_pair_quote"`
|
||||
Quote struct {
|
||||
ExchangeReported struct {
|
||||
Price float64 `json:"price"`
|
||||
Volume24HBase float64 `json:"volume_24h_base"`
|
||||
Volume24HQuote float64 `json:"volume_24h_quote"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
} `json:"exchange_reported"`
|
||||
USD Currency `json:"USD"`
|
||||
} `json:"quote"`
|
||||
} `json:"market_pairs"`
|
||||
}
|
||||
|
||||
// ExchangeLatestQuotes defines latest exchange quotations
|
||||
type ExchangeLatestQuotes struct {
|
||||
Binance struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
NumMarketPairs int `json:"num_market_pairs"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
Quote struct {
|
||||
USD Currency `json:"USD"`
|
||||
} `json:"quote"`
|
||||
} `json:"binance"`
|
||||
}
|
||||
|
||||
// ExchangeHistoricalQuotes defines historical exchange quotations
|
||||
type ExchangeHistoricalQuotes struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
Quotes []struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Quote struct {
|
||||
USD Currency `json:"USD"`
|
||||
} `json:"quote"`
|
||||
NumMarketPairs int `json:"num_market_pairs"`
|
||||
} `json:"quotes"`
|
||||
}
|
||||
|
||||
// GlobalMeticLatestQuotes defines latest global metric quotations
|
||||
type GlobalMeticLatestQuotes struct {
|
||||
BtcDominance float64 `json:"btc_dominance"`
|
||||
EthDominance float64 `json:"eth_dominance"`
|
||||
ActiveCryptocurrencies int `json:"active_cryptocurrencies"`
|
||||
ActiveMarketPairs int `json:"active_market_pairs"`
|
||||
ActiveExchanges int `json:"active_exchanges"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
Quote struct {
|
||||
USD Currency `json:"USD"`
|
||||
} `json:"quote"`
|
||||
}
|
||||
|
||||
// GlobalMeticHistoricalQuotes defines historical global metric quotations
|
||||
type GlobalMeticHistoricalQuotes struct {
|
||||
Quotes []struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
BtcDominance float64 `json:"btc_dominance"`
|
||||
Quote struct {
|
||||
USD Currency `json:"USD"`
|
||||
} `json:"quote"`
|
||||
} `json:"quotes"`
|
||||
}
|
||||
|
||||
// PriceConversion defines price conversion data
|
||||
type PriceConversion struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Amount float64 `json:"amount"`
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
Quote struct {
|
||||
GBP Currency `json:"GBP"`
|
||||
LTC Currency `json:"LTC"`
|
||||
USD Currency `json:"USD"`
|
||||
} `json:"quote"`
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
package currency
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency/coinmarketcap"
|
||||
"github.com/thrasher-/gocryptotrader/currency/forexprovider"
|
||||
"github.com/thrasher-/gocryptotrader/currency/pair"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
@@ -27,6 +30,10 @@ var (
|
||||
|
||||
BaseCurrency string
|
||||
FXProviders *forexprovider.ForexProviders
|
||||
|
||||
CryptocurrencyProvider *coinmarketcap.Coinmarketcap
|
||||
TotalCryptocurrencies []Data
|
||||
TotalExchanges []Data
|
||||
)
|
||||
|
||||
// SetDefaults sets the default currency provider and settings for
|
||||
@@ -201,3 +208,113 @@ func ConvertCurrency(amount float64, from, to string) (float64, error) {
|
||||
|
||||
return converted * resultTo, nil
|
||||
}
|
||||
|
||||
// Data defines information pertaining to exchange or a cryptocurrency from
|
||||
// coinmarketcap
|
||||
type Data struct {
|
||||
ID int
|
||||
Name string
|
||||
Symbol string `json:",omitempty"`
|
||||
Slug string
|
||||
Active bool
|
||||
LastUpdated time.Time
|
||||
}
|
||||
|
||||
// SeedCryptocurrencyMarketData seeds cryptocurrency market data
|
||||
func SeedCryptocurrencyMarketData(settings coinmarketcap.Settings) error {
|
||||
if !settings.Enabled {
|
||||
return errors.New("not enabled please set in config.json with apikey and account levels")
|
||||
}
|
||||
|
||||
if CryptocurrencyProvider == nil {
|
||||
err := setupCryptoProvider(settings)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cryptoData, err := CryptocurrencyProvider.GetCryptocurrencyIDMap()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, data := range cryptoData {
|
||||
var active bool
|
||||
if data.IsActive == 1 {
|
||||
active = true
|
||||
}
|
||||
|
||||
TotalCryptocurrencies = append(TotalCryptocurrencies, Data{
|
||||
ID: data.ID,
|
||||
Name: data.Name,
|
||||
Symbol: data.Symbol,
|
||||
Slug: data.Slug,
|
||||
Active: active,
|
||||
LastUpdated: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SeedExchangeMarketData seeds exchange market data
|
||||
func SeedExchangeMarketData(settings coinmarketcap.Settings) error {
|
||||
if !settings.Enabled {
|
||||
return errors.New("not enabled please set in config.json with apikey and account levels")
|
||||
}
|
||||
|
||||
if CryptocurrencyProvider == nil {
|
||||
err := setupCryptoProvider(settings)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
exchangeData, err := CryptocurrencyProvider.GetExchangeMap(0, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, data := range exchangeData {
|
||||
var active bool
|
||||
if data.IsActive == 1 {
|
||||
active = true
|
||||
}
|
||||
|
||||
TotalExchanges = append(TotalExchanges, Data{
|
||||
ID: data.ID,
|
||||
Name: data.Name,
|
||||
Slug: data.Slug,
|
||||
Active: active,
|
||||
LastUpdated: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupCryptoProvider(settings coinmarketcap.Settings) error {
|
||||
if settings.APIkey == "" ||
|
||||
settings.APIkey == "key" ||
|
||||
settings.AccountPlan == "" ||
|
||||
settings.AccountPlan == "accountPlan" {
|
||||
return errors.New("currencyprovider error api key or plan not set in config.json")
|
||||
}
|
||||
|
||||
CryptocurrencyProvider = new(coinmarketcap.Coinmarketcap)
|
||||
CryptocurrencyProvider.SetDefaults()
|
||||
CryptocurrencyProvider.Setup(settings)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTotalMarketCryptocurrencies returns the total seeded market
|
||||
// cryptocurrencies
|
||||
func GetTotalMarketCryptocurrencies() []Data {
|
||||
return TotalCryptocurrencies
|
||||
}
|
||||
|
||||
// GetTotalMarketExchanges returns the total seeded market exchanges
|
||||
func GetTotalMarketExchanges() []Data {
|
||||
return TotalExchanges
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -290,7 +291,31 @@ func (r *Requester) DoRequest(req *http.Request, method, path string, headers ma
|
||||
return errors.New("resp is nil")
|
||||
}
|
||||
|
||||
contents, err := ioutil.ReadAll(resp.Body)
|
||||
var reader io.ReadCloser
|
||||
switch resp.Header.Get("Content-Encoding") {
|
||||
case "gzip":
|
||||
reader, err = gzip.NewReader(resp.Body)
|
||||
defer reader.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case "json":
|
||||
reader = resp.Body
|
||||
|
||||
default:
|
||||
switch {
|
||||
case common.StringContains(resp.Header.Get("Content-Type"), "application/json"):
|
||||
reader = resp.Body
|
||||
|
||||
default:
|
||||
log.Warnf("encoding is not JSON for request response but receieved %v",
|
||||
resp.Header.Get("Content-Type"))
|
||||
reader = resp.Body
|
||||
}
|
||||
}
|
||||
|
||||
contents, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
26
main.go
26
main.go
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/communications"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
"github.com/thrasher-/gocryptotrader/currency/coinmarketcap"
|
||||
"github.com/thrasher-/gocryptotrader/currency/forexprovider"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
@@ -117,6 +118,31 @@ func main() {
|
||||
bot.comms = communications.NewComm(bot.config.GetCommunicationsConfig())
|
||||
bot.comms.GetEnabledCommunicationMediums()
|
||||
|
||||
if bot.config.GetCryptocurrencyProviderConfig().Enabled {
|
||||
log.Debug("Seeding full market data...")
|
||||
err = currency.SeedCryptocurrencyMarketData(coinmarketcap.Settings(bot.config.GetCryptocurrencyProviderConfig()))
|
||||
if err != nil {
|
||||
log.Warnf("Failure seeding cryptocurrency market data %s", err)
|
||||
} else {
|
||||
if *verbosity {
|
||||
log.Debugf("Total market cryptocurrencies: %d",
|
||||
len(currency.GetTotalMarketCryptocurrencies()))
|
||||
}
|
||||
}
|
||||
|
||||
err = currency.SeedExchangeMarketData(coinmarketcap.Settings(bot.config.GetCryptocurrencyProviderConfig()))
|
||||
if err != nil {
|
||||
log.Warnf("Failure seeding exchange market data %s", err)
|
||||
} else {
|
||||
if *verbosity {
|
||||
log.Debugf("Total market exchanges: %d",
|
||||
len(currency.GetTotalMarketExchanges()))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Debug("Cryptocurrency provider not enabled.")
|
||||
}
|
||||
|
||||
log.Debugf("Fiat display currency: %s.", bot.config.Currency.FiatDisplayCurrency)
|
||||
currency.BaseCurrency = bot.config.Currency.FiatDisplayCurrency
|
||||
currency.FXProviders = forexprovider.StartFXService(bot.config.GetCurrencyConfig().ForexProviders)
|
||||
|
||||
7
testdata/configtest.json
vendored
7
testdata/configtest.json
vendored
@@ -48,6 +48,13 @@
|
||||
"primaryProvider": false
|
||||
}
|
||||
],
|
||||
"cryptocurrencyProvider": {
|
||||
"name": "CoinMarketCap",
|
||||
"enabled": false,
|
||||
"verbose": false,
|
||||
"apiKey": "Key",
|
||||
"accountPlan": "accountPlan"
|
||||
},
|
||||
"cryptocurrencies": "BTC,LTC,ETH,DOGE,DASH,XRP,XMR",
|
||||
"currencyPairFormat": {
|
||||
"uppercase": true,
|
||||
|
||||
Reference in New Issue
Block a user