feat: Fetch community token image (#4440)

This commit is contained in:
Cuteivist 2023-12-12 08:37:57 +01:00 committed by GitHub
parent 575a421786
commit dfe6baed9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 144 additions and 38 deletions

View File

@ -1,6 +1,7 @@
package node
import (
"database/sql"
"encoding/json"
"errors"
"fmt"
@ -73,6 +74,7 @@ func (b *StatusNode) initServices(config *params.NodeConfig, mediaServer *server
if err != nil {
return err
}
setSettingsNotifier(accDB, settingsFeed)
services := []common.StatusService{}
@ -99,7 +101,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 {
walletService := b.walletService(accDB, accountsFeed, settingsFeed, &b.walletFeed)
walletService := b.walletService(accDB, b.appDB, accountsFeed, settingsFeed, &b.walletFeed)
services = append(services, walletService)
}
@ -522,10 +524,10 @@ func (b *StatusNode) SetWalletCollectibleCommunityInfoProvider(provider thirdpar
}
}
func (b *StatusNode) walletService(accountsDB *accounts.Database, accountsFeed *event.Feed, settingsFeed *event.Feed, walletFeed *event.Feed) *wallet.Service {
func (b *StatusNode) walletService(accountsDB *accounts.Database, appDB *sql.DB, accountsFeed *event.Feed, settingsFeed *event.Feed, walletFeed *event.Feed) *wallet.Service {
if b.walletSrvc == nil {
b.walletSrvc = wallet.NewService(
b.walletDB, accountsDB, b.rpcClient, accountsFeed, settingsFeed, b.gethAccountManager, b.transactor, b.config,
b.walletDB, accountsDB, appDB, b.rpcClient, accountsFeed, settingsFeed, b.gethAccountManager, b.transactor, b.config,
b.ensService(b.timeSourceNow()),
b.stickersService(accountsDB),
b.pendingTracker,

View File

@ -459,7 +459,7 @@ func NewMessenger(
if c.tokenManager != nil {
managerOptions = append(managerOptions, communities.WithTokenManager(c.tokenManager))
} else if c.rpcClient != nil {
tokenManager := token.NewTokenManager(c.walletDb, c.rpcClient, c.rpcClient.NetworkManager)
tokenManager := token.NewTokenManager(c.walletDb, c.rpcClient, c.rpcClient.NetworkManager, database)
managerOptions = append(managerOptions, communities.WithTokenManager(communities.NewDefaultTokenManager(tokenManager)))
}

View File

@ -45,3 +45,22 @@ func (db *Database) GetTokenPrivilegesLevel(chainID uint64, contractAddress stri
}
return result, fmt.Errorf("can't find privileges level: chainId %v, contractAddress %v", chainID, contractAddress)
}
func (db *Database) GetCommunityERC20Metadata() ([]*token.CommunityToken, error) {
rows, err := db.db.Query(`SELECT community_id, address, name, symbol, chain_id, image_base64 FROM community_tokens WHERE type = ?`, protobuf.CommunityTokenType_ERC20)
if err != nil {
return nil, err
}
defer rows.Close()
var result []*token.CommunityToken
for rows.Next() {
token := token.CommunityToken{}
err := rows.Scan(&token.CommunityID, &token.Address, &token.Name, &token.Symbol, &token.ChainID, &token.Base64Image)
if err != nil {
return nil, err
}
result = append(result, &token)
}
return result, rows.Err()
}

View File

@ -25,7 +25,7 @@ func TestKeycardPairingsFile(t *testing.T) {
db, err := helpers.SetupTestMemorySQLDB(walletdatabase.DbInitializer{})
require.NoError(t, err)
service := NewService(db, accountsDb, &rpc.Client{NetworkManager: network.NewManager(db)}, nil, nil, nil, nil, &params.NodeConfig{}, nil, nil, nil, nil)
service := NewService(db, accountsDb, appDB, &rpc.Client{NetworkManager: network.NewManager(db)}, nil, nil, nil, nil, &params.NodeConfig{}, nil, nil, nil, nil)
data, err := service.KeycardPairings().GetPairingsJSONFileContent()
require.NoError(t, err)

View File

@ -102,7 +102,8 @@ type Token struct {
MarketValuesPerCurrency map[string]TokenMarketValues `json:"marketValuesPerCurrency"`
PegSymbol string `json:"pegSymbol"`
Verified bool `json:"verified"`
CommunityID string `json:"communityId"`
Image string `json:"image,omitempty"`
CommunityData *token.CommunityData `json:"community_data,omitempty"`
}
func splitVerifiedTokens(tokens []*token.Token) ([]*token.Token, []*token.Token) {
@ -325,11 +326,6 @@ func (r *Reader) GetWalletToken(ctx context.Context, addresses []common.Address)
continue
}
var communityID string
if tokens[0].CommunityID != nil {
communityID = *tokens[0].CommunityID
}
walletToken := Token{
Name: tokens[0].Name,
Symbol: symbol,
@ -337,7 +333,8 @@ func (r *Reader) GetWalletToken(ctx context.Context, addresses []common.Address)
Decimals: decimals,
PegSymbol: token.GetTokenPegSymbol(symbol),
Verified: tokens[0].Verified,
CommunityID: communityID,
CommunityData: tokens[0].CommunityData,
Image: tokens[0].Image,
}
tokenSymbols = append(tokenSymbols, symbol)

View File

@ -45,6 +45,7 @@ const (
func NewService(
db *sql.DB,
accountsDB *accounts.Database,
appDB *sql.DB,
rpcClient *rpc.Client,
accountFeed *event.Feed,
settingsFeed *event.Feed,
@ -96,7 +97,7 @@ func NewService(
})
balanceCacher := balance.NewCacherWithTTL(5 * time.Minute)
tokenManager := token.NewTokenManager(db, rpcClient, rpcClient.NetworkManager)
tokenManager := token.NewTokenManager(db, rpcClient, rpcClient.NetworkManager, appDB)
savedAddressesManager := &SavedAddressesManager{db: db}
transactionManager := transfer.NewTransactionManager(db, gethManager, transactor, config, accountsDB, pendingTxManager, feed)
transferController := transfer.NewTransferController(db, accountsDB, rpcClient, accountFeed, feed, transactionManager, pendingTxManager,

View File

@ -19,9 +19,11 @@ import (
"github.com/status-im/status-go/contracts/ierc20"
eth_node_types "github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/protocol/communities/token"
"github.com/status-im/status-go/rpc"
"github.com/status-im/status-go/rpc/chain"
"github.com/status-im/status-go/rpc/network"
"github.com/status-im/status-go/services/communitytokens"
"github.com/status-im/status-go/services/utils"
"github.com/status-im/status-go/services/wallet/async"
)
@ -42,10 +44,18 @@ type Token struct {
// ISO 4217 alphabetic code. For example, an empty string means it is not
// pegged, while "USD" means it's pegged to the United States Dollar.
PegSymbol string `json:"pegSymbol"`
Image string `json:"image,omitempty"`
CommunityID *string `json:"communityId,omitempty"`
Verified bool `json:"verified"`
TokenListID string `json:"tokenListId"`
CommunityData *CommunityData `json:"community_data,omitempty"`
Verified bool `json:"verified"`
TokenListID string `json:"tokenListId"`
}
type CommunityData struct {
ID string `json:"id"`
Name string `json:"name"`
Color string `json:"color"`
ImageURL *string `json:"image_url,omitempty"`
}
func (t *Token) IsNative() bool {
@ -70,11 +80,12 @@ type ManagerInterface interface {
// Manager is used for accessing token store. It changes the token store based on overridden tokens
type Manager struct {
db *sql.DB
RPCClient *rpc.Client
contractMaker *contracts.ContractMaker
networkManager *network.Manager
stores []store // Set on init, not changed afterwards
db *sql.DB
RPCClient *rpc.Client
contractMaker *contracts.ContractMaker
networkManager *network.Manager
stores []store // Set on init, not changed afterwards
communityTokensDB *communitytokens.Database
tokens []*Token
@ -100,6 +111,7 @@ func NewTokenManager(
db *sql.DB,
RPCClient *rpc.Client,
networkManager *network.Manager,
appDB *sql.DB,
) *Manager {
maker, _ := contracts.NewContractMaker(RPCClient)
stores := []store{newUniswapStore(), newDefaultStore()}
@ -127,12 +139,13 @@ func NewTokenManager(
}
return &Manager{
db: db,
RPCClient: RPCClient,
contractMaker: maker,
networkManager: networkManager,
stores: stores,
tokens: tokens,
db: db,
RPCClient: RPCClient,
contractMaker: maker,
networkManager: networkManager,
stores: stores,
communityTokensDB: communitytokens.NewCommunityTokensDatabase(appDB),
tokens: tokens,
}
}
@ -277,7 +290,7 @@ func (tm *Manager) FindOrCreateTokenByAddress(ctx context.Context, chainID uint6
}
func (tm *Manager) discoverTokenCommunityID(ctx context.Context, token *Token, address common.Address) {
if token == nil || token.CommunityID != nil {
if token == nil || token.CommunityData != nil {
// Token is invalid or is alrady discovered. Nothing to do here.
return
}
@ -482,6 +495,13 @@ func (tm *Manager) DiscoverToken(ctx context.Context, chainID uint64, address co
}
func (tm *Manager) getTokensFromDB(query string, args ...any) ([]*Token, error) {
communityTokens := []*token.CommunityToken{}
if tm.communityTokensDB != nil {
// Error is skipped because it's only returning optional metadata
communityTokens, _ = tm.communityTokensDB.GetCommunityERC20Metadata()
}
rows, err := tm.db.Query(query, args...)
if err != nil {
return nil, err
@ -498,7 +518,18 @@ func (tm *Manager) getTokensFromDB(query string, args ...any) ([]*Token, error)
}
if communityIDDB.Valid {
token.CommunityID = &communityIDDB.String
communityID := communityIDDB.String
for _, communityToken := range communityTokens {
if communityToken.CommunityID != communityID || uint64(communityToken.ChainID) != token.ChainID || communityToken.Symbol != token.Symbol {
continue
}
token.Image = communityToken.Base64Image
break
}
token.CommunityData = &CommunityData{
ID: communityID,
}
}
rst = append(rst, token)

View File

@ -17,16 +17,28 @@ func setupTestTokenDB(t *testing.T) (*Manager, func()) {
require.NoError(t, err)
return &Manager{
db: db,
RPCClient: nil,
contractMaker: nil,
networkManager: nil,
stores: nil,
db: db,
RPCClient: nil,
contractMaker: nil,
networkManager: nil,
stores: nil,
communityTokensDB: nil,
}, func() {
require.NoError(t, db.Close())
}
}
func upsertCommunityToken(t *testing.T, token *Token, manager *Manager) {
require.NotNil(t, token.CommunityData)
err := manager.UpsertCustom(*token)
require.NoError(t, err)
// Community ID is only discovered by calling contract, so must be updated manually
_, err = manager.db.Exec("UPDATE tokens SET community_id = ? WHERE address = ?", token.CommunityData.ID, token.Address)
require.NoError(t, err)
}
func TestCustoms(t *testing.T) {
manager, stop := setupTestTokenDB(t)
defer stop()
@ -59,6 +71,50 @@ func TestCustoms(t *testing.T) {
require.Equal(t, 0, len(rst))
}
func TestCommunityTokens(t *testing.T) {
manager, stop := setupTestTokenDB(t)
defer stop()
rst, err := manager.GetCustoms(true)
require.NoError(t, err)
require.Nil(t, rst)
token := Token{
Address: common.Address{1},
Name: "Zilliqa",
Symbol: "ZIL",
Decimals: 12,
ChainID: 777,
}
err = manager.UpsertCustom(token)
require.NoError(t, err)
communityToken := Token{
Address: common.Address{2},
Name: "Communitia",
Symbol: "COM",
Decimals: 12,
ChainID: 777,
CommunityData: &CommunityData{
ID: "random_community_id",
},
}
upsertCommunityToken(t, &communityToken, manager)
rst, err = manager.GetCustoms(false)
require.NoError(t, err)
require.Equal(t, 2, len(rst))
require.Equal(t, token, *rst[0])
require.Equal(t, communityToken, *rst[1])
rst, err = manager.GetCustoms(true)
require.NoError(t, err)
require.Equal(t, 1, len(rst))
require.Equal(t, communityToken, *rst[0])
}
func toTokenMap(tokens []*Token) storeMap {
tokenMap := storeMap{}

View File

@ -930,7 +930,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(appdb))
tokenManager := token.NewTokenManager(db, client, network.NewManager(appdb), appdb)
tokenManager.SetTokens([]*token.Token{
{
Address: tokenTXXAddress,
@ -1052,7 +1052,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(appdb))
tokenManager := token.NewTokenManager(db, client, network.NewManager(appdb), appdb)
tokenManager.SetTokens([]*token.Token{
{
@ -1169,7 +1169,7 @@ func TestFetchNewBlocksCommand_findBlocksWithEthTransfers(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(appdb))
tokenManager := token.NewTokenManager(db, client, network.NewManager(appdb), appdb)
tokenManager.SetTokens([]*token.Token{
{
@ -1243,7 +1243,7 @@ func TestFetchNewBlocksCommand(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(appdb))
tokenManager := token.NewTokenManager(db, client, network.NewManager(appdb), appdb)
tokenManager.SetTokens([]*token.Token{
{