status-im/status-go

View on GitHub
services/wallet/thirdparty/cryptocompare/client.go

Summary

Maintainability
A
0 mins
Test Coverage
F
8%
package cryptocompare

import (
    "context"
    "encoding/json"
    "fmt"
    "net/url"
    "strings"

    "github.com/status-im/status-go/services/wallet/thirdparty"
    "github.com/status-im/status-go/services/wallet/thirdparty/utils"
)

const baseURL = "https://min-api.cryptocompare.com"
const CryptoCompareStatusProxyURL = "https://cryptocompare.test.api.status.im"
const extraParamStatus = "Status.im"

type HistoricalPricesContainer struct {
    Aggregated     bool                         `json:"Aggregated"`
    TimeFrom       int64                        `json:"TimeFrom"`
    TimeTo         int64                        `json:"TimeTo"`
    HistoricalData []thirdparty.HistoricalPrice `json:"Data"`
}

type HistoricalPricesData struct {
    Data HistoricalPricesContainer `json:"Data"`
}

type TokenDetailsContainer struct {
    Data map[string]thirdparty.TokenDetails `json:"Data"`
}

type MarketValuesContainer struct {
    Raw map[string]map[string]thirdparty.TokenMarketValues `json:"Raw"`
}

type Client struct {
    httpClient *thirdparty.HTTPClient
    baseURL    string
}

func NewClient() *Client {
    return &Client{
        httpClient: thirdparty.NewHTTPClient(),
        baseURL:    baseURL,
    }
}

func NewClientWithURL(url string) *Client {
    return &Client{
        httpClient: thirdparty.NewHTTPClient(),
        baseURL:    url,
    }
}

func (c *Client) FetchPrices(symbols []string, currencies []string) (map[string]map[string]float64, error) {
    chunks := utils.ChunkSymbols(symbols, 60)
    result := make(map[string]map[string]float64)
    realCurrencies := utils.RenameSymbols(currencies)
    for _, smbls := range chunks {
        realSymbols := utils.RenameSymbols(smbls)

        params := url.Values{}
        params.Add("fsyms", strings.Join(realSymbols, ","))
        params.Add("tsyms", strings.Join(realCurrencies, ","))
        params.Add("extraParams", extraParamStatus)

        url := fmt.Sprintf("%s/data/pricemulti", c.baseURL)
        response, err := c.httpClient.DoGetRequest(context.Background(), url, params)
        if err != nil {
            return nil, err
        }

        prices := make(map[string]map[string]float64)
        err = json.Unmarshal(response, &prices)
        if err != nil {
            return nil, fmt.Errorf("%s - %s", err, string(response))
        }

        for _, symbol := range smbls {
            result[symbol] = map[string]float64{}
            for _, currency := range currencies {
                result[symbol][currency] = prices[utils.GetRealSymbol(symbol)][utils.GetRealSymbol(currency)]
            }
        }
    }
    return result, nil
}

func (c *Client) FetchTokenDetails(symbols []string) (map[string]thirdparty.TokenDetails, error) {
    url := fmt.Sprintf("%s/data/all/coinlist", c.baseURL)
    response, err := c.httpClient.DoGetRequest(context.Background(), url, nil)
    if err != nil {
        return nil, err
    }

    container := TokenDetailsContainer{}
    err = json.Unmarshal(response, &container)
    if err != nil {
        return nil, err
    }

    tokenDetails := make(map[string]thirdparty.TokenDetails)

    for _, symbol := range symbols {
        tokenDetails[symbol] = container.Data[utils.GetRealSymbol(symbol)]
    }

    return tokenDetails, nil
}

func (c *Client) FetchTokenMarketValues(symbols []string, currency string) (map[string]thirdparty.TokenMarketValues, error) {
    chunks := utils.ChunkSymbols(symbols)
    realCurrency := utils.GetRealSymbol(currency)
    item := map[string]thirdparty.TokenMarketValues{}
    for _, smbls := range chunks {
        realSymbols := utils.RenameSymbols(smbls)

        params := url.Values{}
        params.Add("fsyms", strings.Join(realSymbols, ","))
        params.Add("tsyms", realCurrency)
        params.Add("extraParams", extraParamStatus)

        url := fmt.Sprintf("%s/data/pricemultifull", c.baseURL)
        response, err := c.httpClient.DoGetRequest(context.Background(), url, params)
        if err != nil {
            return nil, err
        }

        container := MarketValuesContainer{}
        err = json.Unmarshal(response, &container)

        if len(container.Raw) == 0 {
            return nil, fmt.Errorf("no data found - %s", string(response))
        }
        if err != nil {
            return nil, fmt.Errorf("%s - %s", err, string(response))
        }

        for _, symbol := range smbls {
            item[symbol] = container.Raw[utils.GetRealSymbol(symbol)][realCurrency]
        }
    }
    return item, nil
}

func (c *Client) FetchHistoricalHourlyPrices(symbol string, currency string, limit int, aggregate int) ([]thirdparty.HistoricalPrice, error) {
    item := []thirdparty.HistoricalPrice{}

    params := url.Values{}
    params.Add("fsym", utils.GetRealSymbol(symbol))
    params.Add("tsym", currency)
    params.Add("aggregate", fmt.Sprintf("%d", aggregate))
    params.Add("limit", fmt.Sprintf("%d", limit))
    params.Add("extraParams", extraParamStatus)

    url := fmt.Sprintf("%s/data/v2/histohour", c.baseURL)
    response, err := c.httpClient.DoGetRequest(context.Background(), url, params)
    if err != nil {
        return item, err
    }

    container := HistoricalPricesData{}
    err = json.Unmarshal(response, &container)
    if err != nil {
        return item, err
    }

    item = container.Data.HistoricalData

    return item, nil
}

func (c *Client) FetchHistoricalDailyPrices(symbol string, currency string, limit int, allData bool, aggregate int) ([]thirdparty.HistoricalPrice, error) {
    item := []thirdparty.HistoricalPrice{}

    params := url.Values{}
    params.Add("fsym", utils.GetRealSymbol(symbol))
    params.Add("tsym", currency)
    params.Add("aggregate", fmt.Sprintf("%d", aggregate))
    params.Add("limit", fmt.Sprintf("%d", limit))
    params.Add("allData", fmt.Sprintf("%v", allData))
    params.Add("extraParams", extraParamStatus)

    url := fmt.Sprintf("%s/data/v2/histoday", c.baseURL)
    response, err := c.httpClient.DoGetRequest(context.Background(), url, params)
    if err != nil {
        return item, err
    }

    container := HistoricalPricesData{}
    err = json.Unmarshal(response, &container)
    if err != nil {
        return item, err
    }

    item = container.Data.HistoricalData

    return item, nil
}

func (c *Client) ID() string {
    return "cryptocompare"
}