2017-05-16 15:09:52 +03:00
package node
import (
2024-10-15 22:59:17 +07:00
"context"
2021-06-30 13:40:54 +02:00
"database/sql"
2017-05-16 15:09:52 +03:00
"errors"
2025-07-24 16:56:54 -04:00
"fmt"
2025-08-27 10:34:41 -04:00
"os"
2017-05-16 15:09:52 +03:00
"path/filepath"
2025-09-09 11:27:15 +01:00
"reflect"
2017-05-16 15:09:52 +03:00
"sync"
2025-09-09 11:27:15 +01:00
"sync/atomic"
2025-07-24 16:56:54 -04:00
"time"
2017-05-16 15:09:52 +03:00
2025-09-09 11:27:15 +01:00
errorspkg "github.com/pkg/errors"
2024-10-28 21:54:17 +01:00
"go.uber.org/zap"
2020-01-02 10:10:19 +01:00
2023-08-01 19:50:30 +01:00
"github.com/ethereum/go-ethereum/event"
2025-09-08 21:01:02 +02:00
gethrpc "github.com/ethereum/go-ethereum/rpc"
2020-01-02 10:10:19 +01:00
2025-12-18 12:24:40 +00:00
accsmanagement "github.com/status-im/status-go/internal/accounts-management"
2026-03-20 14:41:49 +00:00
"github.com/status-im/status-go/internal/connection"
2025-12-18 12:24:40 +00:00
"github.com/status-im/status-go/internal/crypto"
2025-12-15 12:01:03 +00:00
"github.com/status-im/status-go/internal/db/multiaccounts"
"github.com/status-im/status-go/internal/db/multiaccounts/accounts"
2025-12-16 12:54:23 +00:00
"github.com/status-im/status-go/internal/ipfs"
2026-08-19 20:49:00 +01:00
"github.com/status-im/status-go/internal/panics"
"github.com/status-im/status-go/internal/pausable"
2025-12-18 12:24:40 +00:00
"github.com/status-im/status-go/internal/rpc"
2025-10-16 17:36:49 +01:00
"github.com/status-im/status-go/internal/timesource"
2025-12-15 12:01:03 +00:00
"github.com/status-im/status-go/internal/transactions"
2018-06-08 13:29:50 +02:00
"github.com/status-im/status-go/params"
2026-08-17 15:04:09 +02:00
noderpc "github.com/status-im/status-go/pkg/backend/node/rpc"
2025-06-17 01:02:34 -03:00
"github.com/status-im/status-go/pkg/pubsub"
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/backup"
"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/eth"
"github.com/status-im/status-go/pkg/services/gif"
"github.com/status-im/status-go/pkg/services/linkpreview"
localnotifications "github.com/status-im/status-go/pkg/services/local-notifications"
"github.com/status-im/status-go/pkg/services/media"
2026-08-26 18:05:03 +01:00
"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/newsfeed"
"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/sharedurls"
"github.com/status-im/status-go/pkg/services/stickers"
2026-08-19 18:03:17 +04:00
"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/utils"
"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/community"
"github.com/status-im/status-go/pkg/services/wallet/pendingtxtracker"
"github.com/status-im/status-go/pkg/services/wallet/token"
"github.com/status-im/status-go/pkg/services/wallet/tokenbalances"
2017-05-16 15:09:52 +03:00
)
// errors
var (
2025-09-09 11:27:15 +01:00
ErrNodeRunning = errors . New ( "node is already running" )
ErrNoRunningNode = errors . New ( "there is no running node" )
2017-05-16 15:09:52 +03:00
)
2018-04-05 11:45:26 +02:00
// StatusNode abstracts contained geth node and provides helper methods to
// interact with it.
type StatusNode struct {
2018-04-12 18:17:10 +02:00
mu sync . RWMutex
2021-06-30 13:40:54 +02:00
appDB * sql . DB
multiaccountsDB * multiaccounts . Database
2023-08-11 13:25:14 +02:00
walletDB * sql . DB
2021-06-30 13:40:54 +02:00
2025-09-09 11:27:15 +01:00
running atomic . Bool
2026-08-26 18:05:03 +01:00
config * params . NodeConfig // Status node configuration
rpcClient * rpc . Client // reference to an RPC client
networkManager * networks . Manager
2018-02-09 15:37:56 +02:00
2026-08-19 20:49:00 +01:00
services [] StatusService
2025-09-09 11:27:15 +01:00
rpcServer * gethrpc . Server
2022-05-09 09:07:57 -04:00
downloader * ipfs . Downloader
2024-11-22 10:23:17 +08:00
2025-09-10 10:19:04 +01:00
mediaServerAddress * string
mediaServerAdvertizeHost string
mediaServerAdvertizePort int
mediaServerEnableTLS * bool
2026-08-19 20:50:03 +01:00
mediaServer * media . Server
2022-05-09 09:07:57 -04:00
2025-09-08 21:01:02 +02:00
tokenManager * token . Manager
2024-10-28 21:54:17 +01:00
logger * zap . Logger
2021-06-30 13:40:54 +02:00
2025-06-30 10:24:43 +02:00
gethAccountsManager * accsmanagement . AccountsManager
transactor * transactions . Transactor
2021-06-30 13:40:54 +02:00
2021-07-09 15:19:33 +02:00
publicMethods map [ string ] bool
2021-07-07 08:11:09 +02:00
// we explicitly list every service, we could use interfaces
2021-07-09 15:19:33 +02:00
// and store them in a nicer way and user reflection, but for now stupid is good
2021-06-30 13:40:54 +02:00
rpcStatsSrvc * rpcstats . Service
accountsSrvc * accountssvc . Service
browsersSrvc * browsers . Service
permissionsSrvc * permissions . Service
walletSrvc * wallet . Service
2026-08-26 18:05:03 +01:00
networksSrvc * networks . Service
2021-06-30 13:40:54 +02:00
localNotificationsSrvc * localnotifications . Service
personalSrvc * personal . Service
2025-10-16 17:36:49 +01:00
timeSourceSrvc timesource . Service
2021-06-30 13:40:54 +02:00
wakuV2ExtSrvc * wakuv2ext . Service
2021-12-21 16:05:09 +01:00
ensSrvc * ens . Service
2025-01-16 19:22:46 +01:00
communityTokensSrvc * communitytokens . Service
2022-01-31 13:58:03 +01:00
gifSrvc * gif . Service
2022-02-02 18:50:55 -04:00
stickersSrvc * stickers . Service
2022-02-10 11:15:27 -04:00
chatSrvc * chat . Service
2022-06-08 08:38:26 -04:00
updatesSrvc * updates . Service
2025-10-17 07:29:28 -03:00
pendingTracker * pendingtxtracker . PendingTxTracker
2024-06-24 16:29:40 +02:00
connectorSrvc * connector . Service
2024-08-29 16:03:24 +05:30
appGeneralSrvc * appgeneral . Service
2025-09-09 11:27:15 +01:00
ethSrvc * eth . Service
2025-10-28 20:53:44 +00:00
newsfeedSrvc * newsfeed . Service
2026-05-26 14:18:15 +02:00
preferencesSrvc * preferences . Service
2025-10-31 20:44:06 +00:00
sharedUrlsSrvc * sharedurls . Service
2026-08-19 18:03:17 +04:00
storageStatsSrvc * storagestats . Service
2025-11-26 17:08:27 +01:00
linkPreviewSrvc * linkpreview . Service
2023-08-01 19:50:30 +01:00
2025-06-17 01:02:34 -03:00
walletFeed event . Feed
accountsPublisher * pubsub . Publisher
2025-07-24 16:56:54 -04:00
localBackup * backup . Controller
2026-04-09 13:03:36 +03:00
2026-07-21 18:24:32 -04:00
tokenManagerStartDone chan struct {}
2026-04-09 13:03:36 +03:00
serviceRegistry * ServiceRegistry
}
// ServiceRegistry returns the node's service registry for granular pause/resume control.
func ( n * StatusNode ) ServiceRegistry () * ServiceRegistry {
return n . serviceRegistry
2017-05-16 15:09:52 +03:00
}
2018-04-05 11:45:26 +02:00
// New makes new instance of StatusNode.
2025-06-30 10:24:43 +02:00
func New ( transactor * transactions . Transactor , gethAccountsManager * accsmanagement . AccountsManager , logger * zap . Logger ) * StatusNode {
2024-10-28 21:54:17 +01:00
logger = logger . Named ( "StatusNode" )
2018-04-05 11:45:26 +02:00
return & StatusNode {
2025-06-30 10:24:43 +02:00
transactor : transactor ,
gethAccountsManager : gethAccountsManager ,
logger : logger ,
publicMethods : make ( map [ string ] bool ),
accountsPublisher : pubsub . NewPublisher (),
2025-09-09 11:27:15 +01:00
rpcServer : gethrpc . NewServer (),
2026-04-09 13:03:36 +03:00
serviceRegistry : newServiceRegistry (),
2018-03-20 14:35:28 -04:00
}
2017-05-16 15:09:52 +03:00
}
2018-04-16 14:36:09 +02:00
// Config exposes reference to running node's configuration
func ( n * StatusNode ) Config () * params . NodeConfig {
n . mu . RLock ()
defer n . mu . RUnlock ()
return n . config
}
2026-08-19 20:50:03 +01:00
func ( n * StatusNode ) MediaServer () * media . Server {
2022-05-09 09:07:57 -04:00
n . mu . RLock ()
defer n . mu . RUnlock ()
2025-09-10 10:19:04 +01:00
return n . mediaServer
2022-05-09 09:07:57 -04:00
}
2025-09-10 10:19:04 +01:00
func ( n * StatusNode ) startMediaServer () error {
if n . mediaServer != nil {
if err := n . mediaServer . Stop (); err != nil {
2023-05-18 14:27:16 +08:00
return err
}
}
2026-08-19 20:50:03 +01:00
var opts [] media . MediaServerOption
2024-11-22 10:23:17 +08:00
if n . mediaServerEnableTLS != nil {
2026-08-19 20:50:03 +01:00
opts = append ( opts , media . WithMediaServerDisableTLS (! * n . mediaServerEnableTLS ))
2024-11-22 10:23:17 +08:00
}
2025-09-10 10:19:04 +01:00
if n . mediaServerAddress != nil {
2026-08-19 20:50:03 +01:00
opts = append ( opts , media . WithMediaServerAddress ( * n . mediaServerAddress ))
2025-09-10 10:19:04 +01:00
}
2026-08-19 20:50:03 +01:00
opts = append ( opts , media . WithMediaServerAdvertizeAddress ( n . mediaServerAdvertizeHost , n . mediaServerAdvertizePort ))
mediaServer , err := media . NewServer ( nil , nil , n . multiaccountsDB , nil , opts ... )
2023-05-18 14:27:16 +08:00
if err != nil {
return err
}
2025-09-10 10:19:04 +01:00
n . mediaServer = mediaServer
2023-05-18 14:27:16 +08:00
2025-09-10 10:19:04 +01:00
if err := n . mediaServer . Start (); err != nil {
2023-05-18 14:27:16 +08:00
return err
}
return nil
}
2025-09-10 10:19:04 +01:00
// StartMediaServerWithoutDB starts media server without starting the node
// The server can only handle requests that don't require appdb or IPFS downloader
func ( n * StatusNode ) StartMediaServerWithoutDB () error {
if n . IsRunning () {
n . logger . Debug ( "node is already running, no need to StartMediaServerWithoutDB" )
return nil
}
return n . startMediaServer ()
}
2019-01-02 20:57:36 +02:00
// StartWithOptions starts current StatusNode, failing if it's already started.
// It takes some options that allows to further configure starting process.
2025-06-02 16:03:24 +02:00
func ( n * StatusNode ) Start ( config * params . NodeConfig ) error {
2018-05-02 14:14:08 +02:00
n . mu . Lock ()
defer n . mu . Unlock ()
2018-04-20 13:26:54 +02:00
2025-09-09 11:27:15 +01:00
if ! n . running . CompareAndSwap ( false , true ) {
2024-10-28 21:54:17 +01:00
n . logger . Debug ( "node is already running" )
2018-05-02 14:14:08 +02:00
return ErrNodeRunning
2018-04-20 13:26:54 +02:00
}
2018-05-02 14:14:08 +02:00
2024-10-28 21:54:17 +01:00
n . logger . Debug ( "starting with options" , zap . Stringer ( "ClusterConfig" , & config . ClusterConfig ))
2018-09-13 18:31:29 +02:00
2025-06-02 16:03:24 +02:00
return n . startWithDB ( config )
2018-04-20 13:26:54 +02:00
}
2025-07-24 16:56:54 -04:00
func ( n * StatusNode ) StartLocalBackup () error {
if n . localBackup != nil {
return errors . New ( "local backup already started" )
}
2025-08-27 10:34:41 -04:00
backupPath , err := n . accountsSrvc . GetBackupPath ()
if err != nil {
return err
}
if backupPath == "" {
// No path set yet, set it to the user's config directory
dir , err := os . UserConfigDir ()
// We do not return the error as it's not a major issue
if err != nil {
n . logger . Error ( "failed to get user config dir" , zap . Error ( err ))
} else {
err = n . accountsSrvc . SetBackupPath ( filepath . Join ( dir , "Status" , "backups" ))
if err != nil {
n . logger . Error ( "failed to set backup path" , zap . Error ( err ))
}
}
}
2025-08-28 12:02:09 -04:00
chatAccount , err := n . gethAccountsManager . SelectedChatAccount ()
if err != nil {
return err
}
privateKey := chatAccount . PrivateKey ()
2025-12-12 21:28:00 +00:00
n . localBackup , err = backup . NewController ( backup . Config {
2025-12-05 12:41:17 +00:00
PrivateKey : crypto . Keccak256 ( crypto . FromECDSA ( privateKey )),
FileNameProvider : n ,
BackupEnabled : true ,
Interval : time . Minute * 30 ,
2025-07-24 16:56:54 -04:00
}, n . logger . Named ( "LocalBackup" ))
if err != nil {
return err
}
if n . accountsSrvc != nil {
n . localBackup . Register ( "settings" , n . accountsSrvc )
}
if n . walletSrvc != nil {
n . localBackup . Register ( "wallet" , n . walletSrvc )
}
2025-11-26 20:40:01 +01:00
if n . wakuV2ExtSrvc != nil {
n . localBackup . Register ( "messenger" , n . wakuV2ExtSrvc . Messenger ())
2025-07-24 16:56:54 -04:00
}
2026-04-09 13:03:36 +03:00
n . serviceRegistry . Register ( n . localBackup )
2025-07-24 16:56:54 -04:00
n . localBackup . Start ()
return nil
}
2025-12-05 12:41:17 +00:00
func ( n * StatusNode ) GetBackupFilename () ( string , error ) {
chatAccount , err := n . gethAccountsManager . SelectedChatAccount ()
if err != nil {
return "" , err
}
privateKey := chatAccount . PrivateKey ()
backupPath , err := n . accountsSrvc . GetBackupPath ()
if err != nil {
return "" , err
}
compressedPubKey , err := utils . SerializePublicKey ( crypto . CompressPubkey ( & privateKey . PublicKey ))
if err != nil {
return "" , err
}
if backupPath == "" {
return "" , errors . New ( "backup path is not set" )
}
fullPath := filepath . Join ( backupPath , fmt . Sprintf ( "%s_user_data.bkp" , compressedPubKey [ len ( compressedPubKey ) - 6 :]))
return fullPath , nil
}
2025-07-24 16:56:54 -04:00
func ( n * StatusNode ) PerformLocalBackup () ( string , error ) {
return n . localBackup . PerformBackup ()
}
func ( n * StatusNode ) LoadLocalBackup ( filePath string ) error {
return n . localBackup . LoadBackup ( filePath )
}
2025-09-10 10:19:04 +01:00
func ( n * StatusNode ) SetMediaServerOptions ( address * string , enableTLS * bool , advertizeHost string , advertizePort int ) {
2026-07-07 17:08:05 +04:00
n . mu . Lock ()
defer n . mu . Unlock ()
2025-09-10 10:19:04 +01:00
n . mediaServerAddress = address
2024-11-22 10:23:17 +08:00
n . mediaServerEnableTLS = enableTLS
2025-09-10 10:19:04 +01:00
n . mediaServerAdvertizeHost = advertizeHost
n . mediaServerAdvertizePort = advertizePort
2026-07-07 16:49:42 +04:00
if n . mediaServer != nil {
if err := n . startMediaServer (); err != nil {
n . logger . Error ( "failed to restart media server with updated options" , zap . Error ( err ))
}
}
}
func ( n * StatusNode ) StopMediaServer () error {
2026-07-07 17:08:05 +04:00
n . mu . Lock ()
defer n . mu . Unlock ()
2026-07-07 16:49:42 +04:00
if n . mediaServer == nil {
return nil
}
err := n . mediaServer . Stop ()
n . mediaServer = nil
return err
2024-11-22 10:23:17 +08:00
}
2025-06-02 16:03:24 +02:00
func ( n * StatusNode ) startWithDB ( config * params . NodeConfig ) error {
2019-01-02 20:57:36 +02:00
n . config = config
if err := n . setupRPCClient (); err != nil {
return err
}
2022-05-09 09:07:57 -04:00
n . downloader = ipfs . NewDownloader ( config . RootDataDir )
2025-09-10 10:19:04 +01:00
if n . mediaServer == nil {
if err := n . startMediaServer (); err != nil {
2023-05-18 14:27:16 +08:00
return err
}
}
2025-09-10 10:19:04 +01:00
n . mediaServer . SetDataProviders ( n . appDB , n . walletDB , n . downloader )
2022-05-09 09:07:57 -04:00
2026-07-21 18:24:32 -04:00
if err := n . createTokenManager (); err != nil {
2025-09-08 21:01:02 +02:00
return err
}
2026-08-03 14:57:04 -04:00
if err := n . tokenManager . Start ( context . Background ()); err != nil {
return errorspkg . Wrap ( err , "failed to start token manager" )
}
n . tokenManagerStartDone = make ( chan struct {})
close ( n . tokenManagerStartDone )
2025-09-08 21:01:02 +02:00
2025-09-10 10:19:04 +01:00
if err := n . initServices ( config , n . mediaServer ); err != nil {
2021-06-30 13:40:54 +02:00
return err
}
2019-01-02 20:57:36 +02:00
2025-10-28 20:53:44 +00:00
// Run migrations
err := n . runServicesMigrations ()
if err != nil {
return errorspkg . Wrap ( err , "failed to run services migrations" )
}
2025-09-09 11:27:15 +01:00
// Register services
for _ , service := range n . services {
2025-09-10 10:19:04 +01:00
err := n . registerService ( service )
2025-09-09 11:27:15 +01:00
if err != nil {
name := reflect . TypeOf ( service ). Name ()
text := fmt . Sprintf ( "failed to register service '%s'" , name )
return errorspkg . Wrap ( err , text )
}
}
// Start services
2025-10-28 20:53:44 +00:00
err = n . timeSourceSrvc . Start ( context . Background ())
2025-09-09 11:27:15 +01:00
if err != nil {
return errorspkg . Wrap ( err , "failed to start time source" )
}
for _ , service := range n . services {
err := service . Start ()
if err != nil {
name := reflect . TypeOf ( service ). Name ()
text := fmt . Sprintf ( "failed to start service '%s'" , name )
return errorspkg . Wrap ( err , text )
}
}
2026-04-09 13:03:36 +03:00
n . populateServiceRegistry ()
2025-09-09 11:27:15 +01:00
return nil
2018-04-16 14:36:09 +02:00
}
2026-04-09 13:03:36 +03:00
// populateServiceRegistry registers all services that implement Pausable and wraps the
// media server as a pausable. Called once after all services are started.
func ( n * StatusNode ) populateServiceRegistry () {
// Register services implementing Pausable
for _ , service := range n . services {
2026-08-19 20:49:00 +01:00
if p , ok := service .( pausable . Pausable ); ok {
2026-04-09 13:03:36 +03:00
n . serviceRegistry . Register ( p )
}
}
// Wrap and register the media server
if n . mediaServer != nil {
n . serviceRegistry . Register ( newPausableMediaServer ( n . mediaServer ))
}
2026-06-02 17:49:27 +02:00
// Wrap and register the messenger so that PauseServices/ResumeServices
// gate filter health-check pings and mailserver syncs in background.
if n . wakuV2ExtSrvc != nil {
if m := n . wakuV2ExtSrvc . Messenger (); m != nil {
n . serviceRegistry . Register ( newPausableMessenger ( m ))
}
}
2026-04-09 13:03:36 +03:00
// Register infrastructure components that are not go-ethereum services
if n . downloader != nil {
n . serviceRegistry . Register ( n . downloader )
}
2026-08-19 20:49:00 +01:00
if p , ok := n . timeSourceSrvc .( pausable . Pausable ); ok {
2026-04-09 13:03:36 +03:00
n . serviceRegistry . Register ( p )
}
}
2026-07-21 18:24:32 -04:00
func ( n * StatusNode ) createTokenManager () error {
2025-09-08 21:01:02 +02:00
const (
defaultAutoRefreshInterval = 30 * time . Minute // interval after which we should fetch the token lists from the remote source (or use the default one if remote source is not set)
defaultAutoRefreshCheckInterval = 3 * time . Minute // interval after which we should check if we should trigger the auto-refresh
)
autoRefreshInterval := defaultAutoRefreshInterval
autoRefreshCheckInterval := defaultAutoRefreshCheckInterval
if n . config . WalletConfig . TokensListsAutoRefreshInterval > 0 &&
n . config . WalletConfig . TokensListsAutoRefreshCheckInterval > 0 &&
n . config . WalletConfig . TokensListsAutoRefreshInterval > n . config . WalletConfig . TokensListsAutoRefreshCheckInterval {
autoRefreshInterval = time . Duration ( n . config . WalletConfig . TokensListsAutoRefreshInterval ) * time . Second
autoRefreshCheckInterval = time . Duration ( n . config . WalletConfig . TokensListsAutoRefreshCheckInterval ) * time . Second
}
2025-09-25 14:05:19 +02:00
accDB , err := accounts . NewDB ( n . appDB )
if err != nil {
return err
}
n . tokenManager , err = token . NewTokenManager ( n . walletDB , n . rpcClient , community . NewManager ( n . appDB , n . mediaServer , nil ),
n . rpcClient . GetNetworkManager (), n . appDB , n . mediaServer , & n . walletFeed , n . accountsPublisher , accDB ,
autoRefreshInterval , autoRefreshCheckInterval )
if err != nil {
return err
}
2025-12-15 18:14:10 +08:00
// check for possible custom tokens in the config
if len ( n . config . WalletConfig . CustomTokens ) > 0 {
for _ , token := range n . config . WalletConfig . CustomTokens {
err := n . tokenManager . UpsertCustom ( * token )
if err != nil {
return err
}
}
}
2026-07-21 18:24:32 -04:00
return nil
}
func ( n * StatusNode ) StartTokenManager () {
n . mu . Lock ()
if ! n . running . Load () || n . tokenManager == nil || n . tokenManagerStartDone != nil {
n . mu . Unlock ()
return
}
tokenManager := n . tokenManager
done := make ( chan struct {})
n . tokenManagerStartDone = done
n . mu . Unlock ()
go func () {
2026-08-19 20:49:00 +01:00
defer panics . LogOnPanic ()
2026-07-21 18:24:32 -04:00
defer close ( done )
if err := tokenManager . Start ( context . Background ()); err != nil {
n . logger . Error ( "failed to start token manager" , zap . Error ( err ))
}
}()
2025-09-08 21:01:02 +02:00
}
2026-08-26 18:05:03 +01:00
// NetworkManager returns the network manager owned by the node.
func ( n * StatusNode ) NetworkManager () * networks . Manager {
return n . networkManager
}
2018-04-16 10:01:37 +02:00
func ( n * StatusNode ) setupRPCClient () ( err error ) {
2026-08-26 18:05:03 +01:00
networkManager := networks . NewManager ( n . appDB , n . accountsPublisher )
if networkManager == nil {
return errorspkg . New ( "failed to create network manager" )
}
if err = networkManager . InitEmbeddedNetworks ( n . config . Networks ); err != nil {
return errorspkg . Wrap ( err , "network manager failed to initialize" )
}
n . networkManager = networkManager
2024-10-15 22:59:17 +07:00
config := rpc . ClientConfig {
2026-08-26 18:05:03 +01:00
NetworkManager : networkManager ,
2025-06-17 01:02:34 -03:00
AccountsPublisher : n . accountsPublisher ,
2024-10-15 22:59:17 +07:00
}
n . rpcClient , err = rpc . NewClient ( config )
2025-01-31 21:12:07 +07:00
if err != nil {
return
}
2024-10-15 22:59:17 +07:00
n . rpcClient . Start ( context . Background ())
2018-04-16 10:01:37 +02:00
return
}
2018-04-05 11:45:26 +02:00
// Stop will stop current StatusNode. A stopped node cannot be resumed.
func ( n * StatusNode ) Stop () error {
n . mu . Lock ()
defer n . mu . Unlock ()
2018-04-16 14:36:09 +02:00
2025-09-09 11:27:15 +01:00
n . logger . Debug ( "stopping" )
if ! n . running . CompareAndSwap ( true , false ) {
2018-04-16 14:36:09 +02:00
return ErrNoRunningNode
}
2025-09-09 11:27:15 +01:00
var errs [] error
2026-07-21 18:24:32 -04:00
if n . tokenManagerStartDone != nil {
<- n . tokenManagerStartDone
n . tokenManagerStartDone = nil
2026-08-03 14:57:04 -04:00
n . tokenManager . Stop ()
2026-07-21 18:24:32 -04:00
}
2025-09-09 11:27:15 +01:00
n . timeSourceSrvc . Stop ()
for _ , service := range n . services {
err := service . Stop ()
errs = append ( errs , err )
}
2025-07-24 16:56:54 -04:00
if n . localBackup != nil {
n . localBackup . Stop ()
n . localBackup = nil
}
2025-06-17 01:02:34 -03:00
n . accountsPublisher . Close ()
2024-10-15 22:59:17 +07:00
n . rpcClient . Stop ()
2018-04-05 11:45:26 +02:00
n . rpcClient = nil
2018-04-16 14:36:09 +02:00
n . config = nil
2026-07-07 16:49:42 +04:00
if n . mediaServer != nil {
n . mediaServer . SetDataProviders ( nil , nil , nil )
}
2022-05-09 09:07:57 -04:00
n . downloader . Stop ()
n . downloader = nil
2021-07-07 08:11:09 +02:00
n . rpcStatsSrvc = nil
n . accountsSrvc = nil
n . browsersSrvc = nil
n . permissionsSrvc = nil
n . walletSrvc = nil
2026-08-26 18:05:03 +01:00
n . networksSrvc = nil
n . networkManager = nil
2021-07-07 08:11:09 +02:00
n . localNotificationsSrvc = nil
n . personalSrvc = nil
n . timeSourceSrvc = nil
n . wakuV2ExtSrvc = nil
2021-12-21 16:05:09 +01:00
n . ensSrvc = nil
2025-01-16 19:22:46 +01:00
n . communityTokensSrvc = nil
2022-02-02 18:50:55 -04:00
n . stickersSrvc = nil
2024-06-24 16:29:40 +02:00
n . connectorSrvc = nil
2021-07-09 15:19:33 +02:00
n . publicMethods = make ( map [ string ] bool )
2023-08-01 19:50:30 +01:00
n . pendingTracker = nil
2024-08-29 16:03:24 +05:30
n . appGeneralSrvc = nil
2025-10-28 20:53:44 +00:00
n . newsfeedSrvc = nil
2026-05-26 14:18:15 +02:00
n . preferencesSrvc = nil
2026-08-19 18:03:17 +04:00
n . storageStatsSrvc = nil
2025-09-09 11:27:15 +01:00
2024-10-28 21:54:17 +01:00
n . logger . Debug ( "status node stopped" )
2025-09-09 11:27:15 +01:00
return errors . Join ( errs ... )
2019-01-02 20:57:36 +02:00
}
2018-04-05 11:45:26 +02:00
// IsRunning confirm that node is running.
func ( n * StatusNode ) IsRunning () bool {
2025-09-09 11:27:15 +01:00
return n . running . Load ()
2017-05-16 15:09:52 +03:00
}
2026-04-09 13:03:36 +03:00
// Pause reduces non-essential background work while preserving core messaging/Waku runtime.
// Delegates to the ServiceRegistry so callers can also pause individual services via PauseService.
func ( n * StatusNode ) Pause () error {
if n . serviceRegistry == nil {
return nil
}
return n . serviceRegistry . PauseAll ()
}
// Resume restores regular service work after paused background mode.
// Delegates to the ServiceRegistry so callers can also resume individual services via ResumeService.
func ( n * StatusNode ) Resume () error {
if n . serviceRegistry == nil {
return nil
}
return n . serviceRegistry . ResumeAll ()
}
2025-09-09 11:27:15 +01:00
func ( n * StatusNode ) CallInProcessRPC ( inputJSON string ) string {
2026-08-17 15:04:09 +02:00
codec := noderpc . NewSingleRequestCodec ( inputJSON )
2025-09-09 11:27:15 +01:00
n . rpcServer . ServeCodec ( codec . GethCodec (), 0 )
return codec . Output ()
2017-05-16 15:09:52 +03:00
}
2017-09-07 08:49:40 +01:00
// RPCClient exposes reference to RPC client connected to the running node.
2018-04-05 11:45:26 +02:00
func ( n * StatusNode ) RPCClient () * rpc . Client {
2018-08-20 15:55:43 +02:00
n . mu . RLock ()
defer n . mu . RUnlock ()
2018-04-05 11:45:26 +02:00
return n . rpcClient
2017-05-28 16:57:30 +03:00
}
2017-09-01 20:44:50 +02:00
2021-06-30 13:40:54 +02:00
func ( n * StatusNode ) SetAppDB ( db * sql . DB ) {
n . appDB = db
}
2024-10-06 10:40:22 -03:00
func ( n * StatusNode ) GetAppDB () * sql . DB {
return n . appDB
}
2021-06-30 13:40:54 +02:00
func ( n * StatusNode ) SetMultiaccountsDB ( db * multiaccounts . Database ) {
n . multiaccountsDB = db
}
2023-08-11 13:25:14 +02:00
func ( n * StatusNode ) SetWalletDB ( db * sql . DB ) {
n . walletDB = db
}
2024-10-06 10:40:22 -03:00
func ( n * StatusNode ) GetWalletDB () * sql . DB {
return n . walletDB
}
2025-09-08 21:01:02 +02:00
func ( n * StatusNode ) TokenManager () * token . Manager {
return n . tokenManager
}
2025-10-15 10:05:46 -03:00
2025-11-28 11:19:54 +01:00
func ( n * StatusNode ) TokenBalancesFetcher () tokenbalances . FetcherIface {
2025-10-15 10:05:46 -03:00
if n . walletSrvc != nil {
2025-11-28 11:19:54 +01:00
return n . walletSrvc . GetTokenBalancesFetcher ()
2025-10-15 10:05:46 -03:00
}
return nil
}
func ( n * StatusNode ) TokenBalancesStorage () tokenbalances . Storage {
if n . walletSrvc != nil {
return n . walletSrvc . GetTokenBalancesStorage ()
}
return nil
}
2026-03-20 14:41:49 +00:00
func ( n * StatusNode ) ConnectionChanged ( state connection . State ) {
if n . wakuV2ExtSrvc != nil {
n . wakuV2ExtSrvc . ConnectionChanged ( state )
}
}