feat: add token list
This commit is contained in:
parent
ecbacb0a7f
commit
5381ec4a76
|
@ -131,26 +131,6 @@ func (api *API) FetchDecodedTxData(ctx context.Context, data string) (*thirdpart
|
|||
return api.s.decoder.Decode(data)
|
||||
}
|
||||
|
||||
// @deprecated
|
||||
// GetTokensBalances return mapping of token balances for every account.
|
||||
func (api *API) GetTokensBalances(ctx context.Context, accounts, addresses []common.Address) (map[common.Address]map[common.Address]*hexutil.Big, error) {
|
||||
chainClients, err := api.s.rpcClient.EthClients([]uint64{api.s.rpcClient.UpstreamChainID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return api.s.tokenManager.GetBalances(ctx, chainClients, accounts, addresses)
|
||||
}
|
||||
|
||||
// @deprecated
|
||||
func (api *API) GetTokensBalancesForChainIDs(ctx context.Context, chainIDs []uint64, accounts, addresses []common.Address) (map[common.Address]map[common.Address]*hexutil.Big, error) {
|
||||
log.Debug("wallet.api.GetTokensBalances", "accounts", accounts, "addresses", addresses)
|
||||
clients, err := api.s.rpcClient.EthClients(chainIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return api.s.tokenManager.GetBalances(ctx, clients, accounts, addresses)
|
||||
}
|
||||
|
||||
// GetBalanceHistory retrieves token balance history for token identity on multiple chains
|
||||
func (api *API) GetBalanceHistory(ctx context.Context, chainIDs []uint64, address common.Address, tokenSymbol string, currencySymbol string, timeInterval history.TimeInterval) ([]*history.ValuePoint, error) {
|
||||
log.Debug("wallet.api.GetBalanceHistory", "chainIDs", chainIDs, "address", address, "tokenSymbol", tokenSymbol, "currencySymbol", currencySymbol, "timeInterval", timeInterval)
|
||||
|
@ -182,16 +162,25 @@ func (api *API) GetBalanceHistoryRange(ctx context.Context, chainIDs []uint64, a
|
|||
return api.s.history.GetBalanceHistory(ctx, chainIDs, address, tokenSymbol, currencySymbol, fromTimestamp)
|
||||
}
|
||||
|
||||
func (api *API) GetTokenList(ctx context.Context) ([]*token.List, error) {
|
||||
log.Debug("call to get token list")
|
||||
rst := api.s.tokenManager.GetList()
|
||||
log.Debug("result from token list", "len", len(rst))
|
||||
return rst, nil
|
||||
}
|
||||
|
||||
// @deprecated
|
||||
func (api *API) GetTokens(ctx context.Context, chainID uint64) ([]*token.Token, error) {
|
||||
log.Debug("call to get tokens")
|
||||
rst, err := api.s.tokenManager.GetTokens(chainID, true)
|
||||
rst, err := api.s.tokenManager.GetTokens(chainID)
|
||||
log.Debug("result from token store", "len", len(rst))
|
||||
return rst, err
|
||||
}
|
||||
|
||||
// @deprecated
|
||||
func (api *API) GetCustomTokens(ctx context.Context) ([]*token.Token, error) {
|
||||
log.Debug("call to get custom tokens")
|
||||
rst, err := api.s.tokenManager.GetCustoms()
|
||||
rst, err := api.s.tokenManager.GetCustoms(true)
|
||||
log.Debug("result from database for custom tokens", "len", len(rst))
|
||||
return rst, err
|
||||
}
|
||||
|
@ -202,24 +191,6 @@ func (api *API) DiscoverToken(ctx context.Context, chainID uint64, address commo
|
|||
return token, err
|
||||
}
|
||||
|
||||
// @deprecated
|
||||
func (api *API) GetVisibleTokens(chainIDs []uint64) (map[uint64][]*token.Token, error) {
|
||||
log.Debug("call to get visible tokens")
|
||||
rst, err := api.s.tokenManager.GetVisible(chainIDs)
|
||||
log.Debug("result from database for visible tokens", "len", len(rst))
|
||||
return rst, err
|
||||
}
|
||||
|
||||
// @deprecated
|
||||
func (api *API) ToggleVisibleToken(ctx context.Context, chainID uint64, address common.Address) (bool, error) {
|
||||
log.Debug("call to toggle visible tokens")
|
||||
err := api.s.tokenManager.Toggle(chainID, address)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (api *API) AddCustomToken(ctx context.Context, token token.Token) error {
|
||||
log.Debug("call to create or edit custom token")
|
||||
if token.ChainID == 0 {
|
||||
|
|
|
@ -94,7 +94,7 @@ func (s *Service) getAllFiatCurrencyFormats() (FormatPerSymbol, error) {
|
|||
}
|
||||
|
||||
func (s *Service) fetchAllTokenCurrencyFormats() (FormatPerSymbol, error) {
|
||||
tokens, err := s.tokenManager.GetAllTokensAndNativeCurrencies()
|
||||
tokens, err := s.tokenManager.GetAllTokens()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -6,17 +6,26 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/status-im/status-go/appdatabase"
|
||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||
"github.com/status-im/status-go/params"
|
||||
"github.com/status-im/status-go/rpc"
|
||||
"github.com/status-im/status-go/rpc/network"
|
||||
"github.com/status-im/status-go/t/helpers"
|
||||
"github.com/status-im/status-go/walletdatabase"
|
||||
)
|
||||
|
||||
func TestKeycardPairingsFile(t *testing.T) {
|
||||
appDB, err := helpers.SetupTestMemorySQLDB(appdatabase.DbInitializer{})
|
||||
require.NoError(t, err)
|
||||
|
||||
accountsDb, err := accounts.NewDB(appDB)
|
||||
require.NoError(t, err)
|
||||
|
||||
db, err := helpers.SetupTestMemorySQLDB(walletdatabase.DbInitializer{})
|
||||
require.NoError(t, err)
|
||||
|
||||
service := NewService(db, nil, &rpc.Client{}, nil, nil, nil, nil, ¶ms.NodeConfig{}, nil, nil, nil, nil)
|
||||
service := NewService(db, accountsDb, &rpc.Client{NetworkManager: network.NewManager(db)}, nil, nil, nil, nil, ¶ms.NodeConfig{}, nil, nil, nil, nil)
|
||||
|
||||
data, err := service.KeycardPairings().GetPairingsJSONFileContent()
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -36,7 +36,7 @@ func (p *Persistence) SaveTokens(tokens map[common.Address][]Token) (err error)
|
|||
if b.HasError || b.Balance.Cmp(big.NewFloat(0)) == 0 {
|
||||
continue
|
||||
}
|
||||
_, err = tx.Exec(`INSERT INTO token_balances(user_address,token_name,token_symbol,token_address,token_color,token_decimals,token_description,token_url,balance,raw_balance,chain_id) VALUES (?,?,?,?,?,?,?,?,?,?,?)`, address.Hex(), t.Name, t.Symbol, b.Address.Hex(), t.Color, t.Decimals, t.Description, t.AssetWebsiteURL, b.Balance.String(), b.RawBalance, chainID)
|
||||
_, err = tx.Exec(`INSERT INTO token_balances(user_address,token_name,token_symbol,token_address,token_decimals,token_description,token_url,balance,raw_balance,chain_id) VALUES (?,?,?,?,?,?,?,?,?,?)`, address.Hex(), t.Name, t.Symbol, b.Address.Hex(), t.Decimals, t.Description, t.AssetWebsiteURL, b.Balance.String(), b.RawBalance, chainID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func (p *Persistence) SaveTokens(tokens map[common.Address][]Token) (err error)
|
|||
}
|
||||
|
||||
func (p *Persistence) GetTokens() (map[common.Address][]Token, error) {
|
||||
rows, err := p.db.Query(`SELECT user_address, token_name, token_symbol, token_address, token_color, token_decimals, token_description, token_url, balance, raw_balance, chain_id FROM token_balances `)
|
||||
rows, err := p.db.Query(`SELECT user_address, token_name, token_symbol, token_address, token_decimals, token_description, token_url, balance, raw_balance, chain_id FROM token_balances `)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ func (p *Persistence) GetTokens() (map[common.Address][]Token, error) {
|
|||
token := Token{}
|
||||
var chainID uint64
|
||||
|
||||
err := rows.Scan(&addressStr, &token.Name, &token.Symbol, &tokenAddress, &token.Color, &token.Decimals, &token.Description, &token.AssetWebsiteURL, &balance, &rawBalance, &chainID)
|
||||
err := rows.Scan(&addressStr, &token.Name, &token.Symbol, &tokenAddress, &token.Decimals, &token.Description, &token.AssetWebsiteURL, &balance, &rawBalance, &chainID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ func TestSaveTokens(t *testing.T) {
|
|||
token1 := Token{
|
||||
Name: "token-1",
|
||||
Symbol: "TT1",
|
||||
Color: "color-1",
|
||||
Decimals: 10,
|
||||
BalancesPerChain: make(map[uint64]ChainBalance),
|
||||
Description: "description-1",
|
||||
|
@ -58,7 +57,6 @@ func TestSaveTokens(t *testing.T) {
|
|||
token2 := Token{
|
||||
Name: "token-2",
|
||||
Symbol: "TT2",
|
||||
Color: "color-2",
|
||||
Decimals: 11,
|
||||
BalancesPerChain: make(map[uint64]ChainBalance),
|
||||
Description: "description-2",
|
||||
|
@ -75,7 +73,6 @@ func TestSaveTokens(t *testing.T) {
|
|||
token3 := Token{
|
||||
Name: "token-3",
|
||||
Symbol: "TT3",
|
||||
Color: "color-3",
|
||||
Decimals: 11,
|
||||
BalancesPerChain: make(map[uint64]ChainBalance),
|
||||
Description: "description-3",
|
||||
|
@ -118,7 +115,6 @@ func TestSaveTokens(t *testing.T) {
|
|||
|
||||
require.Equal(t, actualToken1.Name, token1.Name)
|
||||
require.Equal(t, actualToken1.Symbol, token1.Symbol)
|
||||
require.Equal(t, actualToken1.Color, token1.Color)
|
||||
require.Equal(t, actualToken1.Decimals, token1.Decimals)
|
||||
require.Equal(t, actualToken1.Description, token1.Description)
|
||||
require.Equal(t, actualToken1.AssetWebsiteURL, token1.AssetWebsiteURL)
|
||||
|
@ -137,7 +133,6 @@ func TestSaveTokens(t *testing.T) {
|
|||
|
||||
require.Equal(t, actualToken2.Name, token2.Name)
|
||||
require.Equal(t, actualToken2.Symbol, token2.Symbol)
|
||||
require.Equal(t, actualToken2.Color, token2.Color)
|
||||
require.Equal(t, actualToken2.Decimals, token2.Decimals)
|
||||
require.Equal(t, actualToken2.Description, token2.Description)
|
||||
require.Equal(t, actualToken2.AssetWebsiteURL, token2.AssetWebsiteURL)
|
||||
|
@ -150,7 +145,6 @@ func TestSaveTokens(t *testing.T) {
|
|||
|
||||
require.Equal(t, actualToken3.Name, token3.Name)
|
||||
require.Equal(t, actualToken3.Symbol, token3.Symbol)
|
||||
require.Equal(t, actualToken3.Color, token3.Color)
|
||||
require.Equal(t, actualToken3.Decimals, token3.Decimals)
|
||||
require.Equal(t, actualToken3.Description, token3.Description)
|
||||
require.Equal(t, actualToken3.AssetWebsiteURL, token3.AssetWebsiteURL)
|
||||
|
|
|
@ -82,7 +82,6 @@ type ChainBalance struct {
|
|||
type Token struct {
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Color string `json:"color"`
|
||||
Decimals uint `json:"decimals"`
|
||||
BalancesPerChain map[uint64]ChainBalance `json:"balancesPerChain"`
|
||||
Description string `json:"description"`
|
||||
|
@ -192,7 +191,7 @@ func (r *Reader) GetWalletToken(ctx context.Context, addresses []common.Address)
|
|||
}
|
||||
currencies = append(currencies, currency)
|
||||
currencies = append(currencies, getFixedCurrencies()...)
|
||||
allTokens, err := r.tokenManager.GetTokensByChainIDs(chainIDs, true)
|
||||
allTokens, err := r.tokenManager.GetTokensByChainIDs(chainIDs)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -263,7 +262,6 @@ func (r *Reader) GetWalletToken(ctx context.Context, addresses []common.Address)
|
|||
|
||||
walletToken := Token{
|
||||
Name: tokens[0].Name,
|
||||
Color: tokens[0].Color,
|
||||
Symbol: symbol,
|
||||
BalancesPerChain: balancesPerChain,
|
||||
Decimals: decimals,
|
||||
|
|
|
@ -31,7 +31,6 @@ var uniswapTokens = []*Token{
|
|||
Address: common.HexToAddress("{{ $token.Address }}"),
|
||||
Name: "{{ $token.Name }}",
|
||||
Symbol: "{{ $token.Symbol }}",
|
||||
Color: "{{ $token.Color }}",
|
||||
Decimals: {{ $token.Decimals }},
|
||||
ChainID: {{ $token.ChainID }},
|
||||
PegSymbol: "{{ $token.PegSymbol }}",
|
||||
|
|
|
@ -3,7 +3,6 @@ package token
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -34,7 +33,6 @@ type Token struct {
|
|||
Address common.Address `json:"address"`
|
||||
Name string `json:"name"`
|
||||
Symbol string `json:"symbol"`
|
||||
Color string `json:"color"`
|
||||
// Decimals defines how divisible the token is. For example, 0 would be
|
||||
// indivisible, whereas 18 would allow very small amounts of the token
|
||||
// to be traded.
|
||||
|
@ -45,14 +43,26 @@ type Token struct {
|
|||
// pegged, while "USD" means it's pegged to the United States Dollar.
|
||||
PegSymbol string `json:"pegSymbol"`
|
||||
|
||||
Verified bool `json:"verified"`
|
||||
CommunityID *string `json:"communityId,omitempty"`
|
||||
Verified bool `json:"verified"`
|
||||
TokenListID string `json:"tokenListId"`
|
||||
}
|
||||
|
||||
func (t *Token) IsNative() bool {
|
||||
return t.Address == nativeChainAddress
|
||||
}
|
||||
|
||||
type List struct {
|
||||
Name string `json:"name"`
|
||||
Tokens []*Token `json:"tokens"`
|
||||
UpdatedAt int64 `json:"updatedAt"`
|
||||
Source string `json:"source"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type addressTokenMap = map[common.Address]*Token
|
||||
type storeMap = map[uint64]addressTokenMap
|
||||
|
||||
type ManagerInterface interface {
|
||||
LookupTokenIdentity(chainID uint64, address common.Address, native bool) *Token
|
||||
LookupToken(chainID *uint64, tokenSymbol string) (token *Token, isNative bool)
|
||||
|
@ -66,30 +76,63 @@ type Manager struct {
|
|||
networkManager *network.Manager
|
||||
stores []store // Set on init, not changed afterwards
|
||||
|
||||
// member variables below are protected by mutex
|
||||
tokenList []*Token
|
||||
tokenMap storeMap
|
||||
areTokensFetched bool
|
||||
tokens []*Token
|
||||
|
||||
tokenLock sync.RWMutex
|
||||
}
|
||||
|
||||
func mergeTokens(sliceLists [][]*Token) []*Token {
|
||||
allKeys := make(map[string]bool)
|
||||
res := []*Token{}
|
||||
for _, list := range sliceLists {
|
||||
for _, token := range list {
|
||||
key := strconv.FormatUint(token.ChainID, 10) + token.Address.String()
|
||||
if _, value := allKeys[key]; !value {
|
||||
allKeys[key] = true
|
||||
res = append(res, token)
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func NewTokenManager(
|
||||
db *sql.DB,
|
||||
RPCClient *rpc.Client,
|
||||
networkManager *network.Manager,
|
||||
) *Manager {
|
||||
maker, _ := contracts.NewContractMaker(RPCClient)
|
||||
// Order of stores is important when merging token lists. The former prevale
|
||||
stores := []store{newUniswapStore(), newDefaultStore()}
|
||||
tokens := make([]*Token, 0)
|
||||
|
||||
networks, err := networkManager.GetAll()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, store := range stores {
|
||||
validTokens := make([]*Token, 0)
|
||||
for _, token := range store.GetTokens() {
|
||||
token.Verified = true
|
||||
|
||||
for _, network := range networks {
|
||||
if network.ChainID == token.ChainID {
|
||||
validTokens = append(validTokens, token)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tokens = mergeTokens([][]*Token{tokens, validTokens})
|
||||
}
|
||||
|
||||
return &Manager{
|
||||
db: db,
|
||||
RPCClient: RPCClient,
|
||||
contractMaker: maker,
|
||||
networkManager: networkManager,
|
||||
stores: []store{newUniswapStore(), newDefaultStore()},
|
||||
tokenList: nil,
|
||||
tokenMap: nil,
|
||||
areTokensFetched: false,
|
||||
db: db,
|
||||
RPCClient: RPCClient,
|
||||
contractMaker: maker,
|
||||
networkManager: networkManager,
|
||||
stores: stores,
|
||||
tokens: tokens,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,103 +154,17 @@ func overrideTokensInPlace(networks []params.Network, tokens []*Token) {
|
|||
}
|
||||
}
|
||||
|
||||
func mergeTokenLists(sliceLists [][]*Token) []*Token {
|
||||
allKeys := make(map[string]bool)
|
||||
res := []*Token{}
|
||||
for _, list := range sliceLists {
|
||||
for _, token := range list {
|
||||
key := strconv.FormatUint(token.ChainID, 10) + token.Address.String()
|
||||
if _, value := allKeys[key]; !value {
|
||||
allKeys[key] = true
|
||||
res = append(res, token)
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (tm *Manager) inStore(address common.Address, chainID uint64) bool {
|
||||
if address == nativeChainAddress {
|
||||
return true
|
||||
}
|
||||
|
||||
if !tm.areTokensFetched {
|
||||
tm.fetchTokens()
|
||||
}
|
||||
|
||||
tokensMap, ok := tm.getAddressTokenMap(chainID)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
_, ok = tokensMap[address]
|
||||
|
||||
return ok
|
||||
}
|
||||
|
||||
func (tm *Manager) getTokenList() []*Token {
|
||||
func (tm *Manager) getTokens() []*Token {
|
||||
tm.tokenLock.RLock()
|
||||
defer tm.tokenLock.RUnlock()
|
||||
|
||||
return tm.tokenList
|
||||
}
|
||||
|
||||
func (tm *Manager) getAddressTokenMap(chainID uint64) (addressTokenMap, bool) {
|
||||
tm.tokenLock.RLock()
|
||||
defer tm.tokenLock.RUnlock()
|
||||
|
||||
tokenMap, chainPresent := tm.tokenMap[chainID]
|
||||
return tokenMap, chainPresent
|
||||
return tm.tokens
|
||||
}
|
||||
|
||||
func (tm *Manager) SetTokens(tokens []*Token) {
|
||||
tm.tokenLock.Lock()
|
||||
defer tm.tokenLock.Unlock()
|
||||
|
||||
tm.tokenList = tokens
|
||||
tm.tokenMap = toTokenMap(tokens)
|
||||
tm.areTokensFetched = true
|
||||
}
|
||||
|
||||
func (tm *Manager) fetchTokens() {
|
||||
tokenList := make([]*Token, 0)
|
||||
|
||||
networks, err := tm.networkManager.GetAll()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, store := range tm.stores {
|
||||
tokens := store.GetTokens()
|
||||
validTokens := make([]*Token, 0)
|
||||
for _, token := range tokens {
|
||||
token.Verified = true
|
||||
|
||||
for _, network := range networks {
|
||||
if network.ChainID == token.ChainID {
|
||||
validTokens = append(validTokens, token)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tokenList = mergeTokenLists([][]*Token{tokenList, validTokens})
|
||||
}
|
||||
|
||||
tm.SetTokens(tokenList)
|
||||
}
|
||||
|
||||
func (tm *Manager) getFullTokenList(chainID uint64) []*Token {
|
||||
tokens, err := tm.GetTokens(chainID, false)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
customTokens, err := tm.GetCustomsByChainID(chainID, false)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return append(tokens, customTokens...)
|
||||
tm.tokens = tokens
|
||||
}
|
||||
|
||||
func (tm *Manager) FindToken(network *params.Network, tokenSymbol string) *Token {
|
||||
|
@ -220,7 +177,7 @@ func (tm *Manager) FindToken(network *params.Network, tokenSymbol string) *Token
|
|||
|
||||
func (tm *Manager) LookupToken(chainID *uint64, tokenSymbol string) (token *Token, isNative bool) {
|
||||
if chainID == nil {
|
||||
networks, err := tm.networkManager.Get(true)
|
||||
networks, err := tm.networkManager.Get(false)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
|
@ -246,7 +203,10 @@ func (tm *Manager) LookupToken(chainID *uint64, tokenSymbol string) (token *Toke
|
|||
|
||||
// GetToken returns token by chainID and tokenSymbol. Use ToToken for native token
|
||||
func (tm *Manager) GetToken(chainID uint64, tokenSymbol string) *Token {
|
||||
allTokens := tm.getFullTokenList(chainID)
|
||||
allTokens, err := tm.GetTokens(chainID)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, token := range allTokens {
|
||||
if token.Symbol == tokenSymbol {
|
||||
return token
|
||||
|
@ -265,7 +225,10 @@ func (tm *Manager) LookupTokenIdentity(chainID uint64, address common.Address, n
|
|||
}
|
||||
|
||||
func (tm *Manager) FindTokenByAddress(chainID uint64, address common.Address) *Token {
|
||||
allTokens := tm.getFullTokenList(chainID)
|
||||
allTokens, err := tm.GetTokens(chainID)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, token := range allTokens {
|
||||
if token.Address == address {
|
||||
return token
|
||||
|
@ -276,8 +239,23 @@ func (tm *Manager) FindTokenByAddress(chainID uint64, address common.Address) *T
|
|||
}
|
||||
|
||||
func (tm *Manager) FindOrCreateTokenByAddress(ctx context.Context, chainID uint64, address common.Address) *Token {
|
||||
allTokens := tm.getFullTokenList(chainID)
|
||||
for _, token := range allTokens {
|
||||
// If token comes datasource, simply returns it
|
||||
for _, token := range tm.getTokens() {
|
||||
if token.ChainID != chainID {
|
||||
continue
|
||||
}
|
||||
if token.Address == address {
|
||||
return token
|
||||
}
|
||||
}
|
||||
|
||||
// Create custom token if not known or try to link with a community
|
||||
customTokens, err := tm.GetCustoms(false)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, token := range customTokens {
|
||||
if token.Address == address {
|
||||
tm.discoverTokenCommunityID(context.Background(), token, address)
|
||||
return token
|
||||
|
@ -347,7 +325,7 @@ func (tm *Manager) discoverTokenCommunityID(ctx context.Context, token *Token, a
|
|||
}
|
||||
|
||||
func (tm *Manager) FindSNT(chainID uint64) *Token {
|
||||
tokens, err := tm.GetTokens(chainID, false)
|
||||
tokens, err := tm.GetTokens(chainID)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -361,83 +339,110 @@ func (tm *Manager) FindSNT(chainID uint64) *Token {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (tm *Manager) GetAllTokensAndNativeCurrencies() ([]*Token, error) {
|
||||
allTokens, err := tm.GetAllTokens()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (tm *Manager) getNativeTokens() ([]*Token, error) {
|
||||
tokens := make([]*Token, 0)
|
||||
networks, err := tm.networkManager.Get(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, network := range networks {
|
||||
allTokens = append(allTokens, tm.ToToken(network))
|
||||
tokens = append(tokens, tm.ToToken(network))
|
||||
}
|
||||
|
||||
return allTokens, nil
|
||||
return tokens, nil
|
||||
}
|
||||
|
||||
func (tm *Manager) GetAllTokens() ([]*Token, error) {
|
||||
if !tm.areTokensFetched {
|
||||
tm.fetchTokens()
|
||||
}
|
||||
|
||||
tokens, err := tm.GetCustoms()
|
||||
allTokens, err := tm.GetCustoms(true)
|
||||
if err != nil {
|
||||
log.Error("can't fetch custom tokens", "error", err)
|
||||
}
|
||||
|
||||
tokens = append(tm.getTokenList(), tokens...)
|
||||
allTokens = append(tm.getTokens(), allTokens...)
|
||||
|
||||
overrideTokensInPlace(tm.networkManager.GetConfiguredNetworks(), tokens)
|
||||
overrideTokensInPlace(tm.networkManager.GetConfiguredNetworks(), allTokens)
|
||||
|
||||
return tokens, nil
|
||||
native, err := tm.getNativeTokens()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
allTokens = append(allTokens, native...)
|
||||
|
||||
return allTokens, nil
|
||||
}
|
||||
|
||||
func (tm *Manager) GetTokensByChainIDs(chainIDs []uint64, onlyCommunityCustoms bool) ([]*Token, error) {
|
||||
tokens := make([]*Token, 0)
|
||||
for _, chainID := range chainIDs {
|
||||
t, err := tm.GetTokens(chainID, onlyCommunityCustoms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (tm *Manager) GetTokens(chainID uint64) ([]*Token, error) {
|
||||
tokens, err := tm.GetAllTokens()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := make([]*Token, 0)
|
||||
|
||||
for _, token := range tokens {
|
||||
if token.ChainID == chainID {
|
||||
res = append(res, token)
|
||||
}
|
||||
tokens = append(tokens, t...)
|
||||
}
|
||||
return tokens, nil
|
||||
}
|
||||
|
||||
func (tm *Manager) GetDefaultTokens(chainID uint64) ([]*Token, error) {
|
||||
if !tm.areTokensFetched {
|
||||
tm.fetchTokens()
|
||||
}
|
||||
|
||||
tokensMap, ok := tm.getAddressTokenMap(chainID)
|
||||
if !ok {
|
||||
return nil, errors.New("no tokens for this network")
|
||||
}
|
||||
|
||||
res := make([]*Token, 0, len(tokensMap))
|
||||
|
||||
for _, token := range tokensMap {
|
||||
res = append(res, token)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (tm *Manager) GetTokens(chainID uint64, onlyCommunityCustoms bool) ([]*Token, error) {
|
||||
res, err := tm.GetDefaultTokens(chainID)
|
||||
func (tm *Manager) GetTokensByChainIDs(chainIDs []uint64) ([]*Token, error) {
|
||||
tokens, err := tm.GetAllTokens()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tokens, err := tm.GetCustomsByChainID(chainID, onlyCommunityCustoms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
res := make([]*Token, 0)
|
||||
|
||||
for _, token := range tokens {
|
||||
for _, chainID := range chainIDs {
|
||||
if token.ChainID == chainID {
|
||||
res = append(res, token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return append(res, tokens...), nil
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (tm *Manager) GetList() []*List {
|
||||
res := make([]*List, 0)
|
||||
nativeTokens, err := tm.getNativeTokens()
|
||||
if err == nil {
|
||||
res = append(res, &List{
|
||||
Name: "native",
|
||||
Tokens: nativeTokens,
|
||||
UpdatedAt: time.Now().Unix(),
|
||||
Source: "native",
|
||||
Version: "1.0.0",
|
||||
})
|
||||
}
|
||||
|
||||
customTokens, err := tm.GetCustoms(true)
|
||||
if err == nil && len(customTokens) > 0 {
|
||||
res = append(res, &List{
|
||||
Name: "custom",
|
||||
Tokens: customTokens,
|
||||
UpdatedAt: time.Now().Unix(),
|
||||
Source: "custom",
|
||||
Version: "1.0.0",
|
||||
})
|
||||
}
|
||||
|
||||
for _, store := range tm.stores {
|
||||
res = append(res, &List{
|
||||
Name: store.GetName(),
|
||||
Tokens: store.GetTokens(),
|
||||
UpdatedAt: store.GetUpdatedAt(),
|
||||
Source: store.GetSource(),
|
||||
Version: store.GetVersion(),
|
||||
})
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (tm *Manager) DiscoverToken(ctx context.Context, chainID uint64, address common.Address) (*Token, error) {
|
||||
|
@ -476,7 +481,7 @@ func (tm *Manager) DiscoverToken(ctx context.Context, chainID uint64, address co
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (tm *Manager) getTokens(query string, args ...any) ([]*Token, error) {
|
||||
func (tm *Manager) getTokensFromDB(query string, args ...any) ([]*Token, error) {
|
||||
rows, err := tm.db.Query(query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -487,7 +492,7 @@ func (tm *Manager) getTokens(query string, args ...any) ([]*Token, error) {
|
|||
for rows.Next() {
|
||||
token := &Token{}
|
||||
var communityIDDB sql.NullString
|
||||
err := rows.Scan(&token.Address, &token.Name, &token.Symbol, &token.Decimals, &token.Color, &token.ChainID, &communityIDDB)
|
||||
err := rows.Scan(&token.Address, &token.Name, &token.Symbol, &token.Decimals, &token.ChainID, &communityIDDB)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -502,46 +507,11 @@ func (tm *Manager) getTokens(query string, args ...any) ([]*Token, error) {
|
|||
return rst, nil
|
||||
}
|
||||
|
||||
func (tm *Manager) GetCustoms() ([]*Token, error) {
|
||||
return tm.getTokens("SELECT address, name, symbol, decimals, color, network_id, community_id FROM tokens")
|
||||
}
|
||||
|
||||
func (tm *Manager) GetCustomsByChainID(chainID uint64, onlyCommunityCustoms bool) ([]*Token, error) {
|
||||
func (tm *Manager) GetCustoms(onlyCommunityCustoms bool) ([]*Token, error) {
|
||||
if onlyCommunityCustoms {
|
||||
return tm.getTokens("SELECT address, name, symbol, decimals, color, network_id, community_id FROM tokens WHERE network_id=? AND community_id IS NOT NULL AND community_id != ''", chainID)
|
||||
return tm.getTokensFromDB("SELECT address, name, symbol, decimals, network_id, community_id FROM tokens WHERE community_id IS NOT NULL AND community_id != ''")
|
||||
}
|
||||
return tm.getTokens("SELECT address, name, symbol, decimals, color, network_id, community_id FROM tokens WHERE network_id=?", chainID)
|
||||
}
|
||||
|
||||
func (tm *Manager) IsTokenVisible(chainID uint64, address common.Address) (bool, error) {
|
||||
rows, err := tm.db.Query("SELECT chain_id, address FROM visible_tokens WHERE chain_id = ? AND address = ?", chainID, address)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
return rows.Next(), nil
|
||||
}
|
||||
|
||||
func (tm *Manager) Toggle(chainID uint64, address common.Address) error {
|
||||
isVisible, err := tm.IsTokenVisible(chainID, address)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isVisible {
|
||||
_, err = tm.db.Exec(`DELETE FROM visible_tokens WHERE address = ? and chain_id = ?`, address, chainID)
|
||||
return err
|
||||
}
|
||||
|
||||
insert, err := tm.db.Prepare("INSERT OR REPLACE INTO visible_tokens (chain_id, address) VALUES (?, ?)")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer insert.Close()
|
||||
|
||||
_, err = insert.Exec(chainID, address)
|
||||
return err
|
||||
return tm.getTokensFromDB("SELECT address, name, symbol, decimals, network_id, community_id FROM tokens")
|
||||
}
|
||||
|
||||
func (tm *Manager) ToToken(network *params.Network) *Token {
|
||||
|
@ -555,79 +525,12 @@ func (tm *Manager) ToToken(network *params.Network) *Token {
|
|||
}
|
||||
}
|
||||
|
||||
func (tm *Manager) GetVisible(chainIDs []uint64) (map[uint64][]*Token, error) {
|
||||
customTokens, err := tm.GetCustoms()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rst := make(map[uint64][]*Token)
|
||||
for _, chainID := range chainIDs {
|
||||
network := tm.networkManager.Find(chainID)
|
||||
if network == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
rst[chainID] = make([]*Token, 0)
|
||||
rst[chainID] = append(rst[chainID], tm.ToToken(network))
|
||||
}
|
||||
rows, err := tm.db.Query("SELECT chain_id, address FROM visible_tokens")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
address := common.HexToAddress("0x")
|
||||
chainID := uint64(0)
|
||||
err := rows.Scan(&chainID, &address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
found := false
|
||||
tokens, err := tm.GetTokens(chainID, false)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, token := range tokens {
|
||||
if token.Address == address {
|
||||
rst[chainID] = append(rst[chainID], token)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, token := range customTokens {
|
||||
if token.Address == address {
|
||||
rst[chainID] = append(rst[chainID], token)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, chainID := range chainIDs {
|
||||
if len(rst[chainID]) == 1 {
|
||||
token := tm.FindSNT(chainID)
|
||||
if token != nil {
|
||||
rst[chainID] = append(rst[chainID], token)
|
||||
}
|
||||
}
|
||||
}
|
||||
return rst, nil
|
||||
}
|
||||
|
||||
func (tm *Manager) UpsertCustom(token Token) error {
|
||||
insert, err := tm.db.Prepare("INSERT OR REPLACE INTO TOKENS (network_id, address, name, symbol, decimals, color) VALUES (?, ?, ?, ?, ?, ?)")
|
||||
insert, err := tm.db.Prepare("INSERT OR REPLACE INTO TOKENS (network_id, address, name, symbol, decimals) VALUES (?, ?, ?, ?, ?)")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = insert.Exec(token.ChainID, token.Address, token.Name, token.Symbol, token.Decimals, token.Color)
|
||||
_, err = insert.Exec(token.ChainID, token.Address, token.Name, token.Symbol, token.Decimals)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -680,136 +583,6 @@ func (tm *Manager) GetBalance(ctx context.Context, client chain.ClientInterface,
|
|||
return tm.GetTokenBalance(ctx, client, account, token)
|
||||
}
|
||||
|
||||
func (tm *Manager) GetBalances(parent context.Context, clients map[uint64]chain.ClientInterface, accounts, tokens []common.Address) (map[common.Address]map[common.Address]*hexutil.Big, error) {
|
||||
var (
|
||||
group = async.NewAtomicGroup(parent)
|
||||
mu sync.Mutex
|
||||
response = map[common.Address]map[common.Address]*hexutil.Big{}
|
||||
)
|
||||
|
||||
updateBalance := func(account common.Address, token common.Address, balance *big.Int) {
|
||||
mu.Lock()
|
||||
if _, ok := response[account]; !ok {
|
||||
response[account] = map[common.Address]*hexutil.Big{}
|
||||
}
|
||||
|
||||
if _, ok := response[account][token]; !ok {
|
||||
zeroHex := hexutil.Big(*big.NewInt(0))
|
||||
response[account][token] = &zeroHex
|
||||
}
|
||||
sum := big.NewInt(0).Add(response[account][token].ToInt(), balance)
|
||||
sumHex := hexutil.Big(*sum)
|
||||
response[account][token] = &sumHex
|
||||
mu.Unlock()
|
||||
}
|
||||
|
||||
for clientIdx := range clients {
|
||||
client := clients[clientIdx]
|
||||
|
||||
ethScanContract, _, err := tm.contractMaker.NewEthScan(client.NetworkID())
|
||||
|
||||
if err == nil {
|
||||
fetchChainBalance := false
|
||||
var tokenChunks [][]common.Address
|
||||
chunkSize := 500
|
||||
for i := 0; i < len(tokens); i += chunkSize {
|
||||
end := i + chunkSize
|
||||
if end > len(tokens) {
|
||||
end = len(tokens)
|
||||
}
|
||||
|
||||
tokenChunks = append(tokenChunks, tokens[i:end])
|
||||
}
|
||||
|
||||
for _, token := range tokens {
|
||||
if token == nativeChainAddress {
|
||||
fetchChainBalance = true
|
||||
}
|
||||
}
|
||||
if fetchChainBalance {
|
||||
group.Add(func(parent context.Context) error {
|
||||
ctx, cancel := context.WithTimeout(parent, requestTimeout)
|
||||
defer cancel()
|
||||
res, err := ethScanContract.EtherBalances(&bind.CallOpts{
|
||||
Context: ctx,
|
||||
}, accounts)
|
||||
if err != nil {
|
||||
log.Error("can't fetch chain balance 2", err)
|
||||
return nil
|
||||
}
|
||||
for idx, account := range accounts {
|
||||
balance := new(big.Int)
|
||||
balance.SetBytes(res[idx].Data)
|
||||
updateBalance(account, common.HexToAddress("0x"), balance)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
for accountIdx := range accounts {
|
||||
account := accounts[accountIdx]
|
||||
for idx := range tokenChunks {
|
||||
chunk := tokenChunks[idx]
|
||||
group.Add(func(parent context.Context) error {
|
||||
ctx, cancel := context.WithTimeout(parent, requestTimeout)
|
||||
defer cancel()
|
||||
res, err := ethScanContract.TokensBalance(&bind.CallOpts{
|
||||
Context: ctx,
|
||||
}, account, chunk)
|
||||
if err != nil {
|
||||
log.Error("can't fetch erc20 token balance 3", "account", account, "error", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
for idx, token := range chunk {
|
||||
if !res[idx].Success {
|
||||
continue
|
||||
}
|
||||
balance := new(big.Int)
|
||||
balance.SetBytes(res[idx].Data)
|
||||
updateBalance(account, token, balance)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for tokenIdx := range tokens {
|
||||
for accountIdx := range accounts {
|
||||
// Below, we set account, token and client from idx on purpose to avoid override
|
||||
account := accounts[accountIdx]
|
||||
token := tokens[tokenIdx]
|
||||
client := clients[clientIdx]
|
||||
if !tm.inStore(token, client.NetworkID()) {
|
||||
continue
|
||||
}
|
||||
group.Add(func(parent context.Context) error {
|
||||
ctx, cancel := context.WithTimeout(parent, requestTimeout)
|
||||
defer cancel()
|
||||
balance, err := tm.GetBalance(ctx, client, account, token)
|
||||
|
||||
if err != nil {
|
||||
log.Error("can't fetch erc20 token balance 4", "account", account, "token", token, "error", err)
|
||||
|
||||
return nil
|
||||
}
|
||||
updateBalance(account, token, balance)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
select {
|
||||
case <-group.WaitAsync():
|
||||
case <-parent.Done():
|
||||
return nil, parent.Err()
|
||||
}
|
||||
return response, group.Error()
|
||||
}
|
||||
|
||||
func (tm *Manager) GetBalancesByChain(parent context.Context, clients map[uint64]chain.ClientInterface, accounts, tokens []common.Address) (map[uint64]map[common.Address]map[common.Address]*hexutil.Big, error) {
|
||||
return tm.GetBalancesAtByChain(parent, clients, accounts, tokens, nil)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package token
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -18,14 +17,11 @@ func setupTestTokenDB(t *testing.T) (*Manager, func()) {
|
|||
require.NoError(t, err)
|
||||
|
||||
return &Manager{
|
||||
db: db,
|
||||
RPCClient: nil,
|
||||
contractMaker: nil,
|
||||
networkManager: nil,
|
||||
stores: nil,
|
||||
tokenList: nil,
|
||||
tokenMap: nil,
|
||||
areTokensFetched: false,
|
||||
db: db,
|
||||
RPCClient: nil,
|
||||
contractMaker: nil,
|
||||
networkManager: nil,
|
||||
stores: nil,
|
||||
}, func() {
|
||||
require.NoError(t, db.Close())
|
||||
}
|
||||
|
@ -35,7 +31,7 @@ func TestCustoms(t *testing.T) {
|
|||
manager, stop := setupTestTokenDB(t)
|
||||
defer stop()
|
||||
|
||||
rst, err := manager.GetCustoms()
|
||||
rst, err := manager.GetCustoms(false)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, rst)
|
||||
|
||||
|
@ -44,14 +40,13 @@ func TestCustoms(t *testing.T) {
|
|||
Name: "Zilliqa",
|
||||
Symbol: "ZIL",
|
||||
Decimals: 12,
|
||||
Color: "#fa6565",
|
||||
ChainID: 777,
|
||||
}
|
||||
|
||||
err = manager.UpsertCustom(token)
|
||||
require.NoError(t, err)
|
||||
|
||||
rst, err = manager.GetCustoms()
|
||||
rst, err = manager.GetCustoms(false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(rst))
|
||||
require.Equal(t, token, *rst[0])
|
||||
|
@ -59,11 +54,27 @@ func TestCustoms(t *testing.T) {
|
|||
err = manager.DeleteCustom(777, token.Address)
|
||||
require.NoError(t, err)
|
||||
|
||||
rst, err = manager.GetCustoms()
|
||||
rst, err = manager.GetCustoms(false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(rst))
|
||||
}
|
||||
|
||||
func toTokenMap(tokens []*Token) storeMap {
|
||||
tokenMap := storeMap{}
|
||||
|
||||
for _, token := range tokens {
|
||||
addTokMap := tokenMap[token.ChainID]
|
||||
if addTokMap == nil {
|
||||
addTokMap = make(addressTokenMap)
|
||||
}
|
||||
|
||||
addTokMap[token.Address] = token
|
||||
tokenMap[token.ChainID] = addTokMap
|
||||
}
|
||||
|
||||
return tokenMap
|
||||
}
|
||||
|
||||
func TestTokenOverride(t *testing.T) {
|
||||
networks := []params.Network{
|
||||
{
|
||||
|
@ -113,7 +124,7 @@ func TestTokenOverride(t *testing.T) {
|
|||
tokenList,
|
||||
}
|
||||
|
||||
overrideTokensInPlace(networks, testStore.tokenList)
|
||||
overrideTokensInPlace(networks, tokenList)
|
||||
tokens := testStore.GetTokens()
|
||||
tokenMap := toTokenMap(tokens)
|
||||
_, found := tokenMap[1][common.Address{1}]
|
||||
|
@ -125,62 +136,3 @@ func TestTokenOverride(t *testing.T) {
|
|||
require.Equal(t, common.Address{33}, tokenMap[2][common.Address{33}].Address)
|
||||
require.Equal(t, common.Address{4}, tokenMap[2][common.Address{4}].Address)
|
||||
}
|
||||
|
||||
func TestMergeTokenLists(t *testing.T) {
|
||||
tokenList1 := []*Token{
|
||||
&Token{
|
||||
Address: common.Address{1},
|
||||
Symbol: "SNT",
|
||||
ChainID: 1,
|
||||
},
|
||||
}
|
||||
tokenList1Copy := []*Token{
|
||||
&Token{
|
||||
Address: common.Address{1},
|
||||
Symbol: "SNT",
|
||||
ChainID: 1,
|
||||
},
|
||||
}
|
||||
tokenList2 := []*Token{
|
||||
&Token{
|
||||
Address: common.Address{3},
|
||||
Symbol: "STT",
|
||||
ChainID: 2,
|
||||
},
|
||||
&Token{
|
||||
Address: common.Address{4},
|
||||
Symbol: "TTT",
|
||||
ChainID: 2,
|
||||
},
|
||||
}
|
||||
tokenList1Plus2 := []*Token{
|
||||
&Token{
|
||||
Address: common.Address{1},
|
||||
Symbol: "SNT",
|
||||
ChainID: 1,
|
||||
},
|
||||
&Token{
|
||||
Address: common.Address{3},
|
||||
Symbol: "STT",
|
||||
ChainID: 2,
|
||||
},
|
||||
&Token{
|
||||
Address: common.Address{4},
|
||||
Symbol: "TTT",
|
||||
ChainID: 2,
|
||||
},
|
||||
}
|
||||
tokenListEmpty := []*Token{}
|
||||
|
||||
mergedList := mergeTokenLists([][]*Token{tokenListEmpty, tokenListEmpty})
|
||||
require.Equal(t, 0, len(mergedList))
|
||||
|
||||
mergedList = mergeTokenLists([][]*Token{tokenListEmpty, tokenList1})
|
||||
require.True(t, reflect.DeepEqual(mergedList, tokenList1))
|
||||
|
||||
mergedList = mergeTokenLists([][]*Token{tokenList1, tokenList1Copy})
|
||||
require.True(t, reflect.DeepEqual(mergedList, tokenList1))
|
||||
|
||||
mergedList = mergeTokenLists([][]*Token{tokenList1, tokenList2})
|
||||
require.True(t, reflect.DeepEqual(mergedList, tokenList1Plus2))
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -7,6 +7,26 @@ func newUniswapStore() *uniswapStore {
|
|||
return &uniswapStore{}
|
||||
}
|
||||
|
||||
func (ts *uniswapStore) GetTokens() []*Token {
|
||||
func (s *uniswapStore) GetTokens() []*Token {
|
||||
for _, token := range uniswapTokens {
|
||||
token.TokenListID = "uniswap"
|
||||
}
|
||||
|
||||
return uniswapTokens
|
||||
}
|
||||
|
||||
func (s *uniswapStore) GetName() string {
|
||||
return "Uniswap Labs Default Token List"
|
||||
}
|
||||
|
||||
func (s *uniswapStore) GetVersion() string {
|
||||
return "11.8.0"
|
||||
}
|
||||
|
||||
func (s *uniswapStore) GetUpdatedAt() int64 {
|
||||
return 1697613003
|
||||
}
|
||||
|
||||
func (s *uniswapStore) GetSource() string {
|
||||
return "https://gateway.ipfs.io/ipns/tokens.uniswap.org"
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ func (c *findBlocksCommand) ERC20ScanByBalance(parent context.Context, fromBlock
|
|||
|
||||
func (c *findBlocksCommand) checkERC20Tail(parent context.Context) ([]*DBHeader, error) {
|
||||
log.Debug("checkERC20Tail", "account", c.account, "to block", c.startBlockNumber, "from", c.resFromBlock.Number)
|
||||
tokens, err := c.tokenManager.GetTokens(c.chainClient.NetworkID(), false)
|
||||
tokens, err := c.tokenManager.GetTokens(c.chainClient.NetworkID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/status-im/status-go/appdatabase"
|
||||
"github.com/status-im/status-go/contracts/ethscan"
|
||||
"github.com/status-im/status-go/contracts/ierc20"
|
||||
"github.com/status-im/status-go/rpc/chain"
|
||||
|
@ -867,6 +868,9 @@ func TestFindBlocksCommand(t *testing.T) {
|
|||
ctx := context.Background()
|
||||
group := async.NewGroup(ctx)
|
||||
|
||||
appdb, err := helpers.SetupTestMemorySQLDB(appdatabase.DbInitializer{})
|
||||
require.NoError(t, err)
|
||||
|
||||
db, err := helpers.SetupTestMemorySQLDB(walletdatabase.DbInitializer{})
|
||||
require.NoError(t, err)
|
||||
tm := &TransactionManager{db, nil, nil, nil, nil, nil, nil, nil, nil, nil}
|
||||
|
@ -892,7 +896,7 @@ func TestFindBlocksCommand(t *testing.T) {
|
|||
}
|
||||
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db)
|
||||
client.SetClient(tc.NetworkID(), tc)
|
||||
tokenManager := token.NewTokenManager(db, client, network.NewManager(db))
|
||||
tokenManager := token.NewTokenManager(db, client, network.NewManager(appdb))
|
||||
tokenManager.SetTokens([]*token.Token{
|
||||
{
|
||||
Address: tokenTXXAddress,
|
||||
|
@ -990,6 +994,9 @@ func (m *MockChainClient) AbstractEthClient(chainID walletcommon.ChainID) (chain
|
|||
}
|
||||
|
||||
func TestFetchTransfersForLoadedBlocks(t *testing.T) {
|
||||
appdb, err := helpers.SetupTestMemorySQLDB(appdatabase.DbInitializer{})
|
||||
require.NoError(t, err)
|
||||
|
||||
db, err := helpers.SetupTestMemorySQLDB(walletdatabase.DbInitializer{})
|
||||
require.NoError(t, err)
|
||||
tm := &TransactionManager{db, nil, nil, nil, nil, nil, nil, nil, nil, nil}
|
||||
|
@ -1008,7 +1015,7 @@ func TestFetchTransfersForLoadedBlocks(t *testing.T) {
|
|||
|
||||
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db)
|
||||
client.SetClient(tc.NetworkID(), tc)
|
||||
tokenManager := token.NewTokenManager(db, client, network.NewManager(db))
|
||||
tokenManager := token.NewTokenManager(db, client, network.NewManager(appdb))
|
||||
|
||||
tokenManager.SetTokens([]*token.Token{
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue