fix(wallet)_: fixed error with parsing coingecko response. (#5650)
For tokens that it does not support and some that were listed in mapping we responded with error Co-authored-by: Ivan Belyakov <ivan.belyakov.job@gmail.com>
This commit is contained in:
parent
7e87fd0d05
commit
ca25be4516
|
@ -8,6 +8,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"golang.org/x/exp/maps"
|
||||||
|
|
||||||
"github.com/status-im/status-go/services/wallet/thirdparty"
|
"github.com/status-im/status-go/services/wallet/thirdparty"
|
||||||
"github.com/status-im/status-go/services/wallet/thirdparty/utils"
|
"github.com/status-im/status-go/services/wallet/thirdparty/utils"
|
||||||
)
|
)
|
||||||
|
@ -18,10 +20,8 @@ var coinGeckoMapping = map[string]string{
|
||||||
"ETH": "ethereum",
|
"ETH": "ethereum",
|
||||||
"AST": "airswap",
|
"AST": "airswap",
|
||||||
"ABT": "arcblock",
|
"ABT": "arcblock",
|
||||||
"ATM": "",
|
|
||||||
"BNB": "binancecoin",
|
"BNB": "binancecoin",
|
||||||
"BLT": "bloom",
|
"BLT": "bloom",
|
||||||
"CDT": "",
|
|
||||||
"COMP": "compound-coin",
|
"COMP": "compound-coin",
|
||||||
"EDG": "edgeless",
|
"EDG": "edgeless",
|
||||||
"ENG": "enigma",
|
"ENG": "enigma",
|
||||||
|
@ -47,7 +47,6 @@ var coinGeckoMapping = map[string]string{
|
||||||
"UNI": "uniswap",
|
"UNI": "uniswap",
|
||||||
"USDC": "usd-coin",
|
"USDC": "usd-coin",
|
||||||
"USDP": "paxos-standard",
|
"USDP": "paxos-standard",
|
||||||
"VRS": "",
|
|
||||||
"USDT": "tether",
|
"USDT": "tether",
|
||||||
"SHIB": "shiba-inu",
|
"SHIB": "shiba-inu",
|
||||||
"LINK": "chainlink",
|
"LINK": "chainlink",
|
||||||
|
@ -184,23 +183,21 @@ func (c *Client) getTokens() (map[string][]GeckoToken, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mapTokensToSymbols(tokens, c.tokens)
|
mapTokensToSymbols(tokens, c.tokens)
|
||||||
|
|
||||||
return c.tokens, nil
|
return c.tokens, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) mapSymbolsToIds(symbols []string) ([]string, error) {
|
func (c *Client) mapSymbolsToIds(symbols []string) (map[string]string, error) {
|
||||||
tokens, err := c.getTokens()
|
tokens, err := c.getTokens()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ids := make([]string, 0)
|
ids := make(map[string]string, 0)
|
||||||
for _, symbol := range utils.RenameSymbols(symbols) {
|
for _, symbol := range symbols {
|
||||||
id, err := getIDFromSymbol(tokens, symbol)
|
id, err := getIDFromSymbol(tokens, utils.GetRealSymbol(symbol))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ids = append(ids, id)
|
ids[symbol] = id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ids = utils.RemoveDuplicates(ids)
|
|
||||||
|
|
||||||
return ids, nil
|
return ids, nil
|
||||||
}
|
}
|
||||||
|
@ -212,7 +209,7 @@ func (c *Client) FetchPrices(symbols []string, currencies []string) (map[string]
|
||||||
}
|
}
|
||||||
|
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
params.Add("ids", strings.Join(ids, ","))
|
params.Add("ids", strings.Join(maps.Values(ids), ","))
|
||||||
params.Add("vs_currencies", strings.Join(currencies, ","))
|
params.Add("vs_currencies", strings.Join(currencies, ","))
|
||||||
|
|
||||||
url := fmt.Sprintf("%ssimple/price", baseURL)
|
url := fmt.Sprintf("%ssimple/price", baseURL)
|
||||||
|
@ -227,17 +224,9 @@ func (c *Client) FetchPrices(symbols []string, currencies []string) (map[string]
|
||||||
return nil, fmt.Errorf("%s - %s", err, string(response))
|
return nil, fmt.Errorf("%s - %s", err, string(response))
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens, err := c.getTokens()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
result := make(map[string]map[string]float64)
|
result := make(map[string]map[string]float64)
|
||||||
for _, symbol := range symbols {
|
for symbol, id := range ids {
|
||||||
result[symbol] = map[string]float64{}
|
result[symbol] = map[string]float64{}
|
||||||
id, err := getIDFromSymbol(tokens, utils.GetRealSymbol(symbol))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, currency := range currencies {
|
for _, currency := range currencies {
|
||||||
result[symbol][currency] = prices[id][strings.ToLower(currency)]
|
result[symbol][currency] = prices[id][strings.ToLower(currency)]
|
||||||
}
|
}
|
||||||
|
@ -272,7 +261,7 @@ func (c *Client) FetchTokenMarketValues(symbols []string, currency string) (map[
|
||||||
}
|
}
|
||||||
|
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
params.Add("ids", strings.Join(ids, ","))
|
params.Add("ids", strings.Join(maps.Values(ids), ","))
|
||||||
params.Add("vs_currency", currency)
|
params.Add("vs_currency", currency)
|
||||||
params.Add("order", "market_cap_desc")
|
params.Add("order", "market_cap_desc")
|
||||||
params.Add("per_page", "250")
|
params.Add("per_page", "250")
|
||||||
|
@ -292,17 +281,8 @@ func (c *Client) FetchTokenMarketValues(symbols []string, currency string) (map[
|
||||||
return nil, fmt.Errorf("%s - %s", err, string(response))
|
return nil, fmt.Errorf("%s - %s", err, string(response))
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens, err := c.getTokens()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := make(map[string]thirdparty.TokenMarketValues)
|
result := make(map[string]thirdparty.TokenMarketValues)
|
||||||
for _, symbol := range symbols {
|
for symbol, id := range ids {
|
||||||
id, err := getIDFromSymbol(tokens, utils.GetRealSymbol(symbol))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, marketValue := range marketValues {
|
for _, marketValue := range marketValues {
|
||||||
if id != marketValue.ID {
|
if id != marketValue.ID {
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -7,9 +7,9 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/status-im/status-go/services/wallet/thirdparty"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/services/wallet/thirdparty"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TestTokenPlatform struct {
|
type TestTokenPlatform struct {
|
||||||
|
@ -53,12 +53,12 @@ func TestGetTokensSuccess(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedMap := map[string][]GeckoToken{
|
expectedMap := map[string][]GeckoToken{
|
||||||
"ETH": []GeckoToken{{
|
"ETH": {{
|
||||||
ID: "ethereum",
|
ID: "ethereum",
|
||||||
Symbol: "eth",
|
Symbol: "eth",
|
||||||
Name: "Ethereum",
|
Name: "Ethereum",
|
||||||
}},
|
}},
|
||||||
"SNT": []GeckoToken{{
|
"SNT": {{
|
||||||
ID: "status",
|
ID: "status",
|
||||||
Symbol: "snt",
|
Symbol: "snt",
|
||||||
Name: "Status",
|
Name: "Status",
|
||||||
|
@ -176,3 +176,67 @@ func TestGetTokensFailure(t *testing.T) {
|
||||||
_, err := geckoClient.getTokens()
|
_, err := geckoClient.getTokens()
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFetchPrices(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
|
||||||
|
// Register handlers for different URL paths
|
||||||
|
mux.HandleFunc("/coins/list", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
response := "[{\"id\":\"ethereum\",\"symbol\":\"eth\",\"name\":\"Ethereum\",\"platforms\":{\"ethereum\":\"0x5e21d1ee5cf0077b314c381720273ae82378d613\"}},{\"id\":\"status\",\"symbol\":\"snt\",\"name\":\"Status\",\"platforms\":{\"ethereum\":\"0x78ba134c3ace18e69837b01703d07f0db6fb0a60\"}}]"
|
||||||
|
_, _ = w.Write([]byte(response))
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.HandleFunc("/simple/price", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
response := "{\"ethereum\":{\"usd\":3181.32},\"status\":{\"usd\":0.02391704}}"
|
||||||
|
_, _ = w.Write([]byte(response))
|
||||||
|
})
|
||||||
|
|
||||||
|
srv := httptest.NewServer(mux)
|
||||||
|
|
||||||
|
geckoClient := &Client{
|
||||||
|
httpClient: thirdparty.NewHTTPClient(),
|
||||||
|
tokens: make(map[string][]GeckoToken),
|
||||||
|
tokensURL: srv.URL + "/coins/list",
|
||||||
|
}
|
||||||
|
|
||||||
|
symbols := []string{"ETH", "SNT", "UNSUPPORTED", "TOKENS"}
|
||||||
|
prices, err := geckoClient.FetchPrices(symbols, []string{"USD"})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, prices, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFetchMarketValues(t *testing.T) {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
|
||||||
|
// Register handlers for different URL paths
|
||||||
|
mux.HandleFunc("/coins/list", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
response := "[{\"id\":\"ethereum\",\"symbol\":\"eth\",\"name\":\"Ethereum\",\"platforms\":{\"ethereum\":\"0x5e21d1ee5cf0077b314c381720273ae82378d613\"}},{\"id\":\"status\",\"symbol\":\"snt\",\"name\":\"Status\",\"platforms\":{\"ethereum\":\"0x78ba134c3ace18e69837b01703d07f0db6fb0a60\"}}]"
|
||||||
|
_, _ = w.Write([]byte(response))
|
||||||
|
})
|
||||||
|
|
||||||
|
mux.HandleFunc("/coins/markets", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
response := "[{\"id\":\"ethereum\",\"symbol\":\"eth\",\"name\":\"Ethereum\",\"image\":\"https://coin-images.coingecko.com/coins/images/279/large/ethereum.png?1696501628\",\"current_price\":3177.16,\"market_cap\":382035912506,\"market_cap_rank\":2,\"fully_diluted_valuation\":382035912506,\"total_volume\":18958367285,\"high_24h\":3325.57,\"low_24h\":3139.38,\"price_change_24h\":-146.70781392198978,\"price_change_percentage_24h\":-4.41377,\"market_cap_change_24h\":-17315836985.42914,\"market_cap_change_percentage_24h\":-4.33599,\"circulating_supply\":120251313.934882,\"total_supply\":120251313.934882,\"max_supply\":null,\"ath\":4878.26,\"ath_change_percentage\":-34.74074,\"ath_date\":\"2021-11-10T14:24:19.604Z\",\"atl\":0.432979,\"atl_change_percentage\":735159.10684,\"atl_date\":\"2015-10-20T00:00:00.000Z\",\"roi\":{\"times\":64.75457822761112,\"currency\":\"btc\",\"percentage\":6475.457822761112},\"last_updated\":\"2024-08-01T14:17:02.604Z\",\"price_change_percentage_1h_in_currency\":-0.14302683386053758,\"price_change_percentage_24h_in_currency\":-4.413773698570276},{\"id\":\"status\",\"symbol\":\"snt\",\"name\":\"Status\",\"image\":\"https://coin-images.coingecko.com/coins/images/779/large/status.png?1696501931\",\"current_price\":0.02387956,\"market_cap\":94492012,\"market_cap_rank\":420,\"fully_diluted_valuation\":162355386,\"total_volume\":3315607,\"high_24h\":0.02528227,\"low_24h\":0.02351923,\"price_change_24h\":-0.001177587387552543,\"price_change_percentage_24h\":-4.69961,\"market_cap_change_24h\":-5410268.579258412,\"market_cap_change_percentage_24h\":-5.41556,\"circulating_supply\":3960483788.3096976,\"total_supply\":6804870174.0,\"max_supply\":null,\"ath\":0.684918,\"ath_change_percentage\":-96.50467,\"ath_date\":\"2018-01-03T00:00:00.000Z\",\"atl\":0.00592935,\"atl_change_percentage\":303.75704,\"atl_date\":\"2020-03-13T02:10:36.877Z\",\"roi\":null,\"last_updated\":\"2024-08-01T14:16:20.805Z\",\"price_change_percentage_1h_in_currency\":-0.21239208982552796,\"price_change_percentage_24h_in_currency\":-4.699606730698922}]"
|
||||||
|
_, _ = w.Write([]byte(response))
|
||||||
|
})
|
||||||
|
|
||||||
|
srv := httptest.NewServer(mux)
|
||||||
|
|
||||||
|
geckoClient := &Client{
|
||||||
|
httpClient: thirdparty.NewHTTPClient(),
|
||||||
|
tokens: make(map[string][]GeckoToken),
|
||||||
|
tokensURL: srv.URL + "/coins/list",
|
||||||
|
}
|
||||||
|
|
||||||
|
symbols := []string{"ETH", "SNT", "UNSUPPORTED", "TOKENS"}
|
||||||
|
prices, err := geckoClient.FetchTokenMarketValues(symbols, "USD")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, prices, 2)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue