diff --git a/api/geth_backend.go b/api/geth_backend.go index 6a283a5a9..efee85b3a 100644 --- a/api/geth_backend.go +++ b/api/geth_backend.go @@ -20,6 +20,7 @@ import ( signercore "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/status-im/status-go/account" + "github.com/status-im/status-go/account/generator" "github.com/status-im/status-go/appdatabase" "github.com/status-im/status-go/connection" "github.com/status-im/status-go/eth-node/crypto" @@ -711,12 +712,16 @@ func (b *GethStatusBackend) ConvertToKeycardAccount(account multiaccounts.Accoun return nil } -func (b *GethStatusBackend) CreateAccountAndLogin(request *requests.CreateAccount) error { +func (b *GethStatusBackend) RestoreAccountAndLogin(request *requests.RestoreAccount) error { if err := request.Validate(); err != nil { return err } + return b.generateOrImportAccount(request.Mnemonic, &request.CreateAccount) +} + +func (b *GethStatusBackend) generateOrImportAccount(mnemonic string, request *requests.CreateAccount) error { if err := b.accountManager.InitKeystore(filepath.Join(request.BackupDisabledDataDir, keystoreRelativePath)); err != nil { return err } @@ -728,23 +733,31 @@ func (b *GethStatusBackend) CreateAccountAndLogin(request *requests.CreateAccoun return err } - generator := b.accountManager.AccountsGenerator() + accountGenerator := b.accountManager.AccountsGenerator() - // generate 1(n) account with default mnemonic length and no passphrase - generatedAccountInfos, err := generator.Generate(defaultMnemonicLength, 1, "") + var info generator.GeneratedAccountInfo + if mnemonic == "" { + // generate 1(n) account with default mnemonic length and no passphrase + generatedAccountInfos, err := accountGenerator.Generate(defaultMnemonicLength, 1, "") + info = generatedAccountInfos[0] + if err != nil { + return err + } + } else { + + info, err = accountGenerator.ImportMnemonic(mnemonic, "") + if err != nil { + return err + } + } + + derivedAddresses, err := accountGenerator.DeriveAddresses(info.ID, paths) if err != nil { return err } - info := generatedAccountInfos[0] - - derivedAddresses, err := generator.DeriveAddresses(info.ID, paths) - if err != nil { - return err - } - - _, err = generator.StoreDerivedAccounts(info.ID, request.Password, paths) + _, err = accountGenerator.StoreDerivedAccounts(info.ID, request.Password, paths) if err != nil { return err } @@ -760,7 +773,11 @@ func (b *GethStatusBackend) CreateAccountAndLogin(request *requests.CreateAccoun return err } settings.DisplayName = request.DisplayName - settings.Mnemonic = &info.Mnemonic + + // If restoring an account, we don't set the mnemonic + if mnemonic == "" { + settings.Mnemonic = &info.Mnemonic + } nodeConfig, err := defaultNodeConfig(settings.InstallationID, request) if err != nil { @@ -808,6 +825,16 @@ func (b *GethStatusBackend) CreateAccountAndLogin(request *requests.CreateAccoun } return nil + +} + +func (b *GethStatusBackend) CreateAccountAndLogin(request *requests.CreateAccount) error { + + if err := request.Validate(); err != nil { + return err + } + + return b.generateOrImportAccount("", request) } func (b *GethStatusBackend) ConvertToRegularAccount(mnemonic string, currPassword string, newPassword string) error { diff --git a/mobile/status.go b/mobile/status.go index 2246454cd..53374183f 100644 --- a/mobile/status.go +++ b/mobile/status.go @@ -287,6 +287,31 @@ func CreateAccountAndLogin(requestJSON string) string { return makeJSONResponse(nil) } +func RestoreAccountAndLogin(requestJSON string) string { + var request requests.RestoreAccount + err := json.Unmarshal([]byte(requestJSON), &request) + if err != nil { + return makeJSONResponse(err) + } + + err = request.Validate() + if err != nil { + return makeJSONResponse(err) + } + + api.RunAsync(func() error { + log.Debug("starting a node and restoring account") + err := statusBackend.RestoreAccountAndLogin(&request) + if err != nil { + log.Error("failed to restore account", "error", err) + return err + } + log.Debug("started a node, and restored account") + return nil + }) + return makeJSONResponse(nil) +} + // SaveAccountAndLogin saves account in status-go database.. func SaveAccountAndLogin(accountData, password, settingsJSON, configJSON, subaccountData string) string { var account multiaccounts.Account diff --git a/protocol/requests/create_account.go b/protocol/requests/create_account.go index 812ebc42f..7c5b82a96 100644 --- a/protocol/requests/create_account.go +++ b/protocol/requests/create_account.go @@ -32,6 +32,10 @@ type CreateAccount struct { } func (c *CreateAccount) Validate() error { + return ValidateAccountCreationRequest(*c) +} + +func ValidateAccountCreationRequest(c CreateAccount) error { // TODO(cammellos): Add proper validation for password/displayname/etc if len(c.DisplayName) == 0 { return ErrCreateAccountInvalidDisplayName diff --git a/protocol/requests/restore_account.go b/protocol/requests/restore_account.go new file mode 100644 index 000000000..1095507b1 --- /dev/null +++ b/protocol/requests/restore_account.go @@ -0,0 +1,20 @@ +package requests + +import ( + "errors" +) + +var ErrRestoreAccountInvalidMnemonic = errors.New("restore-account: invalid mnemonic") + +type RestoreAccount struct { + Mnemonic string `json:"mnemonic"` + CreateAccount +} + +func (c *RestoreAccount) Validate() error { + if len(c.Mnemonic) == 0 { + return ErrRestoreAccountInvalidMnemonic + } + + return ValidateAccountCreationRequest(c.CreateAccount) +}