diff --git a/internal/logutils/callog/status_request_log.go b/internal/logutils/callog/status_request_log.go index 75fbc15a6e4..e7a3d88f770 100644 --- a/internal/logutils/callog/status_request_log.go +++ b/internal/logutils/callog/status_request_log.go @@ -38,8 +38,6 @@ var sensitiveKeys = []string{ "alchemyApiKey", "AlchemyApiKey", "openSeaApiKey", - "statusProxyMarketUser", - "statusProxyMarketPassword", "marketDataProxyUser", "marketDataProxyPassword", "statusProxyBlockchainUser", diff --git a/params/config.go b/params/config.go index c7ee3e63aae..2ee503aca6a 100644 --- a/params/config.go +++ b/params/config.go @@ -221,21 +221,18 @@ type NodeConfig struct { // WalletConfig extra configuration for wallet.Service. type WalletConfig struct { - Enabled bool - RaribleMainnetAPIKey security.SensitiveString `json:"RaribleMainnetAPIKey"` - RaribleTestnetAPIKey security.SensitiveString `json:"RaribleTestnetAPIKey"` - AlchemyAPIKey security.SensitiveString `json:"AlchemyAPIKey"` - InfuraAPIKey security.SensitiveString `json:"InfuraAPIKey"` - InfuraAPIKeySecret security.SensitiveString `json:"InfuraAPIKeySecret"` - StatusProxyMarketUser security.SensitiveString `json:"StatusProxyMarketUser"` - StatusProxyMarketPassword security.SensitiveString `json:"StatusProxyMarketPassword"` - CoingeckoAPIKey security.SensitiveString `json:"CoingeckoAPIKey"` - CoingeckoDemoAPIKey security.SensitiveString `json:"CoingeckoDemoAPIKey"` - MarketDataProxyConfig MarketDataProxyConfig `json:"MarketDataProxyConfig"` - NftProxyConfig NftProxyConfig `json:"NftProxyConfig"` - - StatusProxyUser security.SensitiveString `json:"StatusProxyBlockchainUser"` - StatusProxyPassword security.SensitiveString `json:"StatusProxyBlockchainPassword"` + Enabled bool + RaribleMainnetAPIKey security.SensitiveString `json:"RaribleMainnetAPIKey"` + RaribleTestnetAPIKey security.SensitiveString `json:"RaribleTestnetAPIKey"` + AlchemyAPIKey security.SensitiveString `json:"AlchemyAPIKey"` + InfuraAPIKey security.SensitiveString `json:"InfuraAPIKey"` + InfuraAPIKeySecret security.SensitiveString `json:"InfuraAPIKeySecret"` + CoingeckoAPIKey security.SensitiveString `json:"CoingeckoAPIKey"` + CoingeckoDemoAPIKey security.SensitiveString `json:"CoingeckoDemoAPIKey"` + MarketDataProxyConfig MarketDataProxyConfig `json:"MarketDataProxyConfig"` + NftProxyConfig NftProxyConfig `json:"NftProxyConfig"` + StatusProxyUser security.SensitiveString `json:"StatusProxyBlockchainUser"` + StatusProxyPassword security.SensitiveString `json:"StatusProxyBlockchainPassword"` StatusProxyStageName string `json:"StatusProxyStageName"` EnableMercuryoProvider bool `json:"EnableMercuryoProvider"` diff --git a/pkg/backend/defaults.go b/pkg/backend/defaults.go index f71f8e487b4..85b99e97cf9 100644 --- a/pkg/backend/defaults.go +++ b/pkg/backend/defaults.go @@ -185,12 +185,6 @@ func buildWalletConfig(walletRequest *requests.WalletConfig, request *requests.W walletConfig.AlchemyAPIKey = request.AlchemyAPIKey } - if !request.StatusProxyMarketUser.Empty() { - walletConfig.StatusProxyMarketUser = request.StatusProxyMarketUser - } - if !request.StatusProxyMarketPassword.Empty() { - walletConfig.StatusProxyMarketPassword = request.StatusProxyMarketPassword - } if !request.MarketDataProxyUser.Empty() { walletConfig.MarketDataProxyConfig.User = request.MarketDataProxyUser } @@ -224,7 +218,6 @@ func buildWalletConfig(walletRequest *requests.WalletConfig, request *requests.W if len(walletRequest.CustomTokens) > 0 { walletConfig.CustomTokens = walletRequest.CustomTokens } - if !request.StatusProxyUser.Empty() { walletConfig.StatusProxyUser = request.StatusProxyUser } diff --git a/pkg/backend/node/status_node_services.go b/pkg/backend/node/status_node_services.go index 060093995bb..0d54762ff95 100644 --- a/pkg/backend/node/status_node_services.go +++ b/pkg/backend/node/status_node_services.go @@ -92,7 +92,7 @@ func (b *StatusNode) initServices(config *params.NodeConfig, mediaServer *server // Wallet Service is used by wakuExtSrvc/wakuV2ExtSrvc // Keep this initialization before the other two if config.WalletConfig.Enabled { - err := b.createWalletService(accDB, b.appDB, b.accountsPublisher, &b.walletFeed, config.WalletConfig.StatusProxyStageName) + err := b.createWalletService(accDB, b.appDB, b.accountsPublisher, &b.walletFeed) if err != nil { return err } @@ -322,7 +322,7 @@ func (b *StatusNode) SetWalletCommunityInfoProvider(provider thirdparty.Communit } } -func (b *StatusNode) createWalletService(accountsDB *accounts.Database, appDB *sql.DB, accountsPublisher *pubsub.Publisher, walletFeed *event.Feed, statusProxyStageName string) (err error) { +func (b *StatusNode) createWalletService(accountsDB *accounts.Database, appDB *sql.DB, accountsPublisher *pubsub.Publisher, walletFeed *event.Feed) (err error) { if b.walletSrvc == nil { b.walletSrvc, err = wallet.NewService( b.walletDB, accountsDB, appDB, b.rpcClient, accountsPublisher, b.gethAccountsManager, b.transactor, b.config, @@ -331,7 +331,6 @@ func (b *StatusNode) createWalletService(accountsDB *accounts.Database, appDB *s walletFeed, b.mediaServer, b.tokenManager, - statusProxyStageName, ) } return diff --git a/protocol/requests/create_account.go b/protocol/requests/create_account.go index 4ea5c77d445..00c8b37e2b3 100644 --- a/protocol/requests/create_account.go +++ b/protocol/requests/create_account.go @@ -111,9 +111,7 @@ type WalletSecretsConfig struct { RaribleTestnetAPIKey security.SensitiveString `json:"raribleTestnetApiKey"` AlchemyAPIKey security.SensitiveString `json:"alchemyApiKey"` - StatusProxyStageName string `json:"statusProxyStageName"` - StatusProxyMarketUser security.SensitiveString `json:"statusProxyMarketUser"` - StatusProxyMarketPassword security.SensitiveString `json:"statusProxyMarketPassword"` + StatusProxyStageName string `json:"statusProxyStageName"` MarketDataProxyUrl security.SensitiveString `json:"marketDataProxyUrl"` MarketDataProxyUser security.SensitiveString `json:"marketDataProxyUser"` @@ -121,7 +119,6 @@ type WalletSecretsConfig struct { CoingeckoAPIKey security.SensitiveString `json:"coingeckoApiKey"` CoingeckoDemoAPIKey security.SensitiveString `json:"coingeckoDemoApiKey"` - StatusProxyUser security.SensitiveString `json:"statusProxyBlockchainUser"` StatusProxyPassword security.SensitiveString `json:"statusProxyBlockchainPassword"` diff --git a/services/wallet/api_impl_test.go b/services/wallet/api_impl_test.go index 5a8d16043e8..73febd317d9 100644 --- a/services/wallet/api_impl_test.go +++ b/services/wallet/api_impl_test.go @@ -90,7 +90,7 @@ func TestAPI_GetAddressDetails(t *testing.T) { tokenManager, err := token.NewTokenManager(db, c, nil, mockNetworkManager, appDB, nil, nil, nil, accountsDb, 0, 0) require.NoError(t, err) - service, err := NewService(db, accountsDb, appDB, c, accountsPublisher, nil, nil, ¶ms.NodeConfig{}, nil, nil, nil, nil, tokenManager, "") + service, err := NewService(db, accountsDb, appDB, c, accountsPublisher, nil, nil, ¶ms.NodeConfig{}, nil, nil, nil, nil, tokenManager) require.NoError(t, err) tokenbalancesFetcher := mock_tokenbalances.NewMockFetcherIface(mockCtrl) diff --git a/services/wallet/keycard_pairings_test.go b/services/wallet/keycard_pairings_test.go index 5426c8f0a81..5e095ae82eb 100644 --- a/services/wallet/keycard_pairings_test.go +++ b/services/wallet/keycard_pairings_test.go @@ -33,7 +33,7 @@ func TestKeycardPairingsFile(t *testing.T) { }) require.NoError(t, err) - service, err := NewService(db, accountsDb, appDB, rpcClient, accountsPublisher, nil, nil, ¶ms.NodeConfig{}, nil, nil, nil, nil, nil, "") + service, err := NewService(db, accountsDb, appDB, rpcClient, accountsPublisher, nil, nil, ¶ms.NodeConfig{}, nil, nil, nil, nil, nil) require.NoError(t, err) data, err := service.KeycardPairings().GetPairingsJSONFileContent() diff --git a/services/wallet/service.go b/services/wallet/service.go index 5bb07daac9a..2d1d484294e 100644 --- a/services/wallet/service.go +++ b/services/wallet/service.go @@ -5,7 +5,6 @@ import ( "database/sql" "encoding/json" "errors" - "fmt" "net/http" "sync" "time" @@ -21,7 +20,6 @@ import ( "github.com/status-im/status-go/services/wallet/common" "github.com/status-im/status-go/services/wallet/multistandardbalance" "github.com/status-im/status-go/services/wallet/pendingtxtracker" - "github.com/status-im/status-go/services/wallet/thirdparty/market/cryptocompare" "github.com/status-im/status-go/services/wallet/tokenbalances" "github.com/status-im/status-go/services/wallet/transferdetector" @@ -131,7 +129,6 @@ func NewService( feed *event.Feed, mediaServer *server.MediaServer, tokenManager *token.Manager, - statusProxyStageName string, ) (*Service, error) { signals := &walletevent.SignalsTransmitter{ Publisher: feed, @@ -159,20 +156,13 @@ func NewService( onramp.NewMoonPayProvider(), } - cryptoCompare := cryptocompare.NewClient() coingeckoClient := coingecko.NewClientWithParams(coingecko.Params{ CoingeckoAPIKey: config.WalletConfig.CoingeckoAPIKey, CoingeckoDemoAPIKey: config.WalletConfig.CoingeckoDemoAPIKey, }) coingeckoProxy := createCoingeckoProxyClient(config.WalletConfig.MarketDataProxyConfig) - cryptoCompareProxy := cryptocompare.NewClientWithParams(cryptocompare.Params{ - ID: fmt.Sprintf("%s-proxy", cryptoCompare.ID()), - URL: fmt.Sprintf("https://%s.api.status.im/cryptocompare/", statusProxyStageName), - User: config.WalletConfig.StatusProxyMarketUser, - Password: config.WalletConfig.StatusProxyMarketPassword, - }) marketProviders = []thirdparty.MarketDataProvider{ - coingeckoProxy, coingeckoClient, cryptoCompare, cryptoCompareProxy, + coingeckoProxy, coingeckoClient, } raribleClient := rarible.NewClient(config.WalletConfig.RaribleMainnetAPIKey, config.WalletConfig.RaribleTestnetAPIKey) diff --git a/services/wallet/thirdparty/market/cryptocompare/client.go b/services/wallet/thirdparty/market/cryptocompare/client.go deleted file mode 100644 index 7f2d0b0be72..00000000000 --- a/services/wallet/thirdparty/market/cryptocompare/client.go +++ /dev/null @@ -1,313 +0,0 @@ -package cryptocompare - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "strings" - "time" - - "golang.org/x/exp/maps" - - "github.com/status-im/status-go/pkg/security" - "github.com/status-im/status-go/services/wallet/thirdparty" - "github.com/status-im/status-go/services/wallet/thirdparty/utils" - tokentypes "github.com/status-im/status-go/services/wallet/token/types" -) - -const baseID = "cryptocompare" -const extraParamStatus = "Status.im" -const baseURL = "https://min-api.cryptocompare.com" - -// 300 is the max length for fsyms, but we need to subtract the length of the ETH symbol cause we want to add ETH to every chunk -// to suppress the error from the API for unknown symbols -const maxFsymsLength = 300 - len("ETH") - -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 Params struct { - ID string - URL string - User security.SensitiveString - Password security.SensitiveString -} - -type Client struct { - id string - httpClient *thirdparty.HTTPClient - baseURL string - creds *thirdparty.BasicCreds -} - -func NewClient() *Client { - return NewClientWithParams(Params{ - ID: baseID, - URL: baseURL, - }) -} - -func NewClientWithParams(params Params) *Client { - var creds *thirdparty.BasicCreds - if !params.User.Empty() { - creds = &thirdparty.BasicCreds{ - User: params.User, - Password: params.Password, - } - } - - // Configure HTTP client with detailed timeouts - httpClient := thirdparty.NewHTTPClient( - thirdparty.WithDetailedTimeouts( - 5*time.Second, // dialTimeout - 5*time.Second, // tlsHandshakeTimeout - 5*time.Second, // responseHeaderTimeout - 20*time.Second, // requestTimeout - ), - thirdparty.WithMaxRetries(5), - ) - - // Ensure baseURL doesn't end with a slash - baseURL := strings.TrimSuffix(params.URL, "/") - - return &Client{ - id: params.ID, - httpClient: httpClient, - baseURL: baseURL, - creds: creds, - } -} - -// buildURL creates a URL by joining the base URL with the given path -// ensuring there are no double slashes -func (c *Client) buildURL(path string) string { - baseURL := strings.TrimRight(c.baseURL, "/") - trimmedPath := strings.TrimLeft(path, "/") - - return baseURL + "/" + trimmedPath -} - -func (c *Client) mapTokensToSymbols(tokens []*tokentypes.Token) (map[string][]string, error) { - symbolsToTokenKeysMap := make(map[string][]string) - for _, token := range tokens { - symbol := strings.ToUpper(token.Symbol) - symbolsToTokenKeysMap[symbol] = append(symbolsToTokenKeysMap[symbol], token.Key()) - } - return symbolsToTokenKeysMap, nil -} - -// FetchPrices fetches the prices for the given tokens and currencies -// returns a map[tokenKey]map[currency]price -func (c *Client) FetchPrices(tokens []*tokentypes.Token, currencies []string) (map[string]map[string]float64, error) { - symbolsToTokenKeysMap, err := c.mapTokensToSymbols(tokens) - if err != nil { - return nil, err - } - - chunkSymbolParams := utils.ChunkSymbolsParams{ - MaxCharsPerChunk: maxFsymsLength, - ExtraCharsPerSymbol: 1, // joined with a comma - } - chunks, err := utils.ChunkSymbols(maps.Keys(symbolsToTokenKeysMap), chunkSymbolParams) - if err != nil { - return nil, err - } - 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("relaxedValidation", "true") - params.Add("extraParams", extraParamStatus) - - url := c.buildURL("data/pricemulti") - - response, err := c.httpClient.DoGetRequestWithCredentials(context.Background(), url, params, c.creds) - 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 { - for _, tokenKey := range symbolsToTokenKeysMap[symbol] { - result[tokenKey] = map[string]float64{} - for _, currency := range currencies { - result[tokenKey][currency] = prices[utils.GetRealSymbol(symbol)][utils.GetRealSymbol(currency)] - } - } - } - } - return result, nil -} - -// FetchTokenDetails fetches the token details for the given tokens -// returns a map[tokenKey]TokenDetails -func (c *Client) FetchTokenDetails(tokens []*tokentypes.Token) (map[string]thirdparty.TokenDetails, error) { - symbolsToTokenKeysMap, err := c.mapTokensToSymbols(tokens) - if err != nil { - return nil, err - } - - url := c.buildURL("data/all/coinlist") - response, err := c.httpClient.DoGetRequestWithCredentials(context.Background(), url, nil, c.creds) - 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, tokenKeys := range symbolsToTokenKeysMap { - for _, tokenKey := range tokenKeys { - tokenDetails[tokenKey] = container.Data[utils.GetRealSymbol(symbol)] - } - } - - return tokenDetails, nil -} - -// FetchTokenMarketValues fetches the market values for the given tokens and currency -// returns a map[tokenKey]TokenMarketValues -func (c *Client) FetchTokenMarketValues(tokens []*tokentypes.Token, currency string) (map[string]thirdparty.TokenMarketValues, error) { - symbolsToTokenKeysMap, err := c.mapTokensToSymbols(tokens) - if err != nil { - return nil, err - } - - chunkSymbolParams := utils.ChunkSymbolsParams{ - MaxCharsPerChunk: maxFsymsLength, - ExtraCharsPerSymbol: 1, // joined with a comma - } - chunks, err := utils.ChunkSymbols(maps.Keys(symbolsToTokenKeysMap), chunkSymbolParams) - if err != nil { - return nil, err - } - realCurrency := utils.GetRealSymbol(currency) - item := map[string]thirdparty.TokenMarketValues{} - for _, smbls := range chunks { - smbls = append(smbls, "ETH") - realSymbols := utils.RenameSymbols(smbls) - - params := url.Values{} - params.Add("fsyms", strings.Join(realSymbols, ",")) - params.Add("tsyms", realCurrency) - params.Add("relaxedValidation", "true") - params.Add("extraParams", extraParamStatus) - - url := c.buildURL("data/pricemultifull") - response, err := c.httpClient.DoGetRequestWithCredentials(context.Background(), url, params, c.creds) - 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 { - for _, tokenKey := range symbolsToTokenKeysMap[symbol] { - item[tokenKey] = container.Raw[utils.GetRealSymbol(symbol)][realCurrency] - } - } - } - return item, nil -} - -// FetchHistoricalHourlyPrices fetches the hourly prices for the given token and currency -// returns a list of HistoricalPrice -func (c *Client) FetchHistoricalHourlyPrices(token *tokentypes.Token, currency string, limit int, aggregate int) ([]thirdparty.HistoricalPrice, error) { - item := []thirdparty.HistoricalPrice{} - - params := url.Values{} - params.Add("fsym", utils.GetRealSymbol(token.Symbol)) - params.Add("tsym", currency) - params.Add("aggregate", fmt.Sprintf("%d", aggregate)) - params.Add("limit", fmt.Sprintf("%d", limit)) - params.Add("extraParams", extraParamStatus) - - url := c.buildURL("data/v2/histohour") - response, err := c.httpClient.DoGetRequestWithCredentials(context.Background(), url, params, c.creds) - 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 -} - -// FetchHistoricalDailyPrices fetches the daily prices for the given token and currency -// returns a list of HistoricalPrice -func (c *Client) FetchHistoricalDailyPrices(token *tokentypes.Token, currency string, limit int, allData bool, aggregate int) ([]thirdparty.HistoricalPrice, error) { - item := []thirdparty.HistoricalPrice{} - - params := url.Values{} - params.Add("fsym", utils.GetRealSymbol(token.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 := c.buildURL("data/v2/histoday") - response, err := c.httpClient.DoGetRequestWithCredentials(context.Background(), url, params, c.creds) - 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 c.id -} diff --git a/services/wallet/thirdparty/market/cryptocompare/client_test.go b/services/wallet/thirdparty/market/cryptocompare/client_test.go deleted file mode 100644 index 297685b635c..00000000000 --- a/services/wallet/thirdparty/market/cryptocompare/client_test.go +++ /dev/null @@ -1,396 +0,0 @@ -package cryptocompare - -import ( - "net/http" - "net/http/httptest" - "strings" - "testing" - - "github.com/stretchr/testify/require" - - gethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/status-im/go-wallet-sdk/pkg/tokens/types" - - "github.com/status-im/status-go/services/wallet/common" - "github.com/status-im/status-go/services/wallet/thirdparty" - tokentypes "github.com/status-im/status-go/services/wallet/token/types" -) - -func TestIDs(t *testing.T) { - stdClient := NewClient() - require.Equal(t, baseID, stdClient.ID()) - - clientWithParams := NewClientWithParams(Params{ - ID: "testID", - }) - require.Equal(t, "testID", clientWithParams.ID()) -} - -func TestBuildURL(t *testing.T) { - tests := []struct { - name string - baseURL string - path string - expected string - }{ - { - name: "base URL without trailing slash, path without leading slash", - baseURL: "https://example.com", - path: "api/v1/endpoint", - expected: "https://example.com/api/v1/endpoint", - }, - { - name: "base URL with trailing slash, path without leading slash", - baseURL: "https://example.com/", - path: "api/v1/endpoint", - expected: "https://example.com/api/v1/endpoint", - }, - { - name: "base URL without trailing slash, path with leading slash", - baseURL: "https://example.com", - path: "/api/v1/endpoint", - expected: "https://example.com/api/v1/endpoint", - }, - { - name: "base URL with trailing slash, path with leading slash", - baseURL: "https://example.com/", - path: "/api/v1/endpoint", - expected: "https://example.com/api/v1/endpoint", - }, - { - name: "base URL with multiple trailing slashes", - baseURL: "https://example.com///", - path: "api/v1/endpoint", - expected: "https://example.com/api/v1/endpoint", - }, - { - name: "path with multiple leading slashes", - baseURL: "https://example.com", - path: "///api/v1/endpoint", - expected: "https://example.com/api/v1/endpoint", - }, - { - name: "empty path", - baseURL: "https://example.com", - path: "", - expected: "https://example.com/", - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - // Simulate the NewClientWithParams behavior which trims trailing slashes - baseURL := strings.TrimSuffix(tc.baseURL, "/") - client := &Client{baseURL: baseURL} - - result := client.buildURL(tc.path) - require.Equal(t, tc.expected, result) - }) - } -} - -var testTokens = []*tokentypes.Token{ - { - Token: &types.Token{ - Name: "USDC", - Symbol: "USDC", - ChainID: common.EthereumMainnet, - Address: gethcommon.HexToAddress("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"), - }, - }, - { - Token: &types.Token{ - Name: "USDC", - Symbol: "USDC", - ChainID: common.OptimismMainnet, - Address: gethcommon.HexToAddress("0x0b2c639c533813f4aa9d7837caf62653d097ff85"), - }, - }, - { - Token: &types.Token{ - Name: "Status", - Symbol: "SNT", - ChainID: common.EthereumMainnet, - Address: gethcommon.HexToAddress("0x744d70fdbe2ba4cf95131626614a1763df805b9e"), - }, - }, - { - Token: &types.Token{ - Name: "Dai", - Symbol: "DAI", - ChainID: common.EthereumMainnet, - Address: gethcommon.HexToAddress("0x6b175474e89094c44da98b954eedeac495271d0f"), - }, - }, - { - Token: &types.Token{ - Name: "Ethereum", - Symbol: "ETH", - ChainID: common.EthereumMainnet, - Address: gethcommon.HexToAddress("0x0000000000000000000000000000000000000000"), - }, - }, - { - Token: &types.Token{ - Name: "Ethereum", - Symbol: "ETH", - ChainID: common.OptimismMainnet, - Address: gethcommon.HexToAddress("0x0000000000000000000000000000000000000000"), - }, - }, -} - -func TestFetchPrices(t *testing.T) { - mux := http.NewServeMux() - - mux.HandleFunc("/data/pricemulti", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - response := `{"USDC":{"USD":0.9999},"SNT":{"USD":0.02605},"ETH":{"USD":4528.86}}` - _, _ = w.Write([]byte(response)) - }) - - srv := httptest.NewServer(mux) - - geckoClient := &Client{ - httpClient: thirdparty.NewHTTPClient(), - baseURL: srv.URL, - } - - prices, err := geckoClient.FetchPrices(testTokens, []string{"USD"}) - require.NoError(t, err) - require.NotNil(t, prices) - require.Len(t, prices, len(testTokens)) - - require.Equal(t, map[string]float64{"USD": 0.9999}, prices[testTokens[0].Key()]) - require.Equal(t, map[string]float64{"USD": 0.9999}, prices[testTokens[1].Key()]) - require.Equal(t, map[string]float64{"USD": 0.02605}, prices[testTokens[2].Key()]) - require.Equal(t, map[string]float64{"USD": 0}, prices[testTokens[3].Key()]) - require.Equal(t, map[string]float64{"USD": 4528.86}, prices[testTokens[4].Key()]) - require.Equal(t, map[string]float64{"USD": 4528.86}, prices[testTokens[5].Key()]) -} - -func TestFetchTokenDetails(t *testing.T) { - mux := http.NewServeMux() - - mux.HandleFunc("/data/all/coinlist", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - response := `{ -"Response": "Success", -"Message": "Coin list successfully returned!", - "Data": { - "USDC": { - "Id": "925809", - "Url": "/coins/usdc/overview", - "ImageUrl": "/media/34835941/usdc.png", - "ContentCreatedOn": 1538573358, - "Name": "USDC", - "Symbol": "USDC", - "CoinName": "USD Coin", - "FullName": "USD Coin (USDC)", - "Description": "Who Created USDC?The cryptocurrency is an open-source project that anyone can view and contribute to and is managed by the Centre consortium, which was co-founded by fintech firm Circle and Nasdaq-listed cryptocurrency exchange Coinbase.Accounting firm Grant Thornton oversees the segregated accounts with regulated U.S. financial institutions that hold the cryptocurrency’s reserves, held in dollars and dollar-denominated assets. In USDC’s case, these dollar-denominated assets are short-term U.S. Treasury securities.How Does USDC Remain at $1!?Because USDC is a fully collateralized stablecoin backed by dollar-denominated assets and allows token holders to redeem USDC tokens for dollars, it can almost be seen as a digital version of the U.S. dollar.Investors can initiate a transaction to buy USDC using fiat currency, with the fiat currency they send over being deposited at a U.S. financial institution while USDC tokens in the same nominal value are minted. If the USDC is redeemed for the fiat currency, the tokens are burned and the dollars are transferred to investors’ bank accounts, according to USDC’s whitepaper. What is USDC Used For?USDC is a widely used stablecoin being adopted throughout the cryptocurrency market as it competes with the leading stablecoin USDT. Some of the cryptocurrency’s use cases include:Hedging against volatilityStable price-peggingRemittancesCrowdfundingPayments for products and servicesLending, borrowing, and other financial servicesBecause USDC is a blockchain-based digital currency, it doesn’t require a bank account, users don’t need to be in a specific location or have an account with a specific institution to use it. Moreover, it isn’t restricted by banking hours or borders.The cryptocurrency is available on a number of blockchains, including Ethereum, Algorand, BNB Chain, Polygon Avalanche, Cronos, Solana, Stellar, and TRON. It’s widely used in the decentralized finance (DeFi) space.GitHub | Medium", - "AssetTokenStatus": "N/A", - "Algorithm": "N/A", - "ProofType": "N/A", - "SortOrder": "3382", - "Sponsored": false, - "Taxonomy": { - "Access": "Permissioned", - "FCA": "Exchange,Asset", - "FINMA": "Payment,Asset", - "Industry": "Financial and Insurance Activities", - "CollateralizedAsset": "Yes", - "CollateralizedAssetType": "Stablecoin", - "CollateralType": "Currency", - "CollateralInfo": "" - }, - "Rating": { - "Weiss": { - "Rating": "", - "TechnologyAdoptionRating": "", - "MarketPerformanceRating": "" - } - }, - "IsTrading": true - }, - "SNT": { - "Id": "137013", - "Url": "/coins/snt/overview", - "ImageUrl": "/media/37747590/snt.png", - "ContentCreatedOn": 1497962382, - "Name": "SNT", - "Symbol": "SNT", - "CoinName": "Status Network Token", - "FullName": "Status Network Token (SNT)", - "Description": "Status is an open source messaging platform and mobile browser that allows users to interact with decentralized applications (dApps) that run on the Ethereum Network.In Status, users own and control their own data, wealth and digital identity. The Status Network Token ('SNT') is an Ethereum-based token that is required to interact with the Status Network.Status strives to be a secure communication tool that upholds human rights. Designed to enable the free flow of information, protect the right to private, secure conversations, and promote the sovereignty of individuals.Discord | YouTube | Instagram | Facebook | WeiboWhitepaper", - "AssetTokenStatus": "Finished", - "Algorithm": "N/A", - "ProofType": "N/A", - "SortOrder": "1264", - "Sponsored": false, - "Taxonomy": { - "Access": "Permissionless", - "FCA": "Utility", - "FINMA": "Utility", - "Industry": "Arts, Entertainment and Recreation", - "CollateralizedAsset": "No", - "CollateralizedAssetType": "", - "CollateralType": "", - "CollateralInfo": "" - }, - "Rating": { - "Weiss": { - "Rating": "C", - "TechnologyAdoptionRating": "C", - "MarketPerformanceRating": "D-" - } - }, - "IsTrading": true - } - } -}` - _, _ = w.Write([]byte(response)) - }) - - srv := httptest.NewServer(mux) - - geckoClient := &Client{ - httpClient: thirdparty.NewHTTPClient(), - baseURL: srv.URL, - } - - details, err := geckoClient.FetchTokenDetails(testTokens) - require.NoError(t, err) - require.NotNil(t, details) - require.Len(t, details, len(testTokens)) - - received := details[testTokens[0].Key()] - require.Equal(t, "925809", received.ID) - require.Equal(t, "USDC", received.Name) - require.Equal(t, "USDC", received.Symbol) - require.Equal(t, float64(0), received.TotalCoinsMined) - - received = details[testTokens[1].Key()] - require.Equal(t, "925809", received.ID) - require.Equal(t, "USDC", received.Name) - require.Equal(t, "USDC", received.Symbol) - require.Equal(t, float64(0), received.TotalCoinsMined) - - received = details[testTokens[2].Key()] - require.Equal(t, "137013", received.ID) - require.Equal(t, "SNT", received.Name) - require.Equal(t, "SNT", received.Symbol) - require.Equal(t, float64(0), received.TotalCoinsMined) - - received = details[testTokens[3].Key()] - require.Equal(t, thirdparty.TokenDetails{}, received) - received = details[testTokens[4].Key()] - require.Equal(t, thirdparty.TokenDetails{}, received) - received = details[testTokens[5].Key()] - require.Equal(t, thirdparty.TokenDetails{}, received) -} - -func TestFetchTokenMarketValues(t *testing.T) { - mux := http.NewServeMux() - - mux.HandleFunc("/data/pricemultifull", func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - response := `{ - "RAW": { - "ETH": { - "USD": { - "TYPE": "5", - "MARKET": "CCCAGG", - "FROMSYMBOL": "ETH", - "TOSYMBOL": "USD", - "FLAGS": "2", - "LASTMARKET": "CCCAGG", - "MEDIAN": 4516.14416425753, - "TOPTIERVOLUME24HOUR": 410168.95285623, - "TOPTIERVOLUME24HOURTO": 1825127962.69741, - "LASTTRADEID": "754495303", - "PRICE": 4516.14416425753, - "LASTUPDATE": 1757667157, - "LASTVOLUME": 0.07697372, - "LASTVOLUMETO": 347.605622148, - "VOLUMEHOUR": 6657.95654658, - "VOLUMEHOURTO": 30120608.7948991, - "OPENHOUR": 4527.26272975992, - "HIGHHOUR": 4534.8406102931, - "LOWHOUR": 4514.93155765281, - "VOLUMEDAY": 109541.21454776, - "VOLUMEDAYTO": 494825176.02217, - "OPENDAY": 4461.10754887017, - "HIGHDAY": 4564.28612417753, - "LOWDAY": 4452.72268362409, - "VOLUME24HOUR": 410168.95285623, - "VOLUME24HOURTO": 1825127962.69741, - "OPEN24HOUR": 4432.7608628562, - "HIGH24HOUR": 4564.28612417753, - "LOW24HOUR": 4373.18427790377, - "CHANGE24HOUR": 83.38330140132985, - "CHANGEPCT24HOUR": 1.8810692473855388, - "CHANGEDAY": 55.03661538736014, - "CHANGEPCTDAY": 1.2336984657834318, - "CHANGEHOUR": -11.118565502390084, - "CHANGEPCTHOUR": -0.24559134660558343, - "CONVERSIONTYPE": "direct", - "CONVERSIONSYMBOL": "", - "CONVERSIONLASTUPDATE": 1757667157, - "SUPPLY": 120704779.826411, - "MKTCAP": 545120187011.0361, - "MKTCAPPENALTY": 0, - "CIRCULATINGSUPPLY": 120704779.826411, - "CIRCULATINGSUPPLYMKTCAP": 545120187011.0361, - "TOTALVOLUME24H": 4716921.79345383, - "TOTALVOLUME24HTO": 21275044670.661804, - "TOTALTOPTIERVOLUME24H": 2809715.26861036, - "TOTALTOPTIERVOLUME24HTO": 12661825053.456081, - "IMAGEURL": "/media/37746238/eth.png" - } - } - } -}` - _, _ = w.Write([]byte(response)) - }) - - srv := httptest.NewServer(mux) - - geckoClient := &Client{ - httpClient: thirdparty.NewHTTPClient(), - baseURL: srv.URL, - } - - marketValues, err := geckoClient.FetchTokenMarketValues(testTokens, "USD") - require.NoError(t, err) - require.NotNil(t, marketValues) - require.Len(t, marketValues, len(testTokens)) - - require.Equal(t, thirdparty.TokenMarketValues{}, marketValues[testTokens[0].Key()]) - require.Equal(t, thirdparty.TokenMarketValues{}, marketValues[testTokens[1].Key()]) - require.Equal(t, thirdparty.TokenMarketValues{}, marketValues[testTokens[2].Key()]) - require.Equal(t, thirdparty.TokenMarketValues{}, marketValues[testTokens[3].Key()]) - - ethereumValues := thirdparty.TokenMarketValues{ - MKTCAP: 5.451201870110361e+11, - HIGHDAY: 4564.28612417753, - LOWDAY: 4452.72268362409, - CHANGEPCTHOUR: -0.24559134660558343, - CHANGEPCTDAY: 1.2336984657834318, - CHANGEPCT24HOUR: 1.8810692473855388, - CHANGE24HOUR: 83.38330140132985, - } - - for _, index := range []int{4, 5} { - require.InDelta(t, ethereumValues.MKTCAP, marketValues[testTokens[index].Key()].MKTCAP, 1e-10) - require.InDelta(t, ethereumValues.HIGHDAY, marketValues[testTokens[index].Key()].HIGHDAY, 1e-10) - require.InDelta(t, ethereumValues.LOWDAY, marketValues[testTokens[index].Key()].LOWDAY, 1e-10) - require.InDelta(t, ethereumValues.CHANGEPCTHOUR, marketValues[testTokens[index].Key()].CHANGEPCTHOUR, 1e-10) - require.InDelta(t, ethereumValues.CHANGEPCTDAY, marketValues[testTokens[index].Key()].CHANGEPCTDAY, 1e-10) - require.InDelta(t, ethereumValues.CHANGEPCT24HOUR, marketValues[testTokens[index].Key()].CHANGEPCT24HOUR, 1e-10) - require.InDelta(t, ethereumValues.CHANGE24HOUR, marketValues[testTokens[index].Key()].CHANGE24HOUR, 1e-10) - } -} diff --git a/services/wallet/token/token.go b/services/wallet/token/token.go index 1f1a7a4408e..013f0eb1746 100644 --- a/services/wallet/token/token.go +++ b/services/wallet/token/token.go @@ -574,7 +574,7 @@ func (tm *Manager) GetTokensOfInterestForActiveNetworksMode() ([]*tokentypes.Tok return tm.GetTokensByKeys(tokensKeys) } -// GetTokensForFetchingMarketData returns all unique tokens for fetching market data from Coingecko (doesn't affect CryptoCompare cause it maps tokens differently, by symbol) +// GetTokensForFetchingMarketData returns all unique tokens for fetching market data from Coingecko. // Special handling for test tokens, for fetching market data from Coingecko, cause their API doesn't support test tokens // Corresponding mainnet tokens are needed to fetch market data for test tokens. // Returns list of test tokens and list of mainnet tokens that have a cross chain id set. @@ -598,7 +598,7 @@ func (tm *Manager) GetTokensForFetchingMarketData() ([]*tokentypes.Token, error) return tm.GetTokensByKeysForFetchingMarketData(tokensKeys) } -// GetTokensByKeysForFetchingMarketData returns all unique tokens for fetching market data from Coingecko (doesn't affect CryptoCompare cause it maps tokens differently, by symbol) +// GetTokensByKeysForFetchingMarketData returns all unique tokens for fetching market data from Coingecko. // Special handling for test tokens, for fetching market data from Coingecko, cause their API doesn't support test tokens // Corresponding mainnet tokens are needed to fetch market data for test tokens. // Returns list of test tokens that match the given token keys and corresponding mainnet tokens for those test tokens that have a cross chain id set. diff --git a/tests-functional/clients/status_backend.py b/tests-functional/clients/status_backend.py index 592b261817a..4c05d6542d2 100644 --- a/tests-functional/clients/status_backend.py +++ b/tests-functional/clients/status_backend.py @@ -244,11 +244,8 @@ def _set_proxy_credentials(self, data): user = os.environ["STATUS_BUILD_PROXY_USER"] password = os.environ["STATUS_BUILD_PROXY_PASSWORD"] - data["StatusProxyMarketUser"] = user - data["StatusProxyMarketPassword"] = password data["StatusProxyBlockchainUser"] = user data["StatusProxyBlockchainPassword"] = password - data["StatusProxyEnabled"] = True data["StatusProxyStageName"] = "test" return data diff --git a/tests-unit-network/cryptocompare/cryptocompare_test.go b/tests-unit-network/cryptocompare/cryptocompare_test.go deleted file mode 100644 index d446735802f..00000000000 --- a/tests-unit-network/cryptocompare/cryptocompare_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package cryptocompare_tests - -import ( - "context" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "go.uber.org/mock/gomock" - - "github.com/status-im/status-go/internal/db/appdatabase" - "github.com/status-im/status-go/internal/db/walletdatabase" - mock_network "github.com/status-im/status-go/internal/rpc/network/mock" - "github.com/status-im/status-go/internal/testutils" - "github.com/status-im/status-go/params" - "github.com/status-im/status-go/pkg/pubsub" - protocolsqlite "github.com/status-im/status-go/protocol/sqlite" - w_common "github.com/status-im/status-go/services/wallet/common" - "github.com/status-im/status-go/services/wallet/thirdparty/market/cryptocompare" - "github.com/status-im/status-go/services/wallet/token" - tokentypes "github.com/status-im/status-go/services/wallet/token/types" -) - -func getTokenSymbols(t *testing.T) []*tokentypes.Token { - appDB, err := testutils.SetupTestMemorySQLDB(appdatabase.DbInitializer{}) - require.NoError(t, err) - require.NoError(t, protocolsqlite.Migrate(appDB)) - - walletDB, err := testutils.SetupTestMemorySQLDB(walletdatabase.DbInitializer{}) - require.NoError(t, err) - - networksList := []params.Network{ - { - ChainID: w_common.EthereumMainnet, - }, - { - ChainID: w_common.OptimismMainnet, - }, - { - ChainID: w_common.ArbitrumMainnet, - }, - { - ChainID: w_common.BaseMainnet, - }, - { - ChainID: w_common.BSCMainnet, - }, - } - - ptrNetworkList := make([]*params.Network, 0, len(networksList)) - for i := range networksList { - ptrNetworkList = append(ptrNetworkList, &networksList[i]) - } - - ctrl := gomock.NewController(t) - defer ctrl.Finish() - networkManager := mock_network.NewMockManagerInterface(ctrl) - networkManager.EXPECT().Get(gomock.Any()).Return(ptrNetworkList, nil).AnyTimes() - networkManager.EXPECT().GetAll().Return(ptrNetworkList, nil).AnyTimes() - networkManager.EXPECT().GetEmbeddedNetworks().Return(networksList).AnyTimes() - networkManager.EXPECT().GetActiveNetworks().Return(ptrNetworkList, nil).AnyTimes() - networkManager.EXPECT().GetPublisher().Return(pubsub.NewPublisher()).AnyTimes() - networkManager.EXPECT().GetTestNetworksEnabled().Return(false, nil).AnyTimes() - - // Skeleton token store to get full list of tokens - tm, err := token.NewTokenManager(walletDB, nil, nil, networkManager, appDB, nil, nil, nil, nil, time.Hour, time.Hour) - require.NoError(t, err) - - err = tm.Start(context.Background()) - require.NoError(t, err) - - tokens, err := tm.GetTokensOfInterestForActiveNetworksMode() - require.NoError(t, err) - require.Greater(t, len(tokens), 0) - - return tokens -} - -func TestFetchPrices(t *testing.T) { - tokens := getTokenSymbols(t) - - stdClient := cryptocompare.NewClient() - _, err := stdClient.FetchPrices(tokens, []string{"USD"}) - require.NoError(t, err) -} - -func TestFetchTokenMarketValues(t *testing.T) { - tokens := getTokenSymbols(t) - - stdClient := cryptocompare.NewClient() - _, err := stdClient.FetchTokenMarketValues(tokens, "USD") - require.NoError(t, err) -}