feat(wallet)_: add support to statusd to create account from seed phrase

fixed minor issues

Closes #5175
This commit is contained in:
Ivan Belyakov 2024-06-02 20:28:55 +02:00 committed by IvanBelyakoff
parent 9e5386955c
commit 99ead2d90c
5 changed files with 186 additions and 90 deletions

View File

@ -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)
}

View File

@ -237,7 +237,11 @@ func defaultNodeConfig(installationID string, request *requests.CreateAccount, o
nodeConfig.LogEnabled = false nodeConfig.LogEnabled = false
} }
if request.TestOverrideNetworks != nil {
nodeConfig.Networks = request.TestOverrideNetworks
} else {
nodeConfig.Networks = BuildDefaultNetworks(&request.WalletSecretsConfig) nodeConfig.Networks = BuildDefaultNetworks(&request.WalletSecretsConfig)
}
if request.NetworkID != nil { if request.NetworkID != nil {
nodeConfig.NetworkID = *request.NetworkID nodeConfig.NetworkID = *request.NetworkID

View File

@ -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,24 +189,46 @@ 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
if err := os.RemoveAll(config.DataDir); err != nil {
logger.Error("failed to remove data dir", "error", err)
return
}
if err := createDirsFromConfig(config); err != nil {
logger.Error("failed to create directories", "error", err) logger.Error("failed to create directories", "error", err)
return return
} }
appDB, walletDB, err := openDatabases(config.DataDir + "/" + installationID.String()) request := requests.RestoreAccount{
if err != nil { Mnemonic: *seedPhrase,
log.Error("failed to open databases") FetchBackup: false,
return 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,
},
} }
backend.StatusNode().SetAppDB(appDB) _, err := backend.RestoreAccountAndLogin(&request)
backend.StatusNode().SetWalletDB(walletDB)
err = backend.StartNode(config)
if err != nil { if err != nil {
logger.Error("Node start failed", "error", err) logger.Error("failed to import account", "error", err)
return
}
} else {
appDB, walletDB, err := startNode(config, backend, installationID)
if err != nil {
logger.Error("failed to start node", "error", err)
return return
} }
@ -277,6 +302,7 @@ func main() {
} }
go retrieveMessagesLoop(messenger, 300*time.Millisecond, interruptCh) go retrieveMessagesLoop(messenger, 300*time.Millisecond, interruptCh)
} }
}
gethNode := backend.StatusNode().GethNode() gethNode := backend.StatusNode().GethNode()
if gethNode != nil { if gethNode != nil {
@ -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
}

View File

@ -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")
@ -58,6 +59,7 @@ type CreateAccount struct {
// 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"`

View File

@ -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)