Skip to content

Commit 4c65398

Browse files
committed
chore: improvements on tokens list being used
Instead of returning all tokens (atm there are ~15k unique tokens that the app operates with) from all supported lists, this change forms a token list based on `token_balances` table which contains tokens for all accounts, for those tokens includes other tokens that share the same cross chain id and includes all mandatory tokens.
1 parent 88d9716 commit 4c65398

File tree

6 files changed

+109
-19
lines changed

6 files changed

+109
-19
lines changed

services/wallet/api.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ func (api *API) GetAllTokens(ctx context.Context) ([]*tokentypes.Token, error) {
151151
return api.s.tokenManager.GetAllTokens()
152152
}
153153

154+
// GetTokensOfInterestForActiveNetworksMode returns all unique tokens that are of interest for the current active networks mode (testnet or mainnet).
155+
func (api *API) GetTokensOfInterestForActiveNetworksMode(ctx context.Context) ([]*tokentypes.Token, error) {
156+
return api.s.tokenManager.GetTokensOfInterestForActiveNetworksMode()
157+
}
158+
154159
// GetTokensForActiveNetworksMode returns all unique tokens for the current active networks mode (testnet or mainnet).
155160
func (api *API) GetTokensForActiveNetworksMode(ctx context.Context) ([]*tokentypes.Token, error) {
156161
return api.s.tokenManager.GetTokensForActiveNetworksMode()
@@ -326,14 +331,14 @@ func (api *API) GetFlatEthereumChains(ctx context.Context) ([]*params.Network, e
326331
}
327332

328333
// @deprecated
329-
// FetchPrices fetches prices for a given token keys and currencies. If no tokens are provided, all tokens are fetched.
334+
// FetchPrices fetches prices for a given token keys and currencies. If no tokens are provided, all tokens of interest are fetched.
330335
func (api *API) FetchPrices(ctx context.Context, tokensKeys []string, currencies []string) (map[string]map[string]float64, error) {
331336
logutils.ZapLogger().Debug("call to FetchPrices")
332337
return api.s.marketManager.FetchPrices(tokensKeys, currencies)
333338
}
334339

335340
// @deprecated
336-
// FetchTokenMarketValues fetches market values for a given token keys and currency. If no tokens are provided, all tokens are fetched.
341+
// FetchTokenMarketValues fetches market values for a given token keys and currency. If no tokens are provided, all tokens of interest are fetched.
337342
func (api *API) FetchMarketValues(ctx context.Context, tokensKeys []string, currency string) (map[string]thirdparty.TokenMarketValues, error) {
338343
logutils.ZapLogger().Debug("call to FetchMarketValues")
339344
return api.s.marketManager.FetchTokenMarketValues(tokensKeys, currency)
@@ -350,7 +355,7 @@ func (api *API) GetDailyMarketValues(ctx context.Context, tokenKey string, curre
350355
}
351356

352357
// @deprecated
353-
// FetchTokenDetails fetches token details for a given tokens. If no tokens are provided, all tokens are fetched.
358+
// FetchTokenDetails fetches token details for a given tokens. If no tokens are provided, all tokens of interest are fetched.
354359
func (api *API) FetchTokenDetails(ctx context.Context, tokensKeys []string) (map[string]thirdparty.TokenDetails, error) {
355360
logutils.ZapLogger().Debug("call to FetchTokenDetails")
356361
return api.s.marketManager.FetchTokenDetails(tokensKeys)

services/wallet/currency/service.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func (s *Service) getAllFiatCurrencyFormats() (FormatPerKey, error) {
100100
}
101101

102102
func (s *Service) getAllFixedTokenCurrencyFormats() (FormatPerKey, error) {
103-
tokens, err := s.tokenManager.GetTokensForActiveNetworksMode()
103+
tokens, err := s.tokenManager.GetTokensOfInterestForActiveNetworksMode()
104104
if err != nil {
105105
return nil, err
106106
}
@@ -127,7 +127,7 @@ func (s *Service) getAllFixedTokenCurrencyFormats() (FormatPerKey, error) {
127127
}
128128

129129
func (s *Service) fetchAllTokenCurrencyFormats() (FormatPerKey, error) {
130-
tokens, err := s.tokenManager.GetTokensForActiveNetworksMode()
130+
tokens, err := s.tokenManager.GetTokensOfInterestForActiveNetworksMode()
131131
if err != nil {
132132
return nil, err
133133
}

services/wallet/market/market_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
type MockTokenManager struct{}
2424

2525
func (m *MockTokenManager) GetTokensForFetchingMarketData() ([]*tokentypes.Token, error) {
26-
return m.GetTokensForActiveNetworksMode()
26+
return m.GetTokensOfInterestForActiveNetworksMode()
2727
}
2828

2929
func (m *MockTokenManager) GetTokensByKeysForFetchingMarketData(tokenKeys []string) ([]*tokentypes.Token, error) {
@@ -53,7 +53,7 @@ func (m *MockTokenManager) GetTokensByKeys(tokenKeys []string) ([]*tokentypes.To
5353
return tokens, nil
5454
}
5555

56-
func (m *MockTokenManager) GetTokensForActiveNetworksMode() ([]*tokentypes.Token, error) {
56+
func (m *MockTokenManager) GetTokensOfInterestForActiveNetworksMode() ([]*tokentypes.Token, error) {
5757
return m.GetTokensByKeys(testTokensKeys)
5858
}
5959

services/wallet/token/balance_persistence.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import (
1010
"github.com/ethereum/go-ethereum/common"
1111
"github.com/ethereum/go-ethereum/common/hexutil"
1212

13+
"github.com/status-im/go-wallet-sdk/pkg/tokens/types"
14+
15+
walletcommon "github.com/status-im/status-go/services/wallet/common"
1316
tokentypes "github.com/status-im/status-go/services/wallet/token/types"
1417
)
1518

@@ -182,3 +185,37 @@ func (p *balanceStorage) getCachedBalancesByChain(accounts []common.Address, tok
182185

183186
return ret, nil
184187
}
188+
189+
func (p *balanceStorage) getUsedTokensKeys(testnetMode bool) (map[string]interface{}, error) {
190+
query := `SELECT token_address, chain_id FROM token_balances`
191+
rows, err := p.walletDB.Query(query)
192+
if err != nil {
193+
return nil, err
194+
}
195+
defer rows.Close()
196+
197+
tokenKeys := make(map[string]interface{}, 0)
198+
199+
for rows.Next() {
200+
var tokenAddressStr string
201+
var chainID uint64
202+
203+
err := rows.Scan(&tokenAddressStr, &chainID)
204+
if err != nil {
205+
return nil, err
206+
}
207+
208+
if testnetMode && walletcommon.ChainID(chainID).IsMainnet() ||
209+
!testnetMode && !walletcommon.ChainID(chainID).IsMainnet() {
210+
continue
211+
}
212+
213+
tokenKey := types.TokenKey(chainID, common.HexToAddress(tokenAddressStr))
214+
215+
if _, ok := tokenKeys[tokenKey]; !ok {
216+
tokenKeys[tokenKey] = nil
217+
}
218+
}
219+
220+
return tokenKeys, nil
221+
}

services/wallet/token/token.go

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313

1414
"go.uber.org/zap"
1515

16+
"golang.org/x/exp/maps"
17+
1618
"github.com/status-im/go-wallet-sdk/pkg/tokens/autofetcher"
1719
"github.com/status-im/go-wallet-sdk/pkg/tokens/fetcher"
1820
"github.com/status-im/go-wallet-sdk/pkg/tokens/manager"
@@ -389,6 +391,58 @@ func (tm *Manager) GetTokensForActiveNetworksMode() ([]*tokentypes.Token, error)
389391
return tm.GetTokensByChains(chainIDs)
390392
}
391393

394+
// getTokenKeysForTokensOfInterestForActiveNetworksMode returns the token keys for the tokens of interest for the active networks mode (testnet or mainnet)
395+
// On top of the used tokens keys, it adds all tokens that share the same cross chain id (because of grouping) and all mandatory tokens.
396+
func (tm *Manager) getTokenKeysForTokensOfInterestForActiveNetworksMode() ([]string, error) {
397+
testnetMode, err := tm.settings.GetTestNetworksEnabled()
398+
if err != nil {
399+
return nil, err
400+
}
401+
402+
usedTokensKeys, err := tm.tokenBalancesStorage.getUsedTokensKeys(testnetMode)
403+
if err != nil {
404+
return nil, err
405+
}
406+
407+
tokens, err := tm.GetTokensByKeys(maps.Keys(usedTokensKeys))
408+
if err != nil {
409+
return nil, err
410+
}
411+
412+
// Because of grouping it's important to add all tokens that share the same cross chain id to the used tokens keys
413+
for _, token := range tokens {
414+
if token.CrossChainID == "" {
415+
continue
416+
}
417+
usedTokensKeys[token.Key()] = nil
418+
}
419+
420+
// It's also important to add all mandatory tokens to the used tokens keys
421+
for _, tokenKey := range walletcommon.MandatoryTokens() {
422+
if _, ok := usedTokensKeys[tokenKey]; ok {
423+
continue
424+
}
425+
chainID, _, ok := types.ChainAndAddressFromTokenKey(tokenKey)
426+
if !ok {
427+
continue
428+
}
429+
if walletcommon.ChainID(chainID).IsMainnet() == testnetMode {
430+
continue
431+
}
432+
usedTokensKeys[tokenKey] = nil
433+
}
434+
435+
return maps.Keys(usedTokensKeys), nil
436+
}
437+
438+
func (tm *Manager) GetTokensOfInterestForActiveNetworksMode() ([]*tokentypes.Token, error) {
439+
tokensKeys, err := tm.getTokenKeysForTokensOfInterestForActiveNetworksMode()
440+
if err != nil {
441+
return nil, err
442+
}
443+
return tm.GetTokensByKeys(tokensKeys)
444+
}
445+
392446
// GetTokensForFetchingMarketData returns all unique tokens for fetching market data from Coingecko (doesn't affect CryptoCompare cause it maps tokens differently, by symbol)
393447
// Special handling for test tokens, for fetching market data from Coingecko, cause their API doesn't support test tokens
394448
// Corresponding mainnet tokens are needed to fetch market data for test tokens.
@@ -401,22 +455,16 @@ func (tm *Manager) GetTokensForFetchingMarketData() ([]*tokentypes.Token, error)
401455

402456
// If not in testnet mode, use the regular tokens
403457
if !testnetMode {
404-
return tm.GetTokensForActiveNetworksMode()
458+
return tm.GetTokensOfInterestForActiveNetworksMode()
405459
}
406460

407461
// Test tokens handling...
408462
// Use all test tokens and add to the list only mainnet tokens that have a cross chain id set
409-
allWsdkTokens := tm.tokensManager.UniqueTokens()
410-
tokens := make([]*tokentypes.Token, 0)
411-
for _, token := range allWsdkTokens {
412-
if !walletcommon.ChainID(token.ChainID).IsMainnet() {
413-
tokens = append(tokens, &tokentypes.Token{Token: token})
414-
} else if token.CrossChainID != "" {
415-
tokens = append(tokens, &tokentypes.Token{Token: token})
416-
}
463+
tokensKeys, err := tm.getTokenKeysForTokensOfInterestForActiveNetworksMode()
464+
if err != nil {
465+
return nil, err
417466
}
418-
419-
return tokens, nil
467+
return tm.GetTokensByKeysForFetchingMarketData(tokensKeys)
420468
}
421469

422470
// GetTokensByKeysForFetchingMarketData returns all unique tokens for fetching market data from Coingecko (doesn't affect CryptoCompare cause it maps tokens differently, by symbol)

tests-unit-network/cryptocompare/cryptocompare_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func getTokenSymbols(t *testing.T) []*tokentypes.Token {
6464
err = tm.Start(context.Background())
6565
require.NoError(t, err)
6666

67-
tokens, err := tm.GetTokensForActiveNetworksMode()
67+
tokens, err := tm.GetTokensOfInterestForActiveNetworksMode()
6868
require.NoError(t, err)
6969
require.Greater(t, len(tokens), 0)
7070

0 commit comments

Comments
 (0)