feat: Fetch community data for tokens (#4497)

This commit is contained in:
Cuteivist 2023-12-22 10:43:19 +01:00 committed by GitHub
parent 54f3cf8af0
commit dac7a0daf9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 84 additions and 24 deletions

View File

@ -455,7 +455,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, community.NewManager(database, c.httpServer), c.rpcClient.NetworkManager, database, c.httpServer)
tokenManager := token.NewTokenManager(c.walletDb, c.rpcClient, community.NewManager(database, c.httpServer, nil), c.rpcClient.NetworkManager, database, c.httpServer)
managerOptions = append(managerOptions, communities.WithTokenManager(communities.NewDefaultTokenManager(tokenManager)))
}

View File

@ -2,22 +2,39 @@ package community
import (
"database/sql"
"encoding/json"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/status-im/status-go/server"
"github.com/status-im/status-go/services/wallet/thirdparty"
"github.com/status-im/status-go/services/wallet/walletevent"
)
// These events are used to notify the UI of state changes
const (
EventCommmunityDataUpdated walletevent.EventType = "wallet-community-data-updated"
)
type Manager struct {
db *DataDB
communityInfoProvider thirdparty.CommunityInfoProvider
mediaServer *server.MediaServer
feed *event.Feed
}
func NewManager(db *sql.DB, mediaServer *server.MediaServer) *Manager {
type Data struct {
ID string `json:"id"`
Name string `json:"name"`
Color string `json:"color"`
Image string `json:"image,omitempty"`
}
func NewManager(db *sql.DB, mediaServer *server.MediaServer, feed *event.Feed) *Manager {
return &Manager{
db: NewDataDB(db),
mediaServer: mediaServer,
feed: feed,
}
}
@ -58,7 +75,43 @@ func (cm *Manager) FetchCommunityInfo(communityID string) (*thirdparty.Community
}
return nil, err
}
err = cm.setCommunityInfo(communityID, communityInfo)
return communityInfo, err
}
func (cm *Manager) FetchCommunityMetadataAsync(communityID string) {
go func() {
communityInfo, err := cm.FetchCommunityInfo(communityID)
if err != nil {
log.Error("FetchCommunityInfo failed", "communityID", communityID, "err", err)
return
}
cm.signalUpdatedCommunityMetadata(communityID, communityInfo)
}()
}
func (cm *Manager) signalUpdatedCommunityMetadata(communityID string, communityInfo *thirdparty.CommunityInfo) {
if communityInfo == nil {
return
}
data := Data{
ID: communityID,
Name: communityInfo.CommunityName,
Color: communityInfo.CommunityColor,
Image: communityInfo.CommunityImage, // TODO make media server url after merging community token media server changes
}
payload, err := json.Marshal(data)
if err != nil {
log.Error("Error marshaling response: %v", err)
return
}
event := walletevent.Event{
Type: EventCommmunityDataUpdated,
Message: string(payload),
}
cm.feed.Send(event)
}

View File

@ -14,6 +14,7 @@ import (
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/rpc"
"github.com/status-im/status-go/services/wallet/async"
"github.com/status-im/status-go/services/wallet/community"
"github.com/status-im/status-go/services/wallet/market"
"github.com/status-im/status-go/services/wallet/thirdparty"
"github.com/status-im/status-go/services/wallet/transfer"
@ -46,11 +47,12 @@ func belongsToMandatoryTokens(symbol string) bool {
return false
}
func NewReader(rpcClient *rpc.Client, tokenManager *token.Manager, marketManager *market.Manager, accountsDB *accounts.Database, persistence *Persistence, walletFeed *event.Feed) *Reader {
func NewReader(rpcClient *rpc.Client, tokenManager *token.Manager, marketManager *market.Manager, communityManager *community.Manager, accountsDB *accounts.Database, persistence *Persistence, walletFeed *event.Feed) *Reader {
return &Reader{
rpcClient: rpcClient,
tokenManager: tokenManager,
marketManager: marketManager,
communityManager: communityManager,
accountsDB: accountsDB,
persistence: persistence,
walletFeed: walletFeed,
@ -62,6 +64,7 @@ type Reader struct {
rpcClient *rpc.Client
tokenManager *token.Manager
marketManager *market.Manager
communityManager *community.Manager
accountsDB *accounts.Database
persistence *Persistence
walletFeed *event.Feed
@ -103,7 +106,7 @@ type Token struct {
PegSymbol string `json:"pegSymbol"`
Verified bool `json:"verified"`
Image string `json:"image,omitempty"`
CommunityData *token.CommunityData `json:"community_data,omitempty"`
CommunityData *community.Data `json:"community_data,omitempty"`
}
func splitVerifiedTokens(tokens []*token.Token) ([]*token.Token, []*token.Token) {
@ -389,6 +392,8 @@ func (r *Reader) GetWalletToken(ctx context.Context, addresses []common.Address)
return nil, err
}
communities := make(map[string]bool)
for address, tokens := range result {
for index, token := range tokens {
marketValuesPerCurrency := make(map[string]TokenMarketValues)
@ -409,6 +414,10 @@ func (r *Reader) GetWalletToken(ctx context.Context, addresses []common.Address)
}
}
if token.CommunityData != nil {
communities[token.CommunityData.ID] = true
}
if _, ok := tokenDetails[token.Symbol]; !ok {
continue
}
@ -422,6 +431,10 @@ func (r *Reader) GetWalletToken(ctx context.Context, addresses []common.Address)
r.lastWalletTokenUpdateTimestamp.Store(time.Now().Unix())
for communityID := range communities {
r.communityManager.FetchCommunityMetadataAsync(communityID)
}
return result, r.persistence.SaveTokens(result)
}

View File

@ -99,7 +99,7 @@ func NewService(
})
})
communityManager := community.NewManager(db, mediaServer)
communityManager := community.NewManager(db, mediaServer, feed)
balanceCacher := balance.NewCacherWithTTL(5 * time.Minute)
tokenManager := token.NewTokenManager(db, rpcClient, communityManager, rpcClient.NetworkManager, appDB, mediaServer)
savedAddressesManager := &SavedAddressesManager{db: db}
@ -110,7 +110,7 @@ func NewService(
cryptoCompare := cryptocompare.NewClient()
coingecko := coingecko.NewClient()
marketManager := market.NewManager(cryptoCompare, coingecko, feed)
reader := NewReader(rpcClient, tokenManager, marketManager, accountsDB, NewPersistence(db), feed)
reader := NewReader(rpcClient, tokenManager, marketManager, communityManager, accountsDB, NewPersistence(db), feed)
history := history.NewService(db, accountsDB, feed, rpcClient, tokenManager, marketManager, balanceCacher.Cache())
currency := currency.NewService(db, feed, tokenManager, marketManager)
blockChainState := NewBlockChainState(rpcClient, accountsDB)

View File

@ -49,16 +49,9 @@ type Token struct {
PegSymbol string `json:"pegSymbol"`
Image string `json:"image,omitempty"`
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"`
Image string `json:"image,omitempty"`
CommunityData *community.Data `json:"community_data,omitempty"`
Verified bool `json:"verified"`
TokenListID string `json:"tokenListId"`
}
func (t *Token) IsNative() bool {
@ -551,7 +544,7 @@ func (tm *Manager) getTokensFromDB(query string, args ...any) ([]*Token, error)
break
}
token.CommunityData = &CommunityData{
token.CommunityData = &community.Data{
ID: communityID,
}
}

View File

@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/services/wallet/community"
"github.com/status-im/status-go/t/helpers"
"github.com/status-im/status-go/walletdatabase"
)
@ -97,7 +98,7 @@ func TestCommunityTokens(t *testing.T) {
Symbol: "COM",
Decimals: 12,
ChainID: 777,
CommunityData: &CommunityData{
CommunityData: &community.Data{
ID: "random_community_id",
},
}

View File

@ -937,7 +937,8 @@ 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, community.NewManager(appdb, nil), network.NewManager(appdb), appdb, mediaServer)
tokenManager := token.NewTokenManager(db, client, community.NewManager(appdb, nil, nil), network.NewManager(appdb), appdb, mediaServer)
tokenManager.SetTokens([]*token.Token{
{
Address: tokenTXXAddress,
@ -1062,7 +1063,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, community.NewManager(appdb, nil), network.NewManager(appdb), appdb, mediaServer)
tokenManager := token.NewTokenManager(db, client, community.NewManager(appdb, nil, nil), network.NewManager(appdb), appdb, mediaServer)
tokenManager.SetTokens([]*token.Token{
{
@ -1182,7 +1183,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, community.NewManager(appdb, nil), network.NewManager(appdb), appdb, mediaServer)
tokenManager := token.NewTokenManager(db, client, community.NewManager(appdb, nil, nil), network.NewManager(appdb), appdb, mediaServer)
tokenManager.SetTokens([]*token.Token{
{
@ -1259,8 +1260,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, community.NewManager(appdb, nil), network.NewManager(appdb), appdb, mediaServer)
tokenManager := token.NewTokenManager(db, client, community.NewManager(appdb, nil, nil), network.NewManager(appdb), appdb, mediaServer)
tokenManager.SetTokens([]*token.Token{
{