github.com/status-im/status-go@v1.1.0/services/wallet/thirdparty/coingecko/client_test.go (about) 1 package coingecko 2 3 import ( 4 "encoding/json" 5 "net/http" 6 "net/http/httptest" 7 "reflect" 8 "testing" 9 10 "github.com/stretchr/testify/require" 11 12 "github.com/status-im/status-go/services/wallet/thirdparty" 13 ) 14 15 type TestTokenPlatform struct { 16 Ethereum string `json:"ethereum"` 17 Arb string `json:"arb"` 18 } 19 20 type TestGeckoToken struct { 21 ID string `json:"id"` 22 Symbol string `json:"symbol"` 23 Name string `json:"name"` 24 Platforms TestTokenPlatform `json:"platforms"` 25 } 26 27 func setupTest(t *testing.T, response []byte) (*httptest.Server, func()) { 28 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 29 w.WriteHeader(200) 30 _, err := w.Write(response) 31 if err != nil { 32 return 33 } 34 })) 35 36 return srv, func() { 37 srv.Close() 38 } 39 } 40 41 func TestGetTokensSuccess(t *testing.T) { 42 expected := []GeckoToken{ 43 { 44 ID: "ethereum", 45 Symbol: "eth", 46 Name: "Ethereum", 47 }, 48 { 49 ID: "status", 50 Symbol: "snt", 51 Name: "Status", 52 }, 53 } 54 55 expectedMap := map[string][]GeckoToken{ 56 "ETH": {{ 57 ID: "ethereum", 58 Symbol: "eth", 59 Name: "Ethereum", 60 }}, 61 "SNT": {{ 62 ID: "status", 63 Symbol: "snt", 64 Name: "Status", 65 }}, 66 } 67 response, _ := json.Marshal(expected) 68 69 srv, stop := setupTest(t, response) 70 defer stop() 71 72 geckoClient := &Client{ 73 httpClient: thirdparty.NewHTTPClient(), 74 tokens: make(map[string][]GeckoToken), 75 baseURL: srv.URL, 76 } 77 78 tokenMap, err := geckoClient.getTokens() 79 require.NoError(t, err) 80 require.True(t, reflect.DeepEqual(expectedMap, tokenMap)) 81 } 82 83 func TestGetTokensEthPlatform(t *testing.T) { 84 tokenList := []TestGeckoToken{ 85 { 86 ID: "ethereum", 87 Symbol: "eth-test", 88 Name: "Ethereum", 89 Platforms: TestTokenPlatform{ 90 Ethereum: "0x123", 91 }, 92 }, 93 { 94 ID: "usdt-bridge-test", 95 Symbol: "usdt-test", 96 Name: "USDT Bridge Test", 97 Platforms: TestTokenPlatform{ 98 Arb: "0x123", 99 }, 100 }, 101 { 102 ID: "tether", 103 Symbol: "usdt-test", 104 Name: "Tether", 105 Platforms: TestTokenPlatform{ 106 Arb: "0x1234", 107 Ethereum: "0x12345", 108 }, 109 }, 110 { 111 ID: "AirDao", 112 Symbol: "amb-test", 113 Name: "Amber", 114 Platforms: TestTokenPlatform{ 115 Arb: "0x123455", 116 }, 117 }, 118 } 119 120 expectedMap := map[string][]GeckoToken{ 121 "ETH-TEST": {{ 122 ID: "ethereum", 123 Symbol: "eth-test", 124 Name: "Ethereum", 125 EthPlatform: true, 126 }}, 127 "USDT-TEST": { 128 { 129 ID: "usdt-bridge-test", 130 Symbol: "usdt-test", 131 Name: "USDT Bridge Test", 132 EthPlatform: false, 133 }, 134 { 135 ID: "tether", 136 Symbol: "usdt-test", 137 Name: "Tether", 138 EthPlatform: true, 139 }, 140 }, 141 "AMB-TEST": {{ 142 ID: "AirDao", 143 Symbol: "amb-test", 144 Name: "Amber", 145 EthPlatform: false, 146 }}, 147 } 148 149 response, _ := json.Marshal(tokenList) 150 151 srv, stop := setupTest(t, response) 152 defer stop() 153 154 geckoClient := &Client{ 155 httpClient: thirdparty.NewHTTPClient(), 156 tokens: make(map[string][]GeckoToken), 157 baseURL: srv.URL, 158 } 159 160 tokenMap, err := geckoClient.getTokens() 161 require.NoError(t, err) 162 require.True(t, reflect.DeepEqual(expectedMap, tokenMap)) 163 } 164 165 func TestGetTokensFailure(t *testing.T) { 166 resp := []byte{} 167 srv, stop := setupTest(t, resp) 168 defer stop() 169 170 geckoClient := &Client{ 171 httpClient: thirdparty.NewHTTPClient(), 172 tokens: make(map[string][]GeckoToken), 173 baseURL: srv.URL, 174 } 175 176 _, err := geckoClient.getTokens() 177 require.Error(t, err) 178 } 179 180 func TestFetchPrices(t *testing.T) { 181 mux := http.NewServeMux() 182 183 // Register handlers for different URL paths 184 mux.HandleFunc("/coins/list", func(w http.ResponseWriter, r *http.Request) { 185 w.WriteHeader(http.StatusOK) 186 w.Header().Set("Content-Type", "application/json") 187 response := "[{\"id\":\"ethereum\",\"symbol\":\"eth\",\"name\":\"Ethereum\",\"platforms\":{\"ethereum\":\"0x5e21d1ee5cf0077b314c381720273ae82378d613\"}},{\"id\":\"status\",\"symbol\":\"snt\",\"name\":\"Status\",\"platforms\":{\"ethereum\":\"0x78ba134c3ace18e69837b01703d07f0db6fb0a60\"}}]" 188 _, _ = w.Write([]byte(response)) 189 }) 190 191 mux.HandleFunc("/simple/price", func(w http.ResponseWriter, r *http.Request) { 192 w.WriteHeader(http.StatusOK) 193 w.Header().Set("Content-Type", "application/json") 194 response := "{\"ethereum\":{\"usd\":3181.32},\"status\":{\"usd\":0.02391704}}" 195 _, _ = w.Write([]byte(response)) 196 }) 197 198 srv := httptest.NewServer(mux) 199 200 geckoClient := &Client{ 201 httpClient: thirdparty.NewHTTPClient(), 202 tokens: make(map[string][]GeckoToken), 203 baseURL: srv.URL, 204 } 205 206 symbols := []string{"ETH", "SNT", "UNSUPPORTED", "TOKENS"} 207 prices, err := geckoClient.FetchPrices(symbols, []string{"USD"}) 208 require.NoError(t, err) 209 require.Len(t, prices, 2) 210 } 211 212 func TestFetchMarketValues(t *testing.T) { 213 mux := http.NewServeMux() 214 215 // Register handlers for different URL paths 216 mux.HandleFunc("/coins/list", func(w http.ResponseWriter, r *http.Request) { 217 w.WriteHeader(http.StatusOK) 218 w.Header().Set("Content-Type", "application/json") 219 response := "[{\"id\":\"ethereum\",\"symbol\":\"eth\",\"name\":\"Ethereum\",\"platforms\":{\"ethereum\":\"0x5e21d1ee5cf0077b314c381720273ae82378d613\"}},{\"id\":\"status\",\"symbol\":\"snt\",\"name\":\"Status\",\"platforms\":{\"ethereum\":\"0x78ba134c3ace18e69837b01703d07f0db6fb0a60\"}}]" 220 _, _ = w.Write([]byte(response)) 221 }) 222 223 mux.HandleFunc("/coins/markets", func(w http.ResponseWriter, r *http.Request) { 224 w.WriteHeader(http.StatusOK) 225 w.Header().Set("Content-Type", "application/json") 226 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}]" 227 _, _ = w.Write([]byte(response)) 228 }) 229 230 srv := httptest.NewServer(mux) 231 232 geckoClient := &Client{ 233 httpClient: thirdparty.NewHTTPClient(), 234 tokens: make(map[string][]GeckoToken), 235 baseURL: srv.URL, 236 } 237 238 symbols := []string{"ETH", "SNT", "UNSUPPORTED", "TOKENS"} 239 prices, err := geckoClient.FetchTokenMarketValues(symbols, "USD") 240 require.NoError(t, err) 241 require.Len(t, prices, 2) 242 }