mirror of https://github.com/miguelmota/cointop
use coinmarketcap pro api v1
parent
3080174642
commit
e457a89755
@ -1,63 +0,0 @@
|
||||
package coinmarketcap
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/miguelmota/cointop/cointop/common/cmc/types"
|
||||
)
|
||||
|
||||
// V1Tickers get information about all coins listed in Coin Market Cap
|
||||
func V1Tickers(limit int, convert string) (map[string]*types.V1Ticker, error) {
|
||||
var params []string
|
||||
if limit >= 0 {
|
||||
params = append(params, fmt.Sprintf("limit=%v", limit))
|
||||
}
|
||||
if convert != "" {
|
||||
params = append(params, fmt.Sprintf("convert=%v", convert))
|
||||
}
|
||||
baseURL := "https://api.coinmarketcap.com/v1"
|
||||
url := fmt.Sprintf("%s/ticker?%s", baseURL, strings.Join(params, "&"))
|
||||
|
||||
resp, err := makeReq(url)
|
||||
var data []*types.V1Ticker
|
||||
err = json.Unmarshal(resp, &data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var mapstring []map[string]interface{}
|
||||
err = json.Unmarshal(resp, &mapstring)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// creating map from the array
|
||||
allCoins := make(map[string]*types.V1Ticker)
|
||||
for i := 0; i < len(data); i++ {
|
||||
allCoins[data[i].ID] = data[i]
|
||||
}
|
||||
|
||||
for _, item := range mapstring {
|
||||
id, _ := item["id"].(string)
|
||||
priceifc := item[fmt.Sprintf("price_%s", strings.ToLower(convert))]
|
||||
pricestr, _ := priceifc.(string)
|
||||
price, _ := strconv.ParseFloat(pricestr, 64)
|
||||
marketcapifc := item[fmt.Sprintf("market_cap_%s", strings.ToLower(convert))]
|
||||
marketcapstr, _ := marketcapifc.(string)
|
||||
marketcap, _ := strconv.ParseFloat(marketcapstr, 64)
|
||||
volumeifc := item[fmt.Sprintf("24h_volume_%s", strings.ToLower(convert))]
|
||||
volumestr, _ := volumeifc.(string)
|
||||
volume, _ := strconv.ParseFloat(volumestr, 64)
|
||||
quotes := &types.TickerQuote{
|
||||
Price: price,
|
||||
Volume24H: volume,
|
||||
MarketCap: marketcap,
|
||||
}
|
||||
allCoins[id].Quotes = map[string]*types.TickerQuote{}
|
||||
allCoins[id].Quotes[strings.ToUpper(convert)] = quotes
|
||||
}
|
||||
|
||||
return allCoins, nil
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package coinmarketcap
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestV1Tickers(t *testing.T) {
|
||||
coins, err := V1Tickers(10, "EUR")
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if len(coins) != 10 {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
MIT license
|
||||
|
||||
Copyright (C) 2015 Miguel Mota
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,753 @@
|
||||
// Package coinmarketcap Coin Market Cap API client for Go
|
||||
package coinmarketcap
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Client the CoinMarketCap client
|
||||
type Client struct {
|
||||
proAPIKey string
|
||||
Cryptocurrency *CryptocurrencyService
|
||||
Exchange *ExchangeService
|
||||
GlobalMetrics *GlobalMetricsService
|
||||
Tools *ToolsService
|
||||
common service
|
||||
}
|
||||
|
||||
// Config the client config structure
|
||||
type Config struct {
|
||||
ProAPIKey string
|
||||
}
|
||||
|
||||
// CryptocurrencyService ...
|
||||
type CryptocurrencyService service
|
||||
|
||||
// ExchangeService ...
|
||||
type ExchangeService service
|
||||
|
||||
// GlobalMetricsService ...
|
||||
type GlobalMetricsService service
|
||||
|
||||
// ToolsService ...
|
||||
type ToolsService service
|
||||
|
||||
// Status is the status structure
|
||||
type Status struct {
|
||||
Timestamp string `json:"timestamp"`
|
||||
ErrorCode int `json:"error_code"`
|
||||
ErrorMessage *string `json:"error_message"`
|
||||
Elapsed int `json:"elapsed"`
|
||||
CreditCount int `json:"credit_count"`
|
||||
}
|
||||
|
||||
// Response is the response structure
|
||||
type Response struct {
|
||||
Status Status `json:"status"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
// Listing is the listing structure
|
||||
type Listing struct {
|
||||
ID float64 `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 string `json:"date_added"`
|
||||
NumMarketPairs float64 `json:"num_market_pairs"`
|
||||
CMCRank float64 `json:"cmc_rank"`
|
||||
LastUpdated string `json:"last_updated"`
|
||||
Quote map[string]*Quote `json:"quote"`
|
||||
}
|
||||
|
||||
// MapListing is the structure of a map listing
|
||||
type MapListing struct {
|
||||
ID float64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Slug string `json:"slug"`
|
||||
IsActive int `json:"is_active"`
|
||||
FirstHistoricalData string `json:"first_historical_data"`
|
||||
LastHistoricalData string `json:"last_historical_data"`
|
||||
Platform *string
|
||||
}
|
||||
|
||||
// ConvertListing is the converted listing structure
|
||||
type ConvertListing struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Amount float64 `json:"amount"`
|
||||
LastUpdated string `json:"last_updated"`
|
||||
Quote map[string]*ConvertQuote `json:"quote"`
|
||||
}
|
||||
|
||||
// ConvertQuote is the converted listing structure
|
||||
type ConvertQuote struct {
|
||||
Price float64 `json:"price"`
|
||||
LastUpdated string `json:"last_updated"`
|
||||
}
|
||||
|
||||
// QuoteLatest is the quotes structure
|
||||
type QuoteLatest struct {
|
||||
ID float64 `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 string `json:"date_added"`
|
||||
NumMarketPairs float64 `json:"num_market_pairs"`
|
||||
CMCRank float64 `json:"cmc_rank"`
|
||||
LastUpdated string `json:"last_updated"`
|
||||
Quote map[string]*Quote `json:"quote"`
|
||||
}
|
||||
|
||||
// Quote is the quote structure
|
||||
type Quote struct {
|
||||
Price float64 `json:"price"`
|
||||
Volume24H float64 `json:"volume_24h"`
|
||||
PercentChange1H float64 `json:"percent_change_1h"`
|
||||
PercentChange24H float64 `json:"percent_change_24h"`
|
||||
PercentChange7D float64 `json:"percent_change_7d"`
|
||||
MarketCap float64 `json:"market_cap"`
|
||||
LastUpdated string `json:"last_updated"`
|
||||
}
|
||||
|
||||
// MarketMetrics is the market metrics structure
|
||||
type MarketMetrics struct {
|
||||
BTCDominance float64 `json:"btc_dominance"`
|
||||
ETHDominance float64 `json:"eth_dominance"`
|
||||
ActiveCryptocurrencies float64 `json:"active_cryptocurrencies"`
|
||||
ActiveMarketPairs float64 `json:"active_market_pairs"`
|
||||
ActiveExchanges float64 `json:"active_exchanges"`
|
||||
LastUpdated string `json:"last_updated"`
|
||||
Quote map[string]*MarketMetricsQuote `json:"quote"`
|
||||
}
|
||||
|
||||
// MarketMetricsQuote is the quote structure
|
||||
type MarketMetricsQuote struct {
|
||||
TotalMarketCap float64 `json:"total_market_cap"`
|
||||
TotalVolume24H float64 `json:"total_volume_24h"`
|
||||
LastUpdated string `json:"last_updated"`
|
||||
}
|
||||
|
||||
// CryptocurrencyInfo options
|
||||
type CryptocurrencyInfo struct {
|
||||
ID float64 `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"`
|
||||
Urls map[string]interface{} `json:"urls"`
|
||||
}
|
||||
|
||||
// InfoOptions options
|
||||
type InfoOptions struct {
|
||||
ID string
|
||||
Symbol string
|
||||
}
|
||||
|
||||
// ListingOptions options
|
||||
type ListingOptions struct {
|
||||
Start int
|
||||
Limit int
|
||||
Convert string
|
||||
Sort string
|
||||
}
|
||||
|
||||
// MapOptions options
|
||||
type MapOptions struct {
|
||||
ListingStatus string
|
||||
Start int
|
||||
Limit int
|
||||
Symbol string
|
||||
}
|
||||
|
||||
// QuoteOptions options
|
||||
type QuoteOptions struct {
|
||||
// Covert suppots multiple currencies command separated. eg. "BRL,USD"
|
||||
Convert string
|
||||
// Symbols suppots multiple tickers command separated. eg. "BTC,ETH,XRP"
|
||||
Symbol string
|
||||
}
|
||||
|
||||
// ConvertOptions options
|
||||
type ConvertOptions struct {
|
||||
Amount float64
|
||||
ID string
|
||||
Symbol string
|
||||
Time int
|
||||
Convert string
|
||||
}
|
||||
|
||||
// MarketPairOptions options
|
||||
type MarketPairOptions struct {
|
||||
ID int
|
||||
Symbol string
|
||||
Start int
|
||||
Limit int
|
||||
Convert string
|
||||
}
|
||||
|
||||
// service is abstraction for individual endpoint resources
|
||||
type service struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// SortOptions sort options
|
||||
var SortOptions sortOptions
|
||||
|
||||
type sortOptions struct {
|
||||
Name string
|
||||
Symbol string
|
||||
DateAdded string
|
||||
MarketCap string
|
||||
Price string
|
||||
CirculatingSupply string
|
||||
TotalSupply string
|
||||
MaxSupply string
|
||||
NumMarketPairs string
|
||||
Volume24H string
|
||||
PercentChange1H string
|
||||
PercentChange24H string
|
||||
PercentChange7D string
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrTypeAssertion is type assertion error
|
||||
ErrTypeAssertion = errors.New("type assertion error")
|
||||
)
|
||||
|
||||
var (
|
||||
siteURL = "https://coinmarketcap.com"
|
||||
baseURL = "https://pro-api.coinmarketcap.com/v1"
|
||||
coinGraphURL = "https://graphs2.coinmarketcap.com/currencies"
|
||||
globalMarketGraphURL = "https://graphs2.coinmarketcap.com/global/marketcap-total"
|
||||
altcoinMarketGraphURL = "https://graphs2.coinmarketcap.com/global/marketcap-altcoin"
|
||||
)
|
||||
|
||||
// NewClient initializes a new client
|
||||
func NewClient(cfg *Config) *Client {
|
||||
if cfg == nil {
|
||||
cfg = new(Config)
|
||||
}
|
||||
|
||||
if cfg.ProAPIKey == "" {
|
||||
cfg.ProAPIKey = os.Getenv("CMC_PRO_API_KEY")
|
||||
}
|
||||
|
||||
if cfg.ProAPIKey == "" {
|
||||
log.Fatal("Pro API Key is required")
|
||||
}
|
||||
|
||||
c := &Client{
|
||||
proAPIKey: cfg.ProAPIKey,
|
||||
}
|
||||
|
||||
c.common.client = c
|
||||
c.Cryptocurrency = (*CryptocurrencyService)(&c.common)
|
||||
c.Exchange = (*ExchangeService)(&c.common)
|
||||
c.GlobalMetrics = (*GlobalMetricsService)(&c.common)
|
||||
c.Tools = (*ToolsService)(&c.common)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// Info returns all static metadata for one or more cryptocurrencies including name, symbol, logo, and its various registered URLs.
|
||||
func (s *CryptocurrencyService) Info(options *InfoOptions) (map[string]*CryptocurrencyInfo, error) {
|
||||
var params []string
|
||||
if options == nil {
|
||||
options = new(InfoOptions)
|
||||
}
|
||||
if options.ID != "" {
|
||||
params = append(params, fmt.Sprintf("id=%s", options.ID))
|
||||
}
|
||||
if options.Symbol != "" {
|
||||
params = append(params, fmt.Sprintf("symbol=%s", options.Symbol))
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/cryptocurrency/info?%s", baseURL, strings.Join(params, "&"))
|
||||
|
||||
body, err := s.client.makeReq(url)
|
||||
resp := new(Response)
|
||||
err = json.Unmarshal(body, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result = make(map[string]*CryptocurrencyInfo)
|
||||
ifcs, ok := resp.Data.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, ErrTypeAssertion
|
||||
}
|
||||
|
||||
for k, v := range ifcs {
|
||||
info := new(CryptocurrencyInfo)
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(b, info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result[k] = info
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// LatestListings gets a paginated list of all cryptocurrencies with latest market data. You can configure this call to sort by market cap or another market ranking field. Use the "convert" option to return market values in multiple fiat and cryptocurrency conversions in the same call.
|
||||
func (s *CryptocurrencyService) LatestListings(options *ListingOptions) ([]*Listing, error) {
|
||||
var params []string
|
||||
if options == nil {
|
||||
options = new(ListingOptions)
|
||||
}
|
||||
if options.Start != 0 {
|
||||
params = append(params, fmt.Sprintf("start=%v", options.Start))
|
||||
}
|
||||
if options.Limit != 0 {
|
||||
params = append(params, fmt.Sprintf("limit=%v", options.Limit))
|
||||
}
|
||||
if options.Convert != "" {
|
||||
params = append(params, fmt.Sprintf("convert=%s", options.Convert))
|
||||
}
|
||||
if options.Sort != "" {
|
||||
params = append(params, fmt.Sprintf("sort=%s", options.Sort))
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/cryptocurrency/listings/latest?%s", baseURL, strings.Join(params, "&"))
|
||||
|
||||
body, err := s.client.makeReq(url)
|
||||
resp := new(Response)
|
||||
err = json.Unmarshal(body, &resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("JSON Error: [%s]. Response body: [%s]", err.Error(), string(body))
|
||||
}
|
||||
|
||||
var listings []*Listing
|
||||
ifcs, ok := resp.Data.([]interface{})
|
||||
if !ok {
|
||||
return nil, ErrTypeAssertion
|
||||
}
|
||||
|
||||
for i := range ifcs {
|
||||
ifc := ifcs[i]
|
||||
listing := new(Listing)
|
||||
b, err := json.Marshal(ifc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(b, listing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listings = append(listings, listing)
|
||||
}
|
||||
|
||||
return listings, nil
|
||||
}
|
||||
|
||||
// Map returns a paginated list of all cryptocurrencies by CoinMarketCap ID.
|
||||
func (s *CryptocurrencyService) Map(options *MapOptions) ([]*MapListing, error) {
|
||||
var params []string
|
||||
if options == nil {
|
||||
options = new(MapOptions)
|
||||
}
|
||||
|
||||
if options.ListingStatus != "" {
|
||||
params = append(params, fmt.Sprintf("listing_status=%s", options.ListingStatus))
|
||||
}
|
||||
|
||||
if options.Start != 0 {
|
||||
params = append(params, fmt.Sprintf("start=%d", options.Start))
|
||||
}
|
||||
|
||||
if options.Limit != 0 {
|
||||
params = append(params, fmt.Sprintf("limit=%d", options.Limit))
|
||||
}
|
||||
|
||||
if options.Symbol != "" {
|
||||
params = append(params, fmt.Sprintf("symbol=%s", options.Symbol))
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/cryptocurrency/map?%s", baseURL, strings.Join(params, "&"))
|
||||
|
||||
body, err := s.client.makeReq(url)
|
||||
resp := new(Response)
|
||||
err = json.Unmarshal(body, &resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("JSON Error: [%s]. Response body: [%s]", err.Error(), string(body))
|
||||
}
|
||||
|
||||
var result []*MapListing
|
||||
ifcs, ok := resp.Data.(interface{})
|
||||
if !ok {
|
||||
return nil, ErrTypeAssertion
|
||||
}
|
||||
|
||||
for _, item := range ifcs.([]interface{}) {
|
||||
value := new(MapListing)
|
||||
b, err := json.Marshal(item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(b, value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result = append(result, value)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Exchange ...
|
||||
type Exchange struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
}
|
||||
|
||||
// MarketPairBase ...
|
||||
type MarketPairBase struct {
|
||||
CurrencyID int `json:"currency_id"`
|
||||
CurrencySymbol string `json:"currency_symbol"`
|
||||
CurrencyType string `json:"currency_type"`
|
||||
}
|
||||
|
||||
// MarketPairQuote ...
|
||||
type MarketPairQuote struct {
|
||||
CurrencyID int `json:"currency_id"`
|
||||
CurrencySymbol string `json:"currency_symbol"`
|
||||
CurrencyType string `json:"currency_type"`
|
||||
}
|
||||
|
||||
// ExchangeQuote ...
|
||||
type ExchangeQuote struct {
|
||||
Price float64 `json:"price"`
|
||||
Volume24 float64 `json:"volume_24h"`
|
||||
Volume24HBase float64 `json:"volume_24h_base"` // for 'exchange_reported'
|
||||
Volume24HQuote float64 `json:"volume_24h_quote"` // for 'exchange_reported'
|
||||
LastUpdated string `json:"last_updated"`
|
||||
}
|
||||
|
||||
// ExchangeQuotes ...
|
||||
type ExchangeQuotes map[string]*ExchangeQuote
|
||||
|
||||
// ExchangeReported ...
|
||||
type ExchangeReported struct {
|
||||
Price float64 `json:"price"`
|
||||
Volume24HBase float64 `json:"volume_24h_base"`
|
||||
Volume24HQuote float64 `json:"volume_24h_quote"`
|
||||
LastUpdated string `json:"last_updated"`
|
||||
}
|
||||
|
||||
// MarketPairs ...
|
||||
type MarketPairs struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
NumMarketPairs int `json:"num_market_pairs"`
|
||||
MarketPairs []*MarketPair `json:"market_pairs"`
|
||||
}
|
||||
|
||||
// MarketPair ...
|
||||
type MarketPair struct {
|
||||
Exchange *Exchange
|
||||
MarketPair string `json:"market_pair"`
|
||||
MarketPairBase *MarketPairBase `json:"market_pair_base"`
|
||||
MarketPairQuote *MarketPairQuote `json:"market_pair_quote"`
|
||||
Quote ExchangeQuotes `json:"quote"`
|
||||
ExchangeReported *ExchangeReported `json:"exchange_reported"`
|
||||
}
|
||||
|
||||
// LatestMarketPairs Lists all market pairs across all exchanges for the specified cryptocurrency with associated stats. Use the "convert" option to return market values in multiple fiat and cryptocurrency conversions in the same call.
|
||||
func (s *CryptocurrencyService) LatestMarketPairs(options *MarketPairOptions) (*MarketPairs, error) {
|
||||
var params []string
|
||||
if options == nil {
|
||||
options = new(MarketPairOptions)
|
||||
}
|
||||
|
||||
if options.ID != 0 {
|
||||
params = append(params, fmt.Sprintf("id=%v", options.ID))
|
||||
}
|
||||
|
||||
if options.Symbol != "" {
|
||||
params = append(params, fmt.Sprintf("symbol=%s", options.Symbol))
|
||||
}
|
||||
|
||||
if options.Start != 0 {
|
||||
params = append(params, fmt.Sprintf("start=%v", options.Start))
|
||||
}
|
||||
|
||||
if options.Limit != 0 {
|
||||
params = append(params, fmt.Sprintf("limit=%v", options.Limit))
|
||||
}
|
||||
|
||||
if options.Convert != "" {
|
||||
params = append(params, fmt.Sprintf("convert=%s", options.Convert))
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/cryptocurrency/market-pairs/latest?%s", baseURL, strings.Join(params, "&"))
|
||||
|
||||
body, err := s.client.makeReq(url)
|
||||
resp := new(Response)
|
||||
|
||||
err = json.Unmarshal(body, &resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("JSON Error: [%s]. Response body: [%s]", err.Error(), string(body))
|
||||
}
|
||||
|
||||
data, ok := resp.Data.(interface{})
|
||||
if !ok {
|
||||
return nil, ErrTypeAssertion
|
||||
}
|
||||
|
||||
marketPairs := new(MarketPairs)
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(b, marketPairs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, pair := range marketPairs.MarketPairs {
|
||||
reported, ok := pair.Quote["exchange_reported"]
|
||||
if ok {
|
||||
pair.ExchangeReported = &ExchangeReported{
|
||||
Price: reported.Price,
|
||||
Volume24HBase: reported.Volume24HBase,
|
||||
Volume24HQuote: reported.Volume24HQuote,
|
||||
LastUpdated: reported.LastUpdated,
|
||||
}
|
||||
|
||||
delete(pair.Quote, "exchange_reported")
|
||||
}
|
||||
}
|
||||
|
||||
return marketPairs, nil
|
||||
}
|
||||
|
||||
// HistoricalOHLCV NOT IMPLEMENTED
|
||||
func (s *CryptocurrencyService) HistoricalOHLCV() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LatestQuotes gets latest quote for each specified symbol. Use the "convert" option to return market values in multiple fiat and cryptocurrency conversions in the same call.
|
||||
func (s *CryptocurrencyService) LatestQuotes(options *QuoteOptions) ([]*QuoteLatest, error) {
|
||||
var params []string
|
||||
if options == nil {
|
||||
options = new(QuoteOptions)
|
||||
}
|
||||
|
||||
if options.Symbol != "" {
|
||||
params = append(params, fmt.Sprintf("symbol=%s", options.Symbol))
|
||||
}
|
||||
|
||||
if options.Convert != "" {
|
||||
params = append(params, fmt.Sprintf("convert=%s", options.Convert))
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/cryptocurrency/quotes/latest?%s", baseURL, strings.Join(params, "&"))
|
||||
|
||||
body, err := s.client.makeReq(url)
|
||||
resp := new(Response)
|
||||
err = json.Unmarshal(body, &resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("JSON Error: [%s]. Response body: [%s]", err.Error(), string(body))
|
||||
}
|
||||
|
||||
var quotesLatest []*QuoteLatest
|
||||
ifcs, ok := resp.Data.(interface{})
|
||||
if !ok {
|
||||
return nil, ErrTypeAssertion
|
||||
}
|
||||
|
||||
for _, coinObj := range ifcs.(map[string]interface{}) {
|
||||
quoteLatest := new(QuoteLatest)
|
||||
b, err := json.Marshal(coinObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(b, quoteLatest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
quotesLatest = append(quotesLatest, quoteLatest)
|
||||
}
|
||||
return quotesLatest, nil
|
||||
}
|
||||
|
||||
// HistoricalQuotes NOT IMPLEMENTED
|
||||
func (s *CryptocurrencyService) HistoricalQuotes() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Info NOT IMPLEMENTED
|
||||
func (s *ExchangeService) Info() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Map NOT IMPLEMENTED
|
||||
func (s *ExchangeService) Map() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LatestListings NOT IMPLEMENTED
|
||||
func (s *ExchangeService) LatestListings() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LatestMarketPairs NOT IMPLEMENTED
|
||||
func (s *ExchangeService) LatestMarketPairs() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LatestQuotes NOT IMPLEMENTED
|
||||
func (s *ExchangeService) LatestQuotes() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// HistoricalQuotes NOT IMPLEMENTED
|
||||
func (s *ExchangeService) HistoricalQuotes() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LatestQuotes Get the latest quote of aggregate market metrics. Use the "convert" option to return market values in multiple fiat and cryptocurrency conversions in the same call.
|
||||
func (s *GlobalMetricsService) LatestQuotes(options *QuoteOptions) (*MarketMetrics, error) {
|
||||
var params []string
|
||||
if options == nil {
|
||||
options = new(QuoteOptions)
|
||||
}
|
||||
|
||||
if options.Convert != "" {
|
||||
params = append(params, fmt.Sprintf("convert=%s", options.Convert))
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/global-metrics/quotes/latest?%s", baseURL, strings.Join(params, "&"))
|
||||
|
||||
body, err := s.client.makeReq(url)
|
||||
resp := new(Response)
|
||||
|
||||
err = json.Unmarshal(body, &resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("JSON Error: [%s]. Response body: [%s]", err.Error(), string(body))
|
||||
}
|
||||
|
||||
data, ok := resp.Data.(interface{})
|
||||
if !ok {
|
||||
return nil, ErrTypeAssertion
|
||||
}
|
||||
|
||||
marketMetrics := new(MarketMetrics)
|
||||
b, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(b, marketMetrics)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return marketMetrics, nil
|
||||
}
|
||||
|
||||
// HistoricalQuotes NOT IMPLEMENTED
|
||||
func (s *GlobalMetricsService) HistoricalQuotes() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PriceConversion Convert 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.
|
||||
func (s *ToolsService) PriceConversion(options *ConvertOptions) (*ConvertListing, error) {
|
||||
var params []string
|
||||
if options == nil {
|
||||
options = new(ConvertOptions)
|
||||
}
|
||||
|
||||
if options.Amount != 0 {
|
||||
params = append(params, fmt.Sprintf("amount=%f", options.Amount))
|
||||
}
|
||||
|
||||
if options.ID != "" {
|
||||
params = append(params, fmt.Sprintf("id=%s", options.ID))
|
||||
}
|
||||
|
||||
if options.Symbol != "" {
|
||||
params = append(params, fmt.Sprintf("symbol=%s", options.Symbol))
|
||||
}
|
||||
|
||||
if options.Time != 0 {
|
||||
params = append(params, fmt.Sprintf("time=%d", options.Time))
|
||||
}
|
||||
|
||||
if options.Convert != "" {
|
||||
params = append(params, fmt.Sprintf("convert=%s", options.Convert))
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/tools/price-conversion?%s", baseURL, strings.Join(params, "&"))
|
||||
|
||||
body, err := s.client.makeReq(url)
|
||||
|
||||
resp := new(Response)
|
||||
err = json.Unmarshal(body, &resp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("JSON Error: [%s]. Response body: [%s]", err.Error(), string(body))
|
||||
}
|
||||
|
||||
ifc, ok := resp.Data.(interface{})
|
||||
if !ok {
|
||||
return nil, ErrTypeAssertion
|
||||
}
|
||||
|
||||
listing := new(ConvertListing)
|
||||
b, err := json.Marshal(ifc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(b, listing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return listing, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
SortOptions = sortOptions{
|
||||
Name: "name",
|
||||
Symbol: "symbol",
|
||||
DateAdded: "date_added",
|
||||
MarketCap: "market_cap",
|
||||
Price: "price",
|
||||
CirculatingSupply: "circulating_supply",
|
||||
TotalSupply: "total_supply",
|
||||
MaxSupply: "max_supply",
|
||||
NumMarketPairs: "num_market_pairs",
|
||||
Volume24H: "volume_24h",
|
||||
PercentChange1H: "percent_change_1h",
|
||||
PercentChange24H: "percent_change_24h",
|
||||
PercentChange7D: "percent_change_7d",
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package coinmarketcap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// toInt helper for parsing strings to int
|
||||
func toInt(rawInt string) int {
|
||||
parsed, _ := strconv.Atoi(strings.Replace(strings.Replace(rawInt, "$", "", -1), ",", "", -1))
|
||||
return parsed
|
||||
}
|
||||
|
||||
// toFloat helper for parsing strings to float
|
||||
func toFloat(rawFloat string) float64 {
|
||||
parsed, _ := strconv.ParseFloat(strings.Replace(strings.Replace(strings.Replace(rawFloat, "$", "", -1), ",", "", -1), "%", "", -1), 64)
|
||||
return parsed
|
||||
}
|
||||
|
||||
// doReq HTTP client
|
||||
func doReq(req *http.Request) ([]byte, error) {
|
||||
requestTimeout := time.Duration(5 * time.Second)
|
||||
client := &http.Client{
|
||||
Timeout: requestTimeout,
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if 200 != resp.StatusCode {
|
||||
return nil, fmt.Errorf("%s", body)
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
// makeReq HTTP request helper
|
||||
func (s *Client) makeReq(url string) ([]byte, error) {
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Add("X-CMC_PRO_API_KEY", s.proAPIKey)
|
||||
resp, err := doReq(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, err
|
||||
}
|
56
cointop/common/cmc/cmc.go → vendor/github.com/miguelmota/go-coinmarketcap/v2/v2.go
generated
vendored
56
cointop/common/cmc/cmc.go → vendor/github.com/miguelmota/go-coinmarketcap/v2/v2.go
generated
vendored
Loading…
Reference in New Issue