feat(wallet)_: add support to statusd to create account from seed phrase
fixed minor issues Closes #5175
This commit is contained in:
parent
9e5386955c
commit
99ead2d90c
|
@ -1622,3 +1622,31 @@ func TestTestnetEnabledSettingOnCreateAccount(t *testing.T) {
|
||||||
|
|
||||||
require.NoError(t, b.Logout())
|
require.NoError(t, b.Logout())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRestoreAccountAndLogin(t *testing.T) {
|
||||||
|
utils.Init()
|
||||||
|
tmpdir := t.TempDir()
|
||||||
|
|
||||||
|
backend := NewGethStatusBackend()
|
||||||
|
|
||||||
|
// Test case 1: Valid restore account request
|
||||||
|
restoreRequest := &requests.RestoreAccount{
|
||||||
|
Mnemonic: "test test test test test test test test test test test test",
|
||||||
|
FetchBackup: false,
|
||||||
|
CreateAccount: requests.CreateAccount{
|
||||||
|
DisplayName: "Account1",
|
||||||
|
DeviceName: "StatusIM",
|
||||||
|
Password: "password",
|
||||||
|
CustomizationColor: "0x000000",
|
||||||
|
BackupDisabledDataDir: tmpdir,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
account, err := backend.RestoreAccountAndLogin(restoreRequest)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, account)
|
||||||
|
|
||||||
|
// Test case 2: Invalid restore account request
|
||||||
|
invalidRequest := &requests.RestoreAccount{}
|
||||||
|
_, err = backend.RestoreAccountAndLogin(invalidRequest)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
|
@ -237,7 +237,11 @@ func defaultNodeConfig(installationID string, request *requests.CreateAccount, o
|
||||||
nodeConfig.LogEnabled = false
|
nodeConfig.LogEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeConfig.Networks = BuildDefaultNetworks(&request.WalletSecretsConfig)
|
if request.TestOverrideNetworks != nil {
|
||||||
|
nodeConfig.Networks = request.TestOverrideNetworks
|
||||||
|
} else {
|
||||||
|
nodeConfig.Networks = BuildDefaultNetworks(&request.WalletSecretsConfig)
|
||||||
|
}
|
||||||
|
|
||||||
if request.NetworkID != nil {
|
if request.NetworkID != nil {
|
||||||
nodeConfig.NetworkID = *request.NetworkID
|
nodeConfig.NetworkID = *request.NetworkID
|
||||||
|
|
|
@ -34,6 +34,7 @@ import (
|
||||||
"github.com/status-im/status-go/profiling"
|
"github.com/status-im/status-go/profiling"
|
||||||
"github.com/status-im/status-go/protocol"
|
"github.com/status-im/status-go/protocol"
|
||||||
"github.com/status-im/status-go/protocol/pushnotificationserver"
|
"github.com/status-im/status-go/protocol/pushnotificationserver"
|
||||||
|
"github.com/status-im/status-go/protocol/requests"
|
||||||
"github.com/status-im/status-go/walletdatabase"
|
"github.com/status-im/status-go/walletdatabase"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -86,6 +87,8 @@ var (
|
||||||
// don't change the name of this flag, https://github.com/ethereum/go-ethereum/blob/master/metrics/metrics.go#L41
|
// don't change the name of this flag, https://github.com/ethereum/go-ethereum/blob/master/metrics/metrics.go#L41
|
||||||
metricsEnabled = flag.Bool("metrics", false, "Expose ethereum metrics with debug_metrics jsonrpc call")
|
metricsEnabled = flag.Bool("metrics", false, "Expose ethereum metrics with debug_metrics jsonrpc call")
|
||||||
metricsPort = flag.Int("metrics-port", 9305, "Port for the Prometheus /metrics endpoint")
|
metricsPort = flag.Int("metrics-port", 9305, "Port for the Prometheus /metrics endpoint")
|
||||||
|
seedPhrase = flag.String("seed-phrase", "", "Seed phrase for account creation")
|
||||||
|
password = flag.String("password", "", "Password for account")
|
||||||
)
|
)
|
||||||
|
|
||||||
// All general log messages in this package should be routed through this logger.
|
// All general log messages in this package should be routed through this logger.
|
||||||
|
@ -110,6 +113,12 @@ func main() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *seedPhrase != "" && *password == "" {
|
||||||
|
printUsage()
|
||||||
|
logger.Error("password is required when seed phrase is provided")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
opts := []params.Option{params.WithFleet(*fleet)}
|
opts := []params.Option{params.WithFleet(*fleet)}
|
||||||
if *mailserver {
|
if *mailserver {
|
||||||
opts = append(opts, params.WithMailserver())
|
opts = append(opts, params.WithMailserver())
|
||||||
|
@ -162,12 +171,6 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
backend := api.NewGethStatusBackend()
|
backend := api.NewGethStatusBackend()
|
||||||
err = backend.AccountManager().InitKeystore(config.KeyStoreDir)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("Failed to init keystore", "error", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.NodeKey == "" {
|
if config.NodeKey == "" {
|
||||||
logger.Error("node key needs to be set if running a push notification server")
|
logger.Error("node key needs to be set if running a push notification server")
|
||||||
return
|
return
|
||||||
|
@ -186,96 +189,119 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = createDirsFromConfig(config)
|
if *seedPhrase != "" {
|
||||||
if err != nil {
|
// Remove data inside dir to avoid conflicts with existing data or account restoration fails
|
||||||
logger.Error("failed to create directories", "error", err)
|
if err := os.RemoveAll(config.DataDir); err != nil {
|
||||||
return
|
logger.Error("failed to remove data dir", "error", err)
|
||||||
}
|
return
|
||||||
|
}
|
||||||
|
|
||||||
appDB, walletDB, err := openDatabases(config.DataDir + "/" + installationID.String())
|
if err := createDirsFromConfig(config); err != nil {
|
||||||
if err != nil {
|
logger.Error("failed to create directories", "error", err)
|
||||||
log.Error("failed to open databases")
|
return
|
||||||
return
|
}
|
||||||
}
|
|
||||||
|
|
||||||
backend.StatusNode().SetAppDB(appDB)
|
request := requests.RestoreAccount{
|
||||||
backend.StatusNode().SetWalletDB(walletDB)
|
Mnemonic: *seedPhrase,
|
||||||
|
FetchBackup: false,
|
||||||
|
CreateAccount: requests.CreateAccount{
|
||||||
|
DisplayName: "Account1",
|
||||||
|
DeviceName: "StatusIM",
|
||||||
|
Password: *password,
|
||||||
|
CustomizationColor: "0x000000",
|
||||||
|
BackupDisabledDataDir: config.DataDir,
|
||||||
|
APIConfig: &requests.APIConfig{
|
||||||
|
HTTPHost: config.HTTPHost,
|
||||||
|
HTTPPort: config.HTTPPort,
|
||||||
|
APIModules: config.APIModules,
|
||||||
|
},
|
||||||
|
NetworkID: &config.NetworkID,
|
||||||
|
TestOverrideNetworks: config.Networks,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
err = backend.StartNode(config)
|
_, err := backend.RestoreAccountAndLogin(&request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Node start failed", "error", err)
|
logger.Error("failed to import account", "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sdnotify.Ready()
|
|
||||||
if err == sdnotify.ErrSdNotifyNoSocket {
|
|
||||||
logger.Debug("sd_notify socket not available")
|
|
||||||
} else if err != nil {
|
|
||||||
logger.Warn("sd_notify READY call failed", "error", err)
|
|
||||||
} else {
|
} else {
|
||||||
// systemd aliveness notifications, affects only Linux
|
appDB, walletDB, err := startNode(config, backend, installationID)
|
||||||
go startSystemDWatchdog()
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle interrupt signals
|
|
||||||
interruptCh := haltOnInterruptSignal(backend.StatusNode())
|
|
||||||
|
|
||||||
// Start collecting metrics. Metrics can be enabled by providing `-metrics` flag
|
|
||||||
// or setting `gethmetrics.Enabled` to true during compilation time:
|
|
||||||
// https://github.com/status-im/go-ethereum/pull/76.
|
|
||||||
if *metricsEnabled || gethmetrics.Enabled {
|
|
||||||
go startCollectingNodeMetrics(interruptCh, backend.StatusNode())
|
|
||||||
go gethmetrics.CollectProcessMetrics(3 * time.Second)
|
|
||||||
go metrics.NewMetricsServer(*metricsPort, gethmetrics.DefaultRegistry).Listen()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if profiling shall be enabled.
|
|
||||||
if *pprofEnabled {
|
|
||||||
profiling.NewProfiler(*pprofPort).Go()
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.PushNotificationServerConfig.Enabled {
|
|
||||||
options := []protocol.Option{
|
|
||||||
protocol.WithPushNotifications(),
|
|
||||||
protocol.WithPushNotificationServerConfig(&pushnotificationserver.Config{
|
|
||||||
Enabled: config.PushNotificationServerConfig.Enabled,
|
|
||||||
Identity: config.PushNotificationServerConfig.Identity,
|
|
||||||
GorushURL: config.PushNotificationServerConfig.GorushURL,
|
|
||||||
}),
|
|
||||||
protocol.WithDatabase(appDB),
|
|
||||||
protocol.WithWalletDatabase(walletDB),
|
|
||||||
protocol.WithTorrentConfig(&config.TorrentConfig),
|
|
||||||
protocol.WithWalletConfig(&config.WalletConfig),
|
|
||||||
protocol.WithAccountManager(backend.AccountManager()),
|
|
||||||
}
|
|
||||||
|
|
||||||
messenger, err := protocol.NewMessenger(
|
|
||||||
config.Name,
|
|
||||||
identity,
|
|
||||||
gethbridge.NewNodeBridge(backend.StatusNode().GethNode(), backend.StatusNode().WakuService(), backend.StatusNode().WakuV2Service()),
|
|
||||||
installationID.String(),
|
|
||||||
nil,
|
|
||||||
options...,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed to create messenger", "error", err)
|
logger.Error("failed to start node", "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = messenger.Init()
|
err = sdnotify.Ready()
|
||||||
if err != nil {
|
if err == sdnotify.ErrSdNotifyNoSocket {
|
||||||
logger.Error("failed to init messenger", "error", err)
|
logger.Debug("sd_notify socket not available")
|
||||||
return
|
} else if err != nil {
|
||||||
|
logger.Warn("sd_notify READY call failed", "error", err)
|
||||||
|
} else {
|
||||||
|
// systemd aliveness notifications, affects only Linux
|
||||||
|
go startSystemDWatchdog()
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will start the push notification server as well as
|
// handle interrupt signals
|
||||||
// the config is set to Enabled
|
interruptCh := haltOnInterruptSignal(backend.StatusNode())
|
||||||
_, err = messenger.Start()
|
|
||||||
if err != nil {
|
// Start collecting metrics. Metrics can be enabled by providing `-metrics` flag
|
||||||
logger.Error("failed to start messenger", "error", err)
|
// or setting `gethmetrics.Enabled` to true during compilation time:
|
||||||
return
|
// https://github.com/status-im/go-ethereum/pull/76.
|
||||||
|
if *metricsEnabled || gethmetrics.Enabled {
|
||||||
|
go startCollectingNodeMetrics(interruptCh, backend.StatusNode())
|
||||||
|
go gethmetrics.CollectProcessMetrics(3 * time.Second)
|
||||||
|
go metrics.NewMetricsServer(*metricsPort, gethmetrics.DefaultRegistry).Listen()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if profiling shall be enabled.
|
||||||
|
if *pprofEnabled {
|
||||||
|
profiling.NewProfiler(*pprofPort).Go()
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.PushNotificationServerConfig.Enabled {
|
||||||
|
options := []protocol.Option{
|
||||||
|
protocol.WithPushNotifications(),
|
||||||
|
protocol.WithPushNotificationServerConfig(&pushnotificationserver.Config{
|
||||||
|
Enabled: config.PushNotificationServerConfig.Enabled,
|
||||||
|
Identity: config.PushNotificationServerConfig.Identity,
|
||||||
|
GorushURL: config.PushNotificationServerConfig.GorushURL,
|
||||||
|
}),
|
||||||
|
protocol.WithDatabase(appDB),
|
||||||
|
protocol.WithWalletDatabase(walletDB),
|
||||||
|
protocol.WithTorrentConfig(&config.TorrentConfig),
|
||||||
|
protocol.WithWalletConfig(&config.WalletConfig),
|
||||||
|
protocol.WithAccountManager(backend.AccountManager()),
|
||||||
|
}
|
||||||
|
|
||||||
|
messenger, err := protocol.NewMessenger(
|
||||||
|
config.Name,
|
||||||
|
identity,
|
||||||
|
gethbridge.NewNodeBridge(backend.StatusNode().GethNode(), backend.StatusNode().WakuService(), backend.StatusNode().WakuV2Service()),
|
||||||
|
installationID.String(),
|
||||||
|
nil,
|
||||||
|
options...,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("failed to create messenger", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = messenger.Init()
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("failed to init messenger", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will start the push notification server as well as
|
||||||
|
// the config is set to Enabled
|
||||||
|
_, err = messenger.Start()
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("failed to start messenger", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go retrieveMessagesLoop(messenger, 300*time.Millisecond, interruptCh)
|
||||||
}
|
}
|
||||||
go retrieveMessagesLoop(messenger, 300*time.Millisecond, interruptCh)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gethNode := backend.StatusNode().GethNode()
|
gethNode := backend.StatusNode().GethNode()
|
||||||
|
@ -402,6 +428,7 @@ Examples:
|
||||||
statusd -c ./default.json # run node with configuration specified in ./default.json file
|
statusd -c ./default.json # run node with configuration specified in ./default.json file
|
||||||
statusd -c ./default.json -c ./standalone.json # run node with configuration specified in ./default.json file, after merging ./standalone.json file
|
statusd -c ./default.json -c ./standalone.json # run node with configuration specified in ./default.json file, after merging ./standalone.json file
|
||||||
statusd -c ./default.json -metrics # run node with configuration specified in ./default.json file, and expose ethereum metrics with debug_metrics jsonrpc call
|
statusd -c ./default.json -metrics # run node with configuration specified in ./default.json file, and expose ethereum metrics with debug_metrics jsonrpc call
|
||||||
|
statusd -c ./default.json -log DEBUG --seed-phrase="test test test test test test test test test test test junk" --password=password # run node with configuration specified in ./default.json file, and import account with seed phrase and password
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
`
|
`
|
||||||
|
@ -483,3 +510,34 @@ func createDirsFromConfig(config *params.NodeConfig) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func startNode(config *params.NodeConfig, backend *api.GethStatusBackend, installationID uuid.UUID) (*sql.DB, *sql.DB, error) {
|
||||||
|
err := backend.AccountManager().InitKeystore(config.KeyStoreDir)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to init keystore", "error", err)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = createDirsFromConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("failed to create directories", "error", err)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
appDB, walletDB, err := openDatabases(config.DataDir + "/" + installationID.String())
|
||||||
|
if err != nil {
|
||||||
|
log.Error("failed to open databases")
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
backend.StatusNode().SetAppDB(appDB)
|
||||||
|
backend.StatusNode().SetWalletDB(walletDB)
|
||||||
|
|
||||||
|
err = backend.StartNode(config)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Node start failed", "error", err)
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return appDB, walletDB, nil
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
utils "github.com/status-im/status-go/common"
|
utils "github.com/status-im/status-go/common"
|
||||||
|
"github.com/status-im/status-go/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrCreateAccountInvalidDisplayName = errors.New("create-account: invalid display name")
|
var ErrCreateAccountInvalidDisplayName = errors.New("create-account: invalid display name")
|
||||||
|
@ -56,8 +57,9 @@ type CreateAccount struct {
|
||||||
|
|
||||||
// Deprecated: CurrentNetwork is deprecated. It was passed and not used, so nothing should be passed instead.
|
// Deprecated: CurrentNetwork is deprecated. It was passed and not used, so nothing should be passed instead.
|
||||||
// If you want to use non-default network, use NetworkID.
|
// If you want to use non-default network, use NetworkID.
|
||||||
CurrentNetwork string `json:"currentNetwork"`
|
CurrentNetwork string `json:"currentNetwork"`
|
||||||
NetworkID *uint64 `json:"networkId"`
|
NetworkID *uint64 `json:"networkId"`
|
||||||
|
TestOverrideNetworks []params.Network `json:"-"` // This is used for testing purposes only
|
||||||
|
|
||||||
TestNetworksEnabled bool `json:"testNetworksEnabled"`
|
TestNetworksEnabled bool `json:"testNetworksEnabled"`
|
||||||
|
|
||||||
|
|
|
@ -486,11 +486,15 @@ func (s *Service) startTransfersWatcher() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
network := s.networkManager.Find(chainID)
|
||||||
|
if network == nil {
|
||||||
|
log.Error("Network not found", "chainID", chainID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
transferDB := transfer.NewDB(s.db)
|
transferDB := transfer.NewDB(s.db)
|
||||||
|
|
||||||
for _, address := range addresses {
|
for _, address := range addresses {
|
||||||
network := s.networkManager.Find(chainID)
|
|
||||||
|
|
||||||
transfers, err := transferDB.GetTransfersByAddressAndBlock(chainID, address, block, 1500) // 1500 is quite arbitrary and far from real, but should be enough to cover all transfers in a block
|
transfers, err := transferDB.GetTransfersByAddressAndBlock(chainID, address, block, 1500) // 1500 is quite arbitrary and far from real, but should be enough to cover all transfers in a block
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error getting transfers", "chainID", chainID, "address", address.String(), "err", err)
|
log.Error("Error getting transfers", "chainID", chainID, "address", address.String(), "err", err)
|
||||||
|
|
Loading…
Reference in New Issue