diff --git a/node/status_node_services.go b/node/status_node_services.go index 4af8760c8..fc2e0e9aa 100644 --- a/node/status_node_services.go +++ b/node/status_node_services.go @@ -45,6 +45,7 @@ import ( "github.com/status-im/status-go/services/wakuext" "github.com/status-im/status-go/services/wakuv2ext" "github.com/status-im/status-go/services/wallet" + "github.com/status-im/status-go/services/wallet/thirdparty" "github.com/status-im/status-go/services/web3provider" "github.com/status-im/status-go/timesource" "github.com/status-im/status-go/waku" @@ -88,6 +89,19 @@ func (b *StatusNode) initServices(config *params.NodeConfig, mediaServer *server services = append(services, b.gifService(accDB)) services = append(services, b.ChatService(accDB)) + // Wallet Service is used by wakuExtSrvc/wakuV2ExtSrvc + // Keep this initialization before the other two + if config.WalletConfig.Enabled { + walletService := b.walletService(accDB, accountsFeed) + services = append(services, walletService) + } + + // CollectiblesManager needs the WakuExt service to get metadata for + // Community collectibles. + // Messenger needs the CollectiblesManager to get the list of collectibles owned + // by a certain account and check community entry permissions. + // We handle circular dependency between the two by delaying ininitalization of the CollectibleMetadataProvider + // in the CollectiblesManager. if config.WakuConfig.Enabled { wakuService, err := b.wakuService(&config.WakuConfig, &config.ClusterConfig) if err != nil { @@ -104,6 +118,8 @@ func (b *StatusNode) initServices(config *params.NodeConfig, mediaServer *server b.wakuExtSrvc = wakuext services = append(services, wakuext) + + b.SetWalletNFTMetadataProvider(wakuext) } if config.WakuV2Config.Enabled { @@ -129,13 +145,8 @@ func (b *StatusNode) initServices(config *params.NodeConfig, mediaServer *server b.wakuV2ExtSrvc = wakuext services = append(services, wakuext) - } - // Wallet Service makes use of wakuExtSrvc/wakuV2ExtSrvc - // Keep this initialization below the other two - if config.WalletConfig.Enabled { - walletService := b.walletService(accDB, accountsFeed) - services = append(services, walletService) + b.SetWalletNFTMetadataProvider(wakuext) } // We ignore for now local notifications flag as users who are upgrading have no mean to enable it @@ -477,20 +488,19 @@ func (b *StatusNode) WalletService() *wallet.Service { return b.walletSrvc } +func (b *StatusNode) SetWalletNFTMetadataProvider(provider thirdparty.NFTMetadataProvider) { + if b.walletSrvc != nil { + b.walletSrvc.SetNFTMetadataProvider(provider) + } +} + func (b *StatusNode) walletService(accountsDB *accounts.Database, accountsFeed *event.Feed) *wallet.Service { if b.walletSrvc == nil { - var extService *ext.Service - if b.WakuV2ExtService() != nil { - extService = b.WakuV2ExtService().Service - } else if b.WakuExtService() != nil { - extService = b.WakuExtService().Service - } b.walletSrvc = wallet.NewService( b.appDB, accountsDB, b.rpcClient, accountsFeed, b.gethAccountManager, b.transactor, b.config, b.ensService(b.timeSourceNow()), b.stickersService(accountsDB), b.rpcFiltersSrvc, - extService, ) } return b.walletSrvc diff --git a/services/wallet/collectibles/collectibles.go b/services/wallet/collectibles/collectibles.go index 61f89e752..6f23d1f2c 100644 --- a/services/wallet/collectibles/collectibles.go +++ b/services/wallet/collectibles/collectibles.go @@ -42,7 +42,7 @@ type Manager struct { walletFeed *event.Feed } -func NewManager(rpcClient *rpc.Client, mainContractOwnershipProvider thirdparty.NFTContractOwnershipProvider, fallbackContractOwnershipProvider thirdparty.NFTContractOwnershipProvider, metadataProvider thirdparty.NFTMetadataProvider, openseaAPIKey string, walletFeed *event.Feed) *Manager { +func NewManager(rpcClient *rpc.Client, mainContractOwnershipProvider thirdparty.NFTContractOwnershipProvider, fallbackContractOwnershipProvider thirdparty.NFTContractOwnershipProvider, openseaAPIKey string, walletFeed *event.Feed) *Manager { hystrix.ConfigureCommand(hystrixContractOwnershipClientName, hystrix.CommandConfig{ Timeout: 10000, MaxConcurrentRequests: 100, @@ -54,7 +54,6 @@ func NewManager(rpcClient *rpc.Client, mainContractOwnershipProvider thirdparty. rpcClient: rpcClient, mainContractOwnershipProvider: mainContractOwnershipProvider, fallbackContractOwnershipProvider: fallbackContractOwnershipProvider, - metadataProvider: metadataProvider, openseaAPIKey: openseaAPIKey, nftCache: make(map[uint64]map[string]opensea.Asset), walletFeed: walletFeed, @@ -90,6 +89,11 @@ func makeContractOwnershipCall(main func() (any, error), fallback func() (any, e } } +// Used to break circular dependency, call once as soon as possible after initialization +func (o *Manager) SetMetadataProvider(metadataProvider thirdparty.NFTMetadataProvider) { + o.metadataProvider = metadataProvider +} + func (o *Manager) FetchAllCollectionsByOwner(chainID uint64, owner common.Address) ([]opensea.OwnedCollection, error) { client, err := opensea.NewOpenseaClient(chainID, o.openseaAPIKey, o.walletFeed) if err != nil { diff --git a/services/wallet/service.go b/services/wallet/service.go index e4061ad75..17d863fba 100644 --- a/services/wallet/service.go +++ b/services/wallet/service.go @@ -51,7 +51,6 @@ func NewService( ens *ens.Service, stickers *stickers.Service, rpcFilterSrvc *rpcfilters.Service, - nftMetadataProvider thirdparty.NFTMetadataProvider, ) *Service { cryptoOnRampManager := NewCryptoOnRampManager(&CryptoOnRampOptions{ dataSourceType: DataSourceStatic, @@ -107,7 +106,7 @@ func NewService( alchemyClient := alchemy.NewClient(config.WalletConfig.AlchemyAPIKeys) infuraClient := infura.NewClient(config.WalletConfig.InfuraAPIKey, config.WalletConfig.InfuraAPIKeySecret) - collectiblesManager := collectibles.NewManager(rpcClient, alchemyClient, infuraClient, nftMetadataProvider, config.WalletConfig.OpenseaAPIKey, walletFeed) + collectiblesManager := collectibles.NewManager(rpcClient, alchemyClient, infuraClient, config.WalletConfig.OpenseaAPIKey, walletFeed) return &Service{ db: db, accountsDB: accountsDB, @@ -181,6 +180,11 @@ func (s *Service) GetFeed() *event.Feed { return s.transferController.TransferFeed } +// Set external Collectibles metadata provider +func (s *Service) SetNFTMetadataProvider(provider thirdparty.NFTMetadataProvider) { + s.collectiblesManager.SetMetadataProvider(provider) +} + // Stop reactor and close db. func (s *Service) Stop() error { log.Info("wallet will be stopped")