You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cointop/pkg/api/vendors/coingecko/v3/v3.go

388 lines
9.8 KiB
Go

// Package coingecko is forked from https://github.com/superoo7/go-gecko
package coingecko
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"github.com/miguelmota/cointop/pkg/api/vendors/coingecko/format"
"github.com/miguelmota/cointop/pkg/api/vendors/coingecko/v3/types"
)
var baseURL = "https://api.coingecko.com/api/v3"
// Client struct
type Client struct {
httpClient *http.Client
}
// NewClient create new client object
func NewClient(httpClient *http.Client) *Client {
if httpClient == nil {
httpClient = http.DefaultClient
}
return &Client{httpClient: httpClient}
}
// helper
// doReq HTTP client
func doReq(req *http.Request, client *http.Client) ([]byte, error) {
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 (c *Client) MakeReq(url string) ([]byte, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
resp, err := doReq(req, c.httpClient)
if err != nil {
return nil, err
}
return resp, err
}
// API
// Ping /ping endpoint
func (c *Client) Ping() (*types.Ping, error) {
url := fmt.Sprintf("%s/ping", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
var data *types.Ping
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return data, nil
}
// SimpleSinglePrice /simple/price Single ID and Currency (ids, vsCurrency)
func (c *Client) SimpleSinglePrice(id string, vsCurrency string) (*types.SimpleSinglePrice, error) {
idParam := []string{strings.ToLower(id)}
vcParam := []string{strings.ToLower(vsCurrency)}
t, err := c.SimplePrice(idParam, vcParam)
if err != nil {
return nil, err
}
curr := (*t)[id]
data := &types.SimpleSinglePrice{ID: id, Currency: vsCurrency, MarketPrice: curr[vsCurrency]}
return data, nil
}
// SimplePrice /simple/price Multiple ID and Currency (ids, vs_currencies)
func (c *Client) SimplePrice(ids []string, vsCurrencies []string) (*map[string]map[string]float32, error) {
params := url.Values{}
idsParam := strings.Join(ids[:], ",")
vsCurrenciesParam := strings.Join(vsCurrencies[:], ",")
params.Add("ids", idsParam)
params.Add("vs_currencies", vsCurrenciesParam)
url := fmt.Sprintf("%s/simple/price?%s", baseURL, params.Encode())
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
t := make(map[string]map[string]float32)
err = json.Unmarshal(resp, &t)
if err != nil {
return nil, err
}
return &t, nil
}
// SimpleSupportedVSCurrencies /simple/supported_vs_currencies
func (c *Client) SimpleSupportedVSCurrencies() (*types.SimpleSupportedVSCurrencies, error) {
url := fmt.Sprintf("%s/simple/supported_vs_currencies", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
var data *types.SimpleSupportedVSCurrencies
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return data, nil
}
// CoinsList /coins/list
func (c *Client) CoinsList() (*types.CoinList, error) {
url := fmt.Sprintf("%s/coins/list", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
var data *types.CoinList
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return data, nil
}
// CoinsMarket /coins/market
func (c *Client) CoinsMarket(vsCurrency string, ids []string, order string, perPage int, page int, sparkline bool, priceChangePercentage []string) (*types.CoinsMarket, error) {
if len(vsCurrency) == 0 {
return nil, fmt.Errorf("vsCurrency is required")
}
params := url.Values{}
// vsCurrency
params.Add("vs_currency", vsCurrency)
// order
if len(order) == 0 {
order = types.OrderTypeObject.MarketCapDesc
}
params.Add("order", order)
// ids
if len(ids) != 0 {
idsParam := strings.Join(ids[:], ",")
params.Add("ids", idsParam)
}
// per_page
if perPage <= 0 || perPage > 250 {
perPage = 100
}
params.Add("per_page", format.Int2String(perPage))
params.Add("page", format.Int2String(page))
// sparkline
params.Add("sparkline", format.Bool2String(sparkline))
// price_change_percentage
if len(priceChangePercentage) != 0 {
priceChangePercentageParam := strings.Join(priceChangePercentage[:], ",")
params.Add("price_change_percentage", priceChangePercentageParam)
}
url := fmt.Sprintf("%s/coins/markets?%s", baseURL, params.Encode())
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
var data *types.CoinsMarket
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return data, nil
}
// CoinsID /coins/{id}
func (c *Client) CoinsID(id string, localization bool, tickers bool, marketData bool, communityData bool, developerData bool, sparkline bool) (*types.CoinsID, error) {
if len(id) == 0 {
return nil, fmt.Errorf("id is required")
}
params := url.Values{}
params.Add("localization", format.Bool2String(sparkline))
params.Add("tickers", format.Bool2String(tickers))
params.Add("market_data", format.Bool2String(marketData))
params.Add("community_data", format.Bool2String(communityData))
params.Add("developer_data", format.Bool2String(developerData))
params.Add("sparkline", format.Bool2String(sparkline))
url := fmt.Sprintf("%s/coins/%s?%s", baseURL, id, params.Encode())
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
var data *types.CoinsID
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return data, nil
}
// CoinsIDTickers /coins/{id}/tickers
func (c *Client) CoinsIDTickers(id string, page int) (*types.CoinsIDTickers, error) {
if len(id) == 0 {
return nil, fmt.Errorf("id is required")
}
params := url.Values{}
if page > 0 {
params.Add("page", format.Int2String(page))
}
url := fmt.Sprintf("%s/coins/%s/tickers?%s", baseURL, id, params.Encode())
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
var data *types.CoinsIDTickers
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return data, nil
}
// CoinsIDHistory /coins/{id}/history?date={date}&localization=false
func (c *Client) CoinsIDHistory(id string, date string, localization bool) (*types.CoinsIDHistory, error) {
if len(id) == 0 || len(date) == 0 {
return nil, fmt.Errorf("id and date is required")
}
params := url.Values{}
params.Add("date", date)
params.Add("localization", format.Bool2String(localization))
url := fmt.Sprintf("%s/coins/%s/history?%s", baseURL, id, params.Encode())
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
var data *types.CoinsIDHistory
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return data, nil
}
// CoinsIDMarketChart /coins/{id}/market_chart?vsCurrency={usd, eur, jpy, etc.}&days={1,14,30,max}
func (c *Client) CoinsIDMarketChart(id string, vsCurrency string, days string) (*types.CoinsIDMarketChart, error) {
if len(id) == 0 || len(vsCurrency) == 0 || len(days) == 0 {
return nil, fmt.Errorf("id, vsCurrency, and days is required")
}
params := url.Values{}
params.Add("vs_currency", vsCurrency)
params.Add("days", days)
url := fmt.Sprintf("%s/coins/%s/market_chart?%s", baseURL, id, params.Encode())
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
m := types.CoinsIDMarketChart{}
err = json.Unmarshal(resp, &m)
if err != nil {
return &m, err
}
return &m, nil
}
// CoinsIDStatusUpdates
// CoinsIDContractAddress https://api.coingecko.com/api/v3/coins/{id}/contract/{contract_address}
// func CoinsIDContractAddress(id string, address string) (nil, error) {
// url := fmt.Sprintf("%s/coins/%s/contract/%s", baseURL, id, address)
// resp, err := request.MakeReq(url)
// if err != nil {
// return nil, err
// }
// }
// EventsCountries https://api.coingecko.com/api/v3/events/countries
func (c *Client) EventsCountries() ([]types.EventCountryItem, error) {
url := fmt.Sprintf("%s/events/countries", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
var data *types.EventsCountries
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return data.Data, nil
}
// EventsTypes https://api.coingecko.com/api/v3/events/types
func (c *Client) EventsTypes() (*types.EventsTypes, error) {
url := fmt.Sprintf("%s/events/types", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
var data *types.EventsTypes
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return data, nil
}
// ExchangeRates https://api.coingecko.com/api/v3/exchange_rates
func (c *Client) ExchangeRates() (*types.ExchangeRatesItem, error) {
url := fmt.Sprintf("%s/exchange_rates", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
var data *types.ExchangeRatesResponse
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return &data.Rates, nil
}
// Global https://api.coingecko.com/api/v3/global
func (c *Client) Global() (*types.Global, error) {
url := fmt.Sprintf("%s/global", baseURL)
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
var data *types.GlobalResponse
err = json.Unmarshal(resp, &data)
if err != nil {
return nil, err
}
return &data.Data, nil
}
// GlobalCharts https://www.coingecko.com/market_cap/total_charts_data?duration=7&locale=en&vs_currency=usd
func (c *Client) GlobalCharts(vsCurrency string, days string) (*types.GlobalCharts, error) {
if len(vsCurrency) == 0 || len(days) == 0 {
return nil, fmt.Errorf("vsCurrency, and days is required")
}
params := url.Values{}
params.Add("locale", "en")
params.Add("vs_currency", vsCurrency)
params.Add("duration", days)
url := fmt.Sprintf("https://www.coingecko.com/market_cap/total_charts_data?%s", params.Encode())
resp, err := c.MakeReq(url)
if err != nil {
return nil, err
}
m := types.GlobalCharts{}
err = json.Unmarshal(resp, &m)
if err != nil {
return &m, err
}
return &m, nil
}