Files

504 lines
15 KiB
Go
Raw Permalink Normal View History

2021-06-30 13:40:54 +02:00
package node
import (
2023-12-12 08:37:57 +01:00
"database/sql"
2021-06-30 13:40:54 +02:00
"errors"
2023-04-26 23:37:18 +08:00
"time"
2021-06-30 13:40:54 +02:00
"go.uber.org/zap"
"github.com/status-im/status-go/internal/db/multiaccounts/accounts"
2025-10-16 17:36:49 +01:00
"github.com/status-im/status-go/internal/timesource"
nodeadapters "github.com/status-im/status-go/pkg/backend/node/adapters"
"github.com/status-im/status-go/pkg/featureflags"
2025-06-26 10:06:15 -03:00
"github.com/status-im/status-go/pkg/pubsub"
2026-08-20 21:44:51 +01:00
"github.com/status-im/status-go/pkg/services/eth"
"github.com/status-im/status-go/pkg/services/linkpreview"
"github.com/status-im/status-go/pkg/services/newsfeed"
"github.com/status-im/status-go/pkg/services/sharedurls"
2022-06-25 15:20:02 +08:00
2021-06-30 13:40:54 +02:00
"github.com/ethereum/go-ethereum/event"
"github.com/status-im/status-go/params"
2026-08-20 21:44:51 +01:00
accountssvc "github.com/status-im/status-go/pkg/services/accounts"
appgeneral "github.com/status-im/status-go/pkg/services/app-general"
"github.com/status-im/status-go/pkg/services/browsers"
"github.com/status-im/status-go/pkg/services/chat"
"github.com/status-im/status-go/pkg/services/communitytokens"
"github.com/status-im/status-go/pkg/services/connector"
"github.com/status-im/status-go/pkg/services/ens"
"github.com/status-im/status-go/pkg/services/gif"
localnotifications "github.com/status-im/status-go/pkg/services/local-notifications"
"github.com/status-im/status-go/pkg/services/media"
"github.com/status-im/status-go/pkg/services/networks"
2026-08-20 21:44:51 +01:00
"github.com/status-im/status-go/pkg/services/permissions"
"github.com/status-im/status-go/pkg/services/personal"
"github.com/status-im/status-go/pkg/services/preferences"
"github.com/status-im/status-go/pkg/services/rpcstats"
"github.com/status-im/status-go/pkg/services/stickers"
"github.com/status-im/status-go/pkg/services/storagestats"
2026-08-20 21:44:51 +01:00
"github.com/status-im/status-go/pkg/services/updates"
"github.com/status-im/status-go/pkg/services/wakuv2ext"
"github.com/status-im/status-go/pkg/services/wallet"
"github.com/status-im/status-go/pkg/services/wallet/pendingtxtracker"
"github.com/status-im/status-go/pkg/services/wallet/router/fees"
"github.com/status-im/status-go/pkg/services/wallet/thirdparty"
2021-06-30 13:40:54 +02:00
)
var (
// ErrWakuClearIdentitiesFailure clearing whisper identities has failed.
ErrWakuClearIdentitiesFailure = errors.New("failed to clear waku identities")
// ErrRPCClientUnavailable is returned if an RPC client can't be retrieved.
// This is a normal situation when a node is stopped.
ErrRPCClientUnavailable = errors.New("JSON-RPC client is unavailable")
2021-06-30 13:40:54 +02:00
)
func (b *StatusNode) ThirdpartyServicesEnabled() (bool, error) {
accDB, err := accounts.NewDB(b.appDB)
if err != nil {
b.logger.Error("failed to create accounts db", zap.Error(err))
return true, err
}
enabled, err := accDB.ThirdpartyServicesEnabled()
if err != nil {
return true, err
}
return enabled, nil
}
2026-08-19 20:50:03 +01:00
func (b *StatusNode) initServices(config *params.NodeConfig, mediaServer *media.Server) error {
2022-03-23 18:47:00 +00:00
accDB, err := accounts.NewDB(b.appDB)
if err != nil {
return err
}
2023-12-12 08:37:57 +01:00
2026-08-19 20:49:00 +01:00
services := []StatusService{}
2021-06-30 13:40:54 +02:00
services = append(services, b.rpcStatsService())
services = append(services, b.networksService())
services = append(services, b.appgeneralService())
2021-06-30 13:40:54 +02:00
services = append(services, b.personalService())
services = append(services, b.pendingTrackerService(&b.walletFeed))
2023-04-26 23:37:18 +08:00
services = append(services, b.ensService(b.timeSourceNow()))
services = append(services, b.CommunityTokensService())
2022-03-23 18:47:00 +00:00
services = append(services, b.stickersService(accDB))
services = append(services, b.updatesService())
2025-06-26 10:06:15 -03:00
services = appendIf(b.appDB != nil && b.multiaccountsDB != nil, services, b.accountsService(accDB, mediaServer))
2021-06-30 13:40:54 +02:00
services = appendIf(config.BrowsersConfig.Enabled, services, b.browsersService())
services = appendIf(config.PermissionsConfig.Enabled, services, b.permissionsService())
services = appendIf(b.appDB != nil, services, b.preferencesService())
services = appendIf(b.appDB != nil, services, b.storageStatsService())
services = appendIf(config.ConnectorConfig.Enabled, services, b.connectorService())
2022-03-23 18:47:00 +00:00
services = append(services, b.gifService(accDB))
services = append(services, b.ChatService(accDB))
services = append(services, b.ethService())
2021-12-21 15:44:37 +00:00
// Wallet Service is used by wakuExtSrvc/wakuV2ExtSrvc
// Keep this initialization before the other two
if config.WalletConfig.Enabled {
2026-05-29 20:12:18 +04:00
err := b.createWalletService(accDB, b.appDB, b.accountsPublisher, &b.walletFeed)
if err != nil {
return err
}
services = append(services, b.walletSrvc)
}
// 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.
2023-10-26 03:30:18 -03:00
// We handle circular dependency between the two by delaying ininitalization of the CommunityCollectibleInfoProvider
// in the CollectiblesManager.
2021-06-30 13:40:54 +02:00
if config.WakuV2Config.Enabled {
wakuext, err := b.wakuV2ExtService(config)
if err != nil {
return err
}
b.wakuV2ExtSrvc = wakuext
services = append(services, wakuext)
b.SetWalletCommunityInfoProvider(wakuext)
}
2021-06-30 13:40:54 +02:00
// We ignore for now local notifications flag as users who are upgrading have no mean to enable it
2022-03-23 18:47:00 +00:00
lns, err := b.localNotificationsService(config.NetworkID)
if err != nil {
return err
}
services = append(services, lns)
2021-06-30 13:40:54 +02:00
if b.NewsFeedService() != nil {
services = append(services, b.NewsFeedService())
}
services = append(services, b.sharedUrlsService())
services = append(services, b.linkPreviewService(accDB))
b.services = services
return nil
}
func (b *StatusNode) runServicesMigrations() error {
err := newsfeed.SQLiteMigrate(b.appDB)
if err != nil {
return err
}
return nil
}
2026-08-19 20:49:00 +01:00
func (b *StatusNode) registerService(s StatusService) error {
for _, api := range s.APIs() {
b.logger.Debug("registering service api", zap.String("namespace", api.Namespace))
err := b.rpcServer.RegisterName(api.Namespace, api.Service)
if err != nil {
b.logger.Error("Failed to register API", zap.String("namespace", api.Namespace), zap.Error(err))
return err
}
2021-06-30 13:40:54 +02:00
}
return nil
}
func (b *StatusNode) wakuV2ExtService(config *params.NodeConfig) (*wakuv2ext.Service, error) {
if b.wakuV2ExtSrvc == nil {
b.wakuV2ExtSrvc = wakuv2ext.New(*config, b.rpcClient, b.logger.Named("protocol"))
2021-06-30 13:40:54 +02:00
}
return b.wakuV2ExtSrvc, nil
}
2022-07-06 19:12:49 +03:00
func (b *StatusNode) AccountService() *accountssvc.Service {
return b.accountsSrvc
}
func (b *StatusNode) BrowserService() *browsers.Service {
return b.browsersSrvc
}
2023-04-26 23:37:18 +08:00
func (b *StatusNode) EnsService() *ens.Service {
return b.ensSrvc
}
2021-06-30 13:40:54 +02:00
func (b *StatusNode) WakuV2ExtService() *wakuv2ext.Service {
return b.wakuV2ExtSrvc
}
func (b *StatusNode) connectorService() *connector.Service {
if b.connectorSrvc == nil {
logger := b.logger.Named("connector")
2026-02-16 22:01:11 +04:00
b.connectorSrvc = connector.NewService(
logger,
b.walletDB,
b.rpcClient,
fees.NewFeeManager(b.rpcClient, logger.Named("feeManager")),
b.networkManager,
&connector.Config{
WSEnabled: b.config.WSEnabled,
2026-02-16 22:01:11 +04:00
WSHost: b.config.WSHost,
WSPort: b.config.WSPort,
ProjectID: b.config.WalletConnectProjectID,
},
)
}
return b.connectorSrvc
}
func (b *StatusNode) networksService() *networks.Service {
if b.networksSrvc == nil {
b.networksSrvc = networks.NewService(b.networkManager)
}
return b.networksSrvc
}
2021-06-30 13:40:54 +02:00
func (b *StatusNode) rpcStatsService() *rpcstats.Service {
if b.rpcStatsSrvc == nil {
b.rpcStatsSrvc = rpcstats.New()
}
return b.rpcStatsSrvc
}
2026-08-19 20:50:03 +01:00
func (b *StatusNode) accountsService(accDB *accounts.Database, mediaServer *media.Server) *accountssvc.Service {
2021-06-30 13:40:54 +02:00
if b.accountsSrvc == nil {
b.accountsSrvc = accountssvc.NewService(
2022-03-23 18:47:00 +00:00
accDB,
b.multiaccountsDB,
b.gethAccountsManager,
b.config,
2025-06-17 01:02:34 -03:00
b.accountsPublisher,
2022-06-25 15:20:02 +08:00
mediaServer,
b.logger.Named("AccountsService"),
)
2021-06-30 13:40:54 +02:00
}
return b.accountsSrvc
}
func (b *StatusNode) browsersService() *browsers.Service {
if b.browsersSrvc == nil {
b.browsersSrvc = browsers.NewService(browsers.NewDB(b.appDB))
}
return b.browsersSrvc
}
2023-04-26 23:37:18 +08:00
func (b *StatusNode) ensService(timesource func() time.Time) *ens.Service {
2021-12-21 16:05:09 +01:00
if b.ensSrvc == nil {
b.ensSrvc = ens.NewService(b.rpcClient, b.gethAccountsManager, b.pendingTracker, b.config, b.appDB, timesource)
2021-12-21 16:05:09 +01:00
}
return b.ensSrvc
}
func (b *StatusNode) pendingTrackerService(walletFeed *event.Feed) *pendingtxtracker.PendingTxTracker {
if b.pendingTracker == nil {
b.pendingTracker = pendingtxtracker.NewPendingTxTracker(b.walletDB, pendingtxtracker.NewBatchTxStatusFetcher(b.rpcClient, b.logger.Named("PendingTxTracker")), walletFeed, pendingtxtracker.PendingCheckInterval)
if b.transactor != nil {
b.transactor.SetPendingTracker(b.pendingTracker)
}
}
return b.pendingTracker
}
func (b *StatusNode) CommunityTokensService() *communitytokens.Service {
if b.communityTokensSrvc == nil {
b.communityTokensSrvc = communitytokens.NewService(b.rpcClient, b.gethAccountsManager, b.config, b.appDB, &b.walletFeed, b.transactor)
}
return b.communityTokensSrvc
}
2022-03-23 18:47:00 +00:00
func (b *StatusNode) stickersService(accountDB *accounts.Database) *stickers.Service {
2022-02-02 18:50:55 -04:00
if b.stickersSrvc == nil {
2025-09-10 10:19:04 +01:00
b.stickersSrvc = stickers.NewService(accountDB, b.rpcClient, b.gethAccountsManager, b.config, b.downloader, b.mediaServer, b.pendingTracker)
2022-02-02 18:50:55 -04:00
}
return b.stickersSrvc
}
func (b *StatusNode) updatesService() *updates.Service {
if b.updatesSrvc == nil {
2023-04-26 23:37:18 +08:00
b.updatesSrvc = updates.NewService(b.ensService(b.timeSourceNow()))
}
return b.updatesSrvc
}
2022-03-23 18:47:00 +00:00
func (b *StatusNode) gifService(accountsDB *accounts.Database) *gif.Service {
2022-01-31 13:58:03 +01:00
if b.gifSrvc == nil {
2022-03-23 18:47:00 +00:00
b.gifSrvc = gif.NewService(accountsDB)
2022-01-31 13:58:03 +01:00
}
return b.gifSrvc
}
2022-03-23 18:47:00 +00:00
func (b *StatusNode) ChatService(accountsDB *accounts.Database) *chat.Service {
2022-02-10 11:15:27 -04:00
if b.chatSrvc == nil {
2022-03-23 18:47:00 +00:00
b.chatSrvc = chat.NewService(accountsDB)
2022-02-10 11:15:27 -04:00
}
return b.chatSrvc
}
2021-06-30 13:40:54 +02:00
func (b *StatusNode) permissionsService() *permissions.Service {
if b.permissionsSrvc == nil {
b.permissionsSrvc = permissions.NewService(permissions.NewDB(b.appDB))
}
return b.permissionsSrvc
}
func (b *StatusNode) preferencesService() *preferences.Service {
if b.preferencesSrvc == nil {
b.preferencesSrvc = preferences.NewService(b.appDB)
}
return b.preferencesSrvc
}
func (b *StatusNode) appgeneralService() *appgeneral.Service {
if b.appGeneralSrvc == nil {
b.appGeneralSrvc = appgeneral.New()
}
return b.appGeneralSrvc
}
func (b *StatusNode) storageStatsService() *storagestats.Service {
if b.storageStatsSrvc == nil {
b.storageStatsSrvc = storagestats.New(b.appDB, b.walletDB, b.logger)
}
return b.storageStatsSrvc
}
2023-04-25 13:00:17 +01:00
func (b *StatusNode) WalletService() *wallet.Service {
return b.walletSrvc
}
2025-06-26 10:06:15 -03:00
func (b *StatusNode) AccountsPublisher() *pubsub.Publisher {
return b.accountsPublisher
}
func (b *StatusNode) SetWalletCommunityInfoProvider(provider thirdparty.CommunityInfoProvider) {
if b.walletSrvc != nil {
b.walletSrvc.SetWalletCommunityInfoProvider(provider)
}
}
2026-05-29 20:12:18 +04:00
func (b *StatusNode) createWalletService(accountsDB *accounts.Database, appDB *sql.DB, accountsPublisher *pubsub.Publisher, walletFeed *event.Feed) (err error) {
2021-06-30 13:40:54 +02:00
if b.walletSrvc == nil {
b.walletSrvc, err = wallet.NewService(
b.walletDB, accountsDB, appDB, b.rpcClient, accountsPublisher, b.gethAccountsManager, b.transactor, b.config,
b.ensService(b.timeSourceNow()).API().EnsResolver(),
b.pendingTracker,
walletFeed,
2025-09-10 10:19:04 +01:00
b.mediaServer,
b.tokenManager,
2022-09-13 09:10:59 +02:00
)
2021-06-30 13:40:54 +02:00
}
return
2021-06-30 13:40:54 +02:00
}
func (b *StatusNode) ethService() *eth.Service {
if b.ethSrvc == nil {
b.ethSrvc = eth.NewService(b.rpcClient, b.gethAccountsManager)
}
return b.ethSrvc
}
func (b *StatusNode) sharedUrlsService() *sharedurls.Service {
if b.sharedUrlsSrvc == nil {
b.sharedUrlsSrvc = sharedurls.NewService(nil)
if extService := b.WakuV2ExtService(); extService != nil {
provider := nodeadapters.NewSharedUrlsMessengerAdapter(extService.Messenger())
b.sharedUrlsSrvc.SetDataProvider(provider)
}
}
return b.sharedUrlsSrvc
}
func (b *StatusNode) SharedUrlsService() *sharedurls.Service {
return b.sharedUrlsSrvc
}
func (b *StatusNode) linkPreviewService(accDB *accounts.Database) *linkpreview.Service {
if b.linkPreviewSrvc == nil {
settingsProvider := nodeadapters.NewLinkPreviewSettingsAdapter(accDB)
b.linkPreviewSrvc = linkpreview.NewService(b.logger.Named("linkpreview"), settingsProvider, nil)
}
return b.linkPreviewSrvc
}
func (b *StatusNode) LinkPreviewService() *linkpreview.Service {
return b.linkPreviewSrvc
}
2022-03-23 18:47:00 +00:00
func (b *StatusNode) localNotificationsService(network uint64) (*localnotifications.Service, error) {
var err error
2021-06-30 13:40:54 +02:00
if b.localNotificationsSrvc == nil {
b.localNotificationsSrvc, err = localnotifications.NewService(b.appDB)
2022-03-23 18:47:00 +00:00
if err != nil {
return nil, err
}
2021-06-30 13:40:54 +02:00
}
2022-03-23 18:47:00 +00:00
return b.localNotificationsSrvc, nil
2021-06-30 13:40:54 +02:00
}
2026-08-19 20:49:00 +01:00
func appendIf(condition bool, services []StatusService, service StatusService) []StatusService {
2021-06-30 13:40:54 +02:00
if !condition {
return services
}
return append(services, service)
}
func (b *StatusNode) PendingTracker() *pendingtxtracker.PendingTxTracker {
return b.pendingTracker
}
2021-06-30 13:40:54 +02:00
func (b *StatusNode) StopLocalNotifications() error {
if b.localNotificationsSrvc == nil {
return nil
}
if b.localNotificationsSrvc.IsStarted() {
err := b.localNotificationsSrvc.Stop()
if err != nil {
b.logger.Error("LocalNotifications service stop failed on StopLocalNotifications", zap.Error(err))
2021-06-30 13:40:54 +02:00
return nil
}
}
return nil
}
func (b *StatusNode) StartLocalNotifications() error {
if b.localNotificationsSrvc == nil {
return nil
}
if b.walletSrvc == nil {
return nil
}
if !b.localNotificationsSrvc.IsStarted() {
err := b.localNotificationsSrvc.Start()
if err != nil {
b.logger.Error("LocalNotifications service start failed on StartLocalNotifications", zap.Error(err))
2021-06-30 13:40:54 +02:00
return nil
}
}
return nil
}
func (b *StatusNode) personalService() *personal.Service {
if b.personalSrvc == nil {
b.personalSrvc = personal.New()
2021-06-30 13:40:54 +02:00
}
return b.personalSrvc
}
2025-10-16 17:36:49 +01:00
func (b *StatusNode) TimeSource() timesource.Provider {
2021-06-30 13:40:54 +02:00
if b.timeSourceSrvc == nil {
thirdpartyServicesEnabled, err := b.ThirdpartyServicesEnabled()
if err != nil {
b.logger.Error("failed to get if thirdparty services enabled", zap.Error(err))
}
if thirdpartyServicesEnabled {
2025-10-16 17:36:49 +01:00
b.timeSourceSrvc = timesource.DefaultService()
} else {
b.timeSourceSrvc = timesource.LocalService()
2025-10-16 17:36:49 +01:00
}
2021-06-30 13:40:54 +02:00
}
return b.timeSourceSrvc
}
2023-04-26 23:37:18 +08:00
func (b *StatusNode) timeSourceNow() func() time.Time {
2025-06-11 13:52:14 +02:00
return b.TimeSource().Now
2023-04-26 23:37:18 +08:00
}
func (b *StatusNode) NewsFeedService() *newsfeed.Service {
thirdpartyServicesEnabled, err := b.ThirdpartyServicesEnabled()
if err != nil {
b.logger.Error("failed to get if thirdparty services are enabled", zap.Error(err))
return nil
}
if !featureflags.EnableNewsFeed || !thirdpartyServicesEnabled {
return nil
}
if b.newsfeedSrvc == nil {
persistence := newsfeed.NewSQLitePersistence(b.appDB)
b.newsfeedSrvc = newsfeed.NewService(
b.logger.Named("newsfeed"),
persistence,
nil,
)
if wakuext := b.WakuV2ExtService(); wakuext != nil && wakuext.Messenger() != nil {
ac := nodeadapters.NewNewsFeedActivityCenterAdapter(wakuext.Messenger())
b.newsfeedSrvc.SetActivityCenter(ac)
}
}
return b.newsfeedSrvc
}