feat: Save previously owned tokens (#4482)
This commit is contained in:
parent
5d644bdf94
commit
313375e215
|
@ -250,6 +250,11 @@ func (r *Reader) GetWalletToken(ctx context.Context, addresses []common.Address)
|
|||
availableNetworks = append(availableNetworks, network)
|
||||
}
|
||||
|
||||
cachedTokens, err := r.GetCachedWalletTokensWithoutMarketData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chainIDs := make([]uint64, 0)
|
||||
for _, network := range availableNetworks {
|
||||
chainIDs = append(chainIDs, network.ChainID)
|
||||
|
@ -296,7 +301,7 @@ func (r *Reader) GetWalletToken(ctx context.Context, addresses []common.Address)
|
|||
for symbol, tokens := range getTokenBySymbols(tokenList) {
|
||||
balancesPerChain := make(map[uint64]ChainBalance)
|
||||
decimals := tokens[0].Decimals
|
||||
anyPositiveBalance := false
|
||||
isVisible := false
|
||||
for _, token := range tokens {
|
||||
hexBalance := balances[token.ChainID][address][token.Address]
|
||||
balance := big.NewFloat(0.0)
|
||||
|
@ -310,8 +315,8 @@ func (r *Reader) GetWalletToken(ctx context.Context, addresses []common.Address)
|
|||
if client, ok := clients[token.ChainID]; ok {
|
||||
hasError = err != nil || !client.GetIsConnected()
|
||||
}
|
||||
if !anyPositiveBalance {
|
||||
anyPositiveBalance = balance.Cmp(big.NewFloat(0.0)) > 0
|
||||
if !isVisible {
|
||||
isVisible = balance.Cmp(big.NewFloat(0.0)) > 0 || r.isCachedToken(cachedTokens, address, token.Symbol, token.ChainID)
|
||||
}
|
||||
balancesPerChain[token.ChainID] = ChainBalance{
|
||||
RawBalance: hexBalance.ToInt().String(),
|
||||
|
@ -322,7 +327,7 @@ func (r *Reader) GetWalletToken(ctx context.Context, addresses []common.Address)
|
|||
}
|
||||
}
|
||||
|
||||
if !anyPositiveBalance && !belongsToMandatoryTokens(symbol) {
|
||||
if !isVisible && !belongsToMandatoryTokens(symbol) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -420,6 +425,21 @@ func (r *Reader) GetWalletToken(ctx context.Context, addresses []common.Address)
|
|||
return result, r.persistence.SaveTokens(result)
|
||||
}
|
||||
|
||||
func (r *Reader) isCachedToken(cachedTokens map[common.Address][]Token, address common.Address, symbol string, chainID uint64) bool {
|
||||
if tokens, ok := cachedTokens[address]; ok {
|
||||
for _, t := range tokens {
|
||||
if t.Symbol != symbol {
|
||||
continue
|
||||
}
|
||||
_, ok := t.BalancesPerChain[chainID]
|
||||
if ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetCachedWalletTokensWithoutMarketData returns the latest fetched balances, minus
|
||||
// price information
|
||||
func (r *Reader) GetCachedWalletTokensWithoutMarketData() (map[common.Address][]Token, error) {
|
||||
|
|
|
@ -3,6 +3,7 @@ package token
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -293,6 +294,22 @@ func (tm *Manager) FindOrCreateTokenByAddress(ctx context.Context, chainID uint6
|
|||
return token
|
||||
}
|
||||
|
||||
func (tm *Manager) MarkAsPreviouslyOwnedToken(token *Token, owner common.Address) error {
|
||||
if token == nil {
|
||||
return errors.New("token is nil")
|
||||
}
|
||||
if (owner == common.Address{}) {
|
||||
return errors.New("owner is nil")
|
||||
}
|
||||
count := 0
|
||||
err := tm.db.QueryRow(`SELECT EXISTS(SELECT 1 FROM token_balances WHERE user_address = ? AND token_address = ? AND chain_id = ?)`, owner.Hex(), token.Address.Hex(), token.ChainID).Scan(&count)
|
||||
if err != nil || count > 0 {
|
||||
return err
|
||||
}
|
||||
_, err = tm.db.Exec(`INSERT INTO token_balances(user_address,token_name,token_symbol,token_address,token_decimals,chain_id,token_decimals,raw_balance,balance) VALUES (?,?,?,?,?,?,?,?,?)`, owner.Hex(), token.Name, token.Symbol, token.Address.Hex(), token.Decimals, token.ChainID, 0, "0", "0")
|
||||
return err
|
||||
}
|
||||
|
||||
func (tm *Manager) discoverTokenCommunityID(ctx context.Context, token *Token, address common.Address) {
|
||||
if token == nil || token.CommunityData != nil {
|
||||
// Token is invalid or is alrady discovered. Nothing to do here.
|
||||
|
|
|
@ -193,3 +193,52 @@ 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 TestMarkAsPreviouslyOwnedToken(t *testing.T) {
|
||||
manager, stop := setupTestTokenDB(t)
|
||||
defer stop()
|
||||
|
||||
owner := common.HexToAddress("0x1234567890abcdef")
|
||||
token := &Token{
|
||||
Address: common.HexToAddress("0xabcdef1234567890"),
|
||||
Name: "TestToken",
|
||||
Symbol: "TT",
|
||||
Decimals: 18,
|
||||
ChainID: 1,
|
||||
}
|
||||
|
||||
err := manager.MarkAsPreviouslyOwnedToken(nil, owner)
|
||||
require.Error(t, err)
|
||||
|
||||
err = manager.MarkAsPreviouslyOwnedToken(token, common.Address{})
|
||||
require.Error(t, err)
|
||||
|
||||
err = manager.MarkAsPreviouslyOwnedToken(token, owner)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify that the token balance was inserted correctly
|
||||
var count int
|
||||
err = manager.db.QueryRow(`SELECT count(*) FROM token_balances`).Scan(&count)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, count)
|
||||
|
||||
token.Name = "123"
|
||||
|
||||
err = manager.MarkAsPreviouslyOwnedToken(token, owner)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Not updated because already exists
|
||||
err = manager.db.QueryRow(`SELECT count(*) FROM token_balances`).Scan(&count)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, count)
|
||||
|
||||
token.ChainID = 2
|
||||
|
||||
err = manager.MarkAsPreviouslyOwnedToken(token, owner)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Same token on different chains counts as different token
|
||||
err = manager.db.QueryRow(`SELECT count(*) FROM token_balances`).Scan(&count)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 2, count)
|
||||
}
|
||||
|
|
|
@ -354,6 +354,20 @@ func setMultiTxID(tx Transaction, multiTxID MultiTransactionIDType) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *transfersCommand) markMultiTxTokensAsPreviouslyOwned(ctx context.Context, multiTransaction *MultiTransaction, ownerAddress common.Address) {
|
||||
if multiTransaction == nil {
|
||||
return
|
||||
}
|
||||
if len(multiTransaction.ToAsset) > 0 && multiTransaction.ToNetworkID > 0 {
|
||||
token := c.tokenManager.GetToken(multiTransaction.ToNetworkID, multiTransaction.ToAsset)
|
||||
_ = c.tokenManager.MarkAsPreviouslyOwnedToken(token, ownerAddress)
|
||||
}
|
||||
if len(multiTransaction.FromAsset) > 0 && multiTransaction.FromNetworkID > 0 {
|
||||
token := c.tokenManager.GetToken(multiTransaction.FromNetworkID, multiTransaction.FromAsset)
|
||||
_ = c.tokenManager.MarkAsPreviouslyOwnedToken(token, ownerAddress)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *transfersCommand) checkAndProcessSwapMultiTx(ctx context.Context, tx Transaction) (bool, error) {
|
||||
for _, subTx := range tx {
|
||||
switch subTx.Type {
|
||||
|
@ -370,6 +384,7 @@ func (c *transfersCommand) checkAndProcessSwapMultiTx(ctx context.Context, tx Tr
|
|||
return false, err
|
||||
}
|
||||
setMultiTxID(tx, id)
|
||||
c.markMultiTxTokensAsPreviouslyOwned(ctx, multiTransaction, subTx.Address)
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
@ -390,6 +405,7 @@ func (c *transfersCommand) checkAndProcessBridgeMultiTx(ctx context.Context, tx
|
|||
|
||||
if multiTransaction != nil {
|
||||
setMultiTxID(tx, MultiTransactionIDType(multiTransaction.ID))
|
||||
c.markMultiTxTokensAsPreviouslyOwned(ctx, multiTransaction, subTx.Address)
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
@ -403,7 +419,10 @@ func (c *transfersCommand) processUnknownErc20CommunityTransactions(ctx context.
|
|||
// To can be nil in case of erc20 contract creation
|
||||
if tx.Type == w_common.Erc20Transfer && tx.Transaction.To() != nil {
|
||||
// Find token in db or if this is a community token, find its metadata
|
||||
_ = c.tokenManager.FindOrCreateTokenByAddress(ctx, tx.NetworkID, *tx.Transaction.To())
|
||||
token := c.tokenManager.FindOrCreateTokenByAddress(ctx, tx.NetworkID, *tx.Transaction.To())
|
||||
if token != nil && (token.Verified || token.CommunityData != nil) {
|
||||
_ = c.tokenManager.MarkAsPreviouslyOwnedToken(token, tx.Address)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue