github.com/status-im/status-go@v1.1.0/services/wallet/thirdparty/cryptocompare/client.go (about) 1 package cryptocompare 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "net/url" 8 "strings" 9 10 "github.com/status-im/status-go/services/wallet/thirdparty" 11 "github.com/status-im/status-go/services/wallet/thirdparty/utils" 12 ) 13 14 const baseID = "cryptocompare" 15 const extraParamStatus = "Status.im" 16 const baseURL = "https://min-api.cryptocompare.com" 17 18 type HistoricalPricesContainer struct { 19 Aggregated bool `json:"Aggregated"` 20 TimeFrom int64 `json:"TimeFrom"` 21 TimeTo int64 `json:"TimeTo"` 22 HistoricalData []thirdparty.HistoricalPrice `json:"Data"` 23 } 24 25 type HistoricalPricesData struct { 26 Data HistoricalPricesContainer `json:"Data"` 27 } 28 29 type TokenDetailsContainer struct { 30 Data map[string]thirdparty.TokenDetails `json:"Data"` 31 } 32 33 type MarketValuesContainer struct { 34 Raw map[string]map[string]thirdparty.TokenMarketValues `json:"Raw"` 35 } 36 37 type Params struct { 38 ID string 39 URL string 40 User string 41 Password string 42 } 43 44 type Client struct { 45 id string 46 httpClient *thirdparty.HTTPClient 47 baseURL string 48 creds *thirdparty.BasicCreds 49 } 50 51 func NewClient() *Client { 52 return NewClientWithParams(Params{ 53 ID: baseID, 54 URL: baseURL, 55 }) 56 } 57 58 func NewClientWithParams(params Params) *Client { 59 var creds *thirdparty.BasicCreds 60 if params.User != "" { 61 creds = &thirdparty.BasicCreds{ 62 User: params.User, 63 Password: params.Password, 64 } 65 } 66 67 return &Client{ 68 id: params.ID, 69 httpClient: thirdparty.NewHTTPClient(), 70 baseURL: params.URL, 71 creds: creds, 72 } 73 } 74 75 func (c *Client) FetchPrices(symbols []string, currencies []string) (map[string]map[string]float64, error) { 76 chunks := utils.ChunkSymbols(symbols, 60) 77 result := make(map[string]map[string]float64) 78 realCurrencies := utils.RenameSymbols(currencies) 79 for _, smbls := range chunks { 80 realSymbols := utils.RenameSymbols(smbls) 81 82 params := url.Values{} 83 params.Add("fsyms", strings.Join(realSymbols, ",")) 84 params.Add("tsyms", strings.Join(realCurrencies, ",")) 85 params.Add("extraParams", extraParamStatus) 86 87 url := fmt.Sprintf("%s/data/pricemulti", c.baseURL) 88 response, err := c.httpClient.DoGetRequest(context.Background(), url, params, c.creds) 89 if err != nil { 90 return nil, err 91 } 92 93 prices := make(map[string]map[string]float64) 94 err = json.Unmarshal(response, &prices) 95 if err != nil { 96 return nil, fmt.Errorf("%s - %s", err, string(response)) 97 } 98 99 for _, symbol := range smbls { 100 result[symbol] = map[string]float64{} 101 for _, currency := range currencies { 102 result[symbol][currency] = prices[utils.GetRealSymbol(symbol)][utils.GetRealSymbol(currency)] 103 } 104 } 105 } 106 return result, nil 107 } 108 109 func (c *Client) FetchTokenDetails(symbols []string) (map[string]thirdparty.TokenDetails, error) { 110 url := fmt.Sprintf("%s/data/all/coinlist", c.baseURL) 111 response, err := c.httpClient.DoGetRequest(context.Background(), url, nil, c.creds) 112 if err != nil { 113 return nil, err 114 } 115 116 container := TokenDetailsContainer{} 117 err = json.Unmarshal(response, &container) 118 if err != nil { 119 return nil, err 120 } 121 122 tokenDetails := make(map[string]thirdparty.TokenDetails) 123 124 for _, symbol := range symbols { 125 tokenDetails[symbol] = container.Data[utils.GetRealSymbol(symbol)] 126 } 127 128 return tokenDetails, nil 129 } 130 131 func (c *Client) FetchTokenMarketValues(symbols []string, currency string) (map[string]thirdparty.TokenMarketValues, error) { 132 chunks := utils.ChunkSymbols(symbols) 133 realCurrency := utils.GetRealSymbol(currency) 134 item := map[string]thirdparty.TokenMarketValues{} 135 for _, smbls := range chunks { 136 realSymbols := utils.RenameSymbols(smbls) 137 138 params := url.Values{} 139 params.Add("fsyms", strings.Join(realSymbols, ",")) 140 params.Add("tsyms", realCurrency) 141 params.Add("extraParams", extraParamStatus) 142 143 url := fmt.Sprintf("%s/data/pricemultifull", c.baseURL) 144 response, err := c.httpClient.DoGetRequest(context.Background(), url, params, c.creds) 145 if err != nil { 146 return nil, err 147 } 148 149 container := MarketValuesContainer{} 150 err = json.Unmarshal(response, &container) 151 152 if len(container.Raw) == 0 { 153 return nil, fmt.Errorf("no data found - %s", string(response)) 154 } 155 if err != nil { 156 return nil, fmt.Errorf("%s - %s", err, string(response)) 157 } 158 159 for _, symbol := range smbls { 160 item[symbol] = container.Raw[utils.GetRealSymbol(symbol)][realCurrency] 161 } 162 } 163 return item, nil 164 } 165 166 func (c *Client) FetchHistoricalHourlyPrices(symbol string, currency string, limit int, aggregate int) ([]thirdparty.HistoricalPrice, error) { 167 item := []thirdparty.HistoricalPrice{} 168 169 params := url.Values{} 170 params.Add("fsym", utils.GetRealSymbol(symbol)) 171 params.Add("tsym", currency) 172 params.Add("aggregate", fmt.Sprintf("%d", aggregate)) 173 params.Add("limit", fmt.Sprintf("%d", limit)) 174 params.Add("extraParams", extraParamStatus) 175 176 url := fmt.Sprintf("%s/data/v2/histohour", c.baseURL) 177 response, err := c.httpClient.DoGetRequest(context.Background(), url, params, c.creds) 178 if err != nil { 179 return item, err 180 } 181 182 container := HistoricalPricesData{} 183 err = json.Unmarshal(response, &container) 184 if err != nil { 185 return item, err 186 } 187 188 item = container.Data.HistoricalData 189 190 return item, nil 191 } 192 193 func (c *Client) FetchHistoricalDailyPrices(symbol string, currency string, limit int, allData bool, aggregate int) ([]thirdparty.HistoricalPrice, error) { 194 item := []thirdparty.HistoricalPrice{} 195 196 params := url.Values{} 197 params.Add("fsym", utils.GetRealSymbol(symbol)) 198 params.Add("tsym", currency) 199 params.Add("aggregate", fmt.Sprintf("%d", aggregate)) 200 params.Add("limit", fmt.Sprintf("%d", limit)) 201 params.Add("allData", fmt.Sprintf("%v", allData)) 202 params.Add("extraParams", extraParamStatus) 203 204 url := fmt.Sprintf("%s/data/v2/histoday", c.baseURL) 205 response, err := c.httpClient.DoGetRequest(context.Background(), url, params, c.creds) 206 if err != nil { 207 return item, err 208 } 209 210 container := HistoricalPricesData{} 211 err = json.Unmarshal(response, &container) 212 if err != nil { 213 return item, err 214 } 215 216 item = container.Data.HistoricalData 217 218 return item, nil 219 } 220 221 func (c *Client) ID() string { 222 return c.id 223 }