create random accounts in memory for onboarding (#1464)
* add account onboarding struct * add onboarding to account manager * allow resetting onboarding * add onboarding functions to lib and mobile * fix lint warnings * update mnemonic test * remove unused fmt * reset onboarding before selecting account * expose ResetOnboaring to lib and mobile * refactoring * add comment * update StartOnboarding function * remove unused var * update VERSION * fix returned accounts slice
This commit is contained in:
parent
e28d4ef1a3
commit
dd17860302
|
@ -26,6 +26,8 @@ var (
|
||||||
ErrAccountToKeyMappingFailure = errors.New("cannot retrieve a valid key for a given account")
|
ErrAccountToKeyMappingFailure = errors.New("cannot retrieve a valid key for a given account")
|
||||||
ErrNoAccountSelected = errors.New("no account has been selected, please login")
|
ErrNoAccountSelected = errors.New("no account has been selected, please login")
|
||||||
ErrInvalidMasterKeyCreated = errors.New("can not create master extended key")
|
ErrInvalidMasterKeyCreated = errors.New("can not create master extended key")
|
||||||
|
ErrOnboardingNotStarted = errors.New("onboarding must be started before choosing an account")
|
||||||
|
ErrOnboardingAccountNotFound = errors.New("cannot find onboarding account with the given id")
|
||||||
)
|
)
|
||||||
|
|
||||||
// GethServiceProvider provides required geth services.
|
// GethServiceProvider provides required geth services.
|
||||||
|
@ -38,7 +40,10 @@ type GethServiceProvider interface {
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
geth GethServiceProvider
|
geth GethServiceProvider
|
||||||
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
|
|
||||||
|
onboarding *Onboarding
|
||||||
|
|
||||||
selectedWalletAccount *SelectedExtKey // account that was processed during the last call to SelectAccount()
|
selectedWalletAccount *SelectedExtKey // account that was processed during the last call to SelectAccount()
|
||||||
selectedChatAccount *SelectedExtKey // account that was processed during the last call to SelectAccount()
|
selectedChatAccount *SelectedExtKey // account that was processed during the last call to SelectAccount()
|
||||||
}
|
}
|
||||||
|
@ -365,6 +370,55 @@ func (m *Manager) Accounts() ([]gethcommon.Address, error) {
|
||||||
return filtered, nil
|
return filtered, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartOnboarding starts the onboarding process generating accountsCount accounts and returns a slice of OnboardingAccount.
|
||||||
|
func (m *Manager) StartOnboarding(accountsCount, mnemonicPhraseLength int) ([]*OnboardingAccount, error) {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
onboarding, err := NewOnboarding(accountsCount, mnemonicPhraseLength)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
m.onboarding = onboarding
|
||||||
|
|
||||||
|
return m.onboarding.Accounts(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveOnboarding reset the current onboarding struct setting it to nil and deleting the accounts from memory.
|
||||||
|
func (m *Manager) RemoveOnboarding() {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
m.onboarding = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImportOnboardingAccount imports the account specified by id and encrypts it with password.
|
||||||
|
func (m *Manager) ImportOnboardingAccount(id string, password string) (Info, string, error) {
|
||||||
|
var info Info
|
||||||
|
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
if m.onboarding == nil {
|
||||||
|
return info, "", ErrOnboardingNotStarted
|
||||||
|
}
|
||||||
|
|
||||||
|
acc, err := m.onboarding.Account(id)
|
||||||
|
if err != nil {
|
||||||
|
return info, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err = m.RecoverAccount(password, acc.mnemonic)
|
||||||
|
if err != nil {
|
||||||
|
return info, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
m.onboarding = nil
|
||||||
|
|
||||||
|
return info, acc.mnemonic, nil
|
||||||
|
}
|
||||||
|
|
||||||
// refreshSelectedWalletAccount re-populates list of sub-accounts of the currently selected account (if any)
|
// refreshSelectedWalletAccount re-populates list of sub-accounts of the currently selected account (if any)
|
||||||
func (m *Manager) refreshSelectedWalletAccount() {
|
func (m *Manager) refreshSelectedWalletAccount() {
|
||||||
if m.selectedWalletAccount == nil {
|
if m.selectedWalletAccount == nil {
|
||||||
|
|
|
@ -224,6 +224,46 @@ func (s *ManagerTestSuite) TestRecoverAccount() {
|
||||||
s.Equal(errKeyStore, err)
|
s.Equal(errKeyStore, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ManagerTestSuite) TestOnboarding() {
|
||||||
|
// try to choose an account before starting onboarding
|
||||||
|
_, _, err := s.accManager.ImportOnboardingAccount("test-id", "test-password")
|
||||||
|
s.Equal(ErrOnboardingNotStarted, err)
|
||||||
|
|
||||||
|
// generates 5 random accounts
|
||||||
|
count := 5
|
||||||
|
accounts, err := s.accManager.StartOnboarding(count, 24)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Equal(count, len(accounts))
|
||||||
|
|
||||||
|
// try to choose an account with an undefined id
|
||||||
|
_, _, err = s.accManager.ImportOnboardingAccount("test-id", "test-password")
|
||||||
|
s.Equal(ErrOnboardingAccountNotFound, err)
|
||||||
|
|
||||||
|
// choose one account and encrypt it with password
|
||||||
|
password := "test-onboarding-account"
|
||||||
|
account := accounts[0]
|
||||||
|
s.gethServiceProvider.EXPECT().AccountKeyStore().Return(s.keyStore, nil)
|
||||||
|
info, mnemonic, err := s.accManager.ImportOnboardingAccount(account.ID, password)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Equal(account.Info, info)
|
||||||
|
s.Equal(account.mnemonic, mnemonic)
|
||||||
|
s.Nil(s.accManager.onboarding)
|
||||||
|
|
||||||
|
// try to decrypt it with password to check if it's been imported correctly
|
||||||
|
s.gethServiceProvider.EXPECT().AccountKeyStore().Return(s.keyStore, nil)
|
||||||
|
decAccount, _, err := s.accManager.AddressToDecryptedAccount(info.WalletAddress, password)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Equal(info.WalletAddress, decAccount.Address.Hex())
|
||||||
|
|
||||||
|
// try resetting onboarding
|
||||||
|
_, err = s.accManager.StartOnboarding(count, 24)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.NotNil(s.accManager.onboarding)
|
||||||
|
|
||||||
|
s.accManager.RemoveOnboarding()
|
||||||
|
s.Nil(s.accManager.onboarding)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ManagerTestSuite) TestSelectAccount() {
|
func (s *ManagerTestSuite) TestSelectAccount() {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
package account
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/pborman/uuid"
|
||||||
|
"github.com/status-im/status-go/extkeys"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrInvalidMnemonicPhraseLength is returned if the requested mnemonic length is invalid.
|
||||||
|
// Valid lengths are 12, 15, 18, 21, and 24.
|
||||||
|
var ErrInvalidMnemonicPhraseLength = errors.New("mnemonic phrase length; valid lengths are 12, 15, 18, 21, and 24")
|
||||||
|
|
||||||
|
// OnboardingAccount is returned during onboarding and contains its ID and the mnemonic to re-generate the same account Info keys.
|
||||||
|
type OnboardingAccount struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
mnemonic string
|
||||||
|
Info Info `json:"info"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Onboarding is a struct contains a slice of OnboardingAccount.
|
||||||
|
type Onboarding struct {
|
||||||
|
accounts map[string]*OnboardingAccount
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOnboarding returns a new onboarding struct generating n accounts.
|
||||||
|
func NewOnboarding(n, mnemonicPhraseLength int) (*Onboarding, error) {
|
||||||
|
onboarding := &Onboarding{
|
||||||
|
accounts: make(map[string]*OnboardingAccount),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
account, err := onboarding.generateAccount(mnemonicPhraseLength)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
onboarding.accounts[account.ID] = account
|
||||||
|
}
|
||||||
|
|
||||||
|
return onboarding, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accounts return the list of OnboardingAccount generated.
|
||||||
|
func (o *Onboarding) Accounts() []*OnboardingAccount {
|
||||||
|
accounts := make([]*OnboardingAccount, 0)
|
||||||
|
for _, a := range o.accounts {
|
||||||
|
accounts = append(accounts, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
return accounts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account returns an OnboardingAccount by id.
|
||||||
|
func (o *Onboarding) Account(id string) (*OnboardingAccount, error) {
|
||||||
|
account, ok := o.accounts[id]
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrOnboardingAccountNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return account, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Onboarding) generateAccount(mnemonicPhraseLength int) (*OnboardingAccount, error) {
|
||||||
|
entropyStrength, err := mnemonicPhraseLengthToEntropyStrenght(mnemonicPhraseLength)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mnemonic := extkeys.NewMnemonic()
|
||||||
|
mnemonicPhrase, err := mnemonic.MnemonicPhrase(entropyStrength, extkeys.EnglishLanguage)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can not create mnemonic seed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
masterExtendedKey, err := extkeys.NewMaster(mnemonic.MnemonicSeed(mnemonicPhrase, ""))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can not create master extended key: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
walletAddress, walletPubKey, err := o.deriveAccount(masterExtendedKey, extkeys.KeyPurposeWallet, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := Info{
|
||||||
|
WalletAddress: walletAddress,
|
||||||
|
WalletPubKey: walletPubKey,
|
||||||
|
ChatAddress: walletAddress,
|
||||||
|
ChatPubKey: walletPubKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
uuid := uuid.NewRandom().String()
|
||||||
|
|
||||||
|
account := &OnboardingAccount{
|
||||||
|
ID: uuid,
|
||||||
|
mnemonic: mnemonicPhrase,
|
||||||
|
Info: info,
|
||||||
|
}
|
||||||
|
|
||||||
|
return account, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Onboarding) deriveAccount(masterExtendedKey *extkeys.ExtendedKey, purpose extkeys.KeyPurpose, index uint32) (string, string, error) {
|
||||||
|
extendedKey, err := masterExtendedKey.ChildForPurpose(purpose, index)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKeyECDSA := extendedKey.ToECDSA()
|
||||||
|
address := crypto.PubkeyToAddress(privateKeyECDSA.PublicKey)
|
||||||
|
publicKeyHex := hexutil.Encode(crypto.FromECDSAPub(&privateKeyECDSA.PublicKey))
|
||||||
|
|
||||||
|
return address.Hex(), publicKeyHex, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mnemonicPhraseLengthToEntropyStrenght(length int) (extkeys.EntropyStrength, error) {
|
||||||
|
if length < 12 || length > 24 || length%3 != 0 {
|
||||||
|
return 0, ErrInvalidMnemonicPhraseLength
|
||||||
|
}
|
||||||
|
|
||||||
|
bitsLength := length * 11
|
||||||
|
checksumLength := bitsLength % 32
|
||||||
|
|
||||||
|
return extkeys.EntropyStrength(bitsLength - checksumLength), nil
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package account
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/extkeys"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMnemonicPhraseLengthToEntropyStrenght(t *testing.T) {
|
||||||
|
scenarios := []struct {
|
||||||
|
phraseLength int
|
||||||
|
expectedStrength extkeys.EntropyStrength
|
||||||
|
expectedError error
|
||||||
|
}{
|
||||||
|
{12, 128, nil},
|
||||||
|
{15, 160, nil},
|
||||||
|
{18, 192, nil},
|
||||||
|
{21, 224, nil},
|
||||||
|
{24, 256, nil},
|
||||||
|
// invalid
|
||||||
|
{11, 0, ErrInvalidMnemonicPhraseLength},
|
||||||
|
{14, 0, ErrInvalidMnemonicPhraseLength},
|
||||||
|
{25, 0, ErrInvalidMnemonicPhraseLength},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range scenarios {
|
||||||
|
strength, err := mnemonicPhraseLengthToEntropyStrenght(s.phraseLength)
|
||||||
|
assert.Equal(t, s.expectedError, err)
|
||||||
|
assert.Equal(t, s.expectedStrength, strength)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOnboarding(t *testing.T) {
|
||||||
|
count := 2
|
||||||
|
wordsCount := 24
|
||||||
|
o, _ := NewOnboarding(count, wordsCount)
|
||||||
|
assert.Equal(t, count, len(o.accounts))
|
||||||
|
|
||||||
|
for id, a := range o.accounts {
|
||||||
|
words := strings.Split(a.mnemonic, " ")
|
||||||
|
|
||||||
|
assert.Equal(t, wordsCount, len(words))
|
||||||
|
assert.NotEmpty(t, a.Info.WalletAddress)
|
||||||
|
assert.NotEmpty(t, a.Info.WalletPubKey)
|
||||||
|
assert.NotEmpty(t, a.Info.ChatAddress)
|
||||||
|
assert.NotEmpty(t, a.Info.ChatPubKey)
|
||||||
|
|
||||||
|
retrieved, err := o.Account(id)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, a, retrieved)
|
||||||
|
}
|
||||||
|
}
|
|
@ -493,6 +493,8 @@ func (b *StatusBackend) Logout() error {
|
||||||
|
|
||||||
// reSelectAccount selects previously selected account, often, after node restart.
|
// reSelectAccount selects previously selected account, often, after node restart.
|
||||||
func (b *StatusBackend) reSelectAccount() error {
|
func (b *StatusBackend) reSelectAccount() error {
|
||||||
|
b.AccountManager().RemoveOnboarding()
|
||||||
|
|
||||||
selectedChatAccount, err := b.AccountManager().SelectedChatAccount()
|
selectedChatAccount, err := b.AccountManager().SelectedChatAccount()
|
||||||
if selectedChatAccount == nil || err == account.ErrNoAccountSelected {
|
if selectedChatAccount == nil || err == account.ErrNoAccountSelected {
|
||||||
return nil
|
return nil
|
||||||
|
@ -518,6 +520,8 @@ func (b *StatusBackend) SelectAccount(walletAddress, chatAddress, password strin
|
||||||
b.mu.Lock()
|
b.mu.Lock()
|
||||||
defer b.mu.Unlock()
|
defer b.mu.Unlock()
|
||||||
|
|
||||||
|
b.AccountManager().RemoveOnboarding()
|
||||||
|
|
||||||
err := b.accountManager.SelectAccount(walletAddress, chatAddress, password)
|
err := b.accountManager.SelectAccount(walletAddress, chatAddress, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -40,11 +40,11 @@ const (
|
||||||
totalAvailableLanguages
|
totalAvailableLanguages
|
||||||
)
|
)
|
||||||
|
|
||||||
type entropyStrength int
|
type EntropyStrength int
|
||||||
|
|
||||||
// Valid entropy strengths
|
// Valid entropy strengths
|
||||||
const (
|
const (
|
||||||
EntropyStrength128 entropyStrength = 128 + 32*iota
|
EntropyStrength128 EntropyStrength = 128 + 32*iota
|
||||||
EntropyStrength160
|
EntropyStrength160
|
||||||
EntropyStrength192
|
EntropyStrength192
|
||||||
EntropyStrength224
|
EntropyStrength224
|
||||||
|
@ -129,7 +129,7 @@ func (m *Mnemonic) MnemonicSeed(mnemonic string, password string) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MnemonicPhrase returns a human readable seed for BIP32 Hierarchical Deterministic Wallets
|
// MnemonicPhrase returns a human readable seed for BIP32 Hierarchical Deterministic Wallets
|
||||||
func (m *Mnemonic) MnemonicPhrase(strength entropyStrength, language Language) (string, error) {
|
func (m *Mnemonic) MnemonicPhrase(strength EntropyStrength, language Language) (string, error) {
|
||||||
wordList, err := m.WordList(language)
|
wordList, err := m.WordList(language)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
|
@ -45,7 +45,7 @@ func TestMnemonicPhrase(t *testing.T) {
|
||||||
mnemonic := NewMnemonic()
|
mnemonic := NewMnemonic()
|
||||||
|
|
||||||
// test strength validation
|
// test strength validation
|
||||||
strengths := []entropyStrength{127, 129, 257}
|
strengths := []EntropyStrength{127, 129, 257}
|
||||||
for _, s := range strengths {
|
for _, s := range strengths {
|
||||||
_, err := mnemonic.MnemonicPhrase(s, EnglishLanguage)
|
_, err := mnemonic.MnemonicPhrase(s, EnglishLanguage)
|
||||||
if err != ErrInvalidEntropyStrength {
|
if err != ErrInvalidEntropyStrength {
|
||||||
|
|
|
@ -234,6 +234,72 @@ func RecoverAccount(password, mnemonic *C.char) *C.char {
|
||||||
return C.CString(string(outBytes))
|
return C.CString(string(outBytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartOnboarding initialize the onboarding with n random accounts
|
||||||
|
//export StartOnboarding
|
||||||
|
func StartOnboarding(n, mnemonicPhraseLength C.int) *C.char {
|
||||||
|
out := struct {
|
||||||
|
Accounts []OnboardingAccount `json:"accounts"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
}{
|
||||||
|
Accounts: make([]OnboardingAccount, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
accounts, err := statusBackend.AccountManager().StartOnboarding(int(n), int(mnemonicPhraseLength))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
out.Error = err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
for _, account := range accounts {
|
||||||
|
out.Accounts = append(out.Accounts, OnboardingAccount{
|
||||||
|
ID: account.ID,
|
||||||
|
Address: account.Info.WalletAddress,
|
||||||
|
PubKey: account.Info.WalletPubKey,
|
||||||
|
WalletAddress: account.Info.WalletAddress,
|
||||||
|
WalletPubKey: account.Info.WalletPubKey,
|
||||||
|
ChatAddress: account.Info.ChatAddress,
|
||||||
|
ChatPubKey: account.Info.ChatPubKey,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outBytes, _ := json.Marshal(out)
|
||||||
|
return C.CString(string(outBytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImportOnboardingAccount re-creates and imports an account created during onboarding.
|
||||||
|
//export ImportOnboardingAccount
|
||||||
|
func ImportOnboardingAccount(id, password *C.char) *C.char {
|
||||||
|
info, mnemonic, err := statusBackend.AccountManager().ImportOnboardingAccount(C.GoString(id), C.GoString(password))
|
||||||
|
|
||||||
|
errString := ""
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
errString = err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
out := AccountInfo{
|
||||||
|
Address: info.WalletAddress,
|
||||||
|
PubKey: info.WalletPubKey,
|
||||||
|
WalletAddress: info.WalletAddress,
|
||||||
|
WalletPubKey: info.WalletPubKey,
|
||||||
|
ChatAddress: info.ChatAddress,
|
||||||
|
ChatPubKey: info.ChatPubKey,
|
||||||
|
Mnemonic: mnemonic,
|
||||||
|
Error: errString,
|
||||||
|
}
|
||||||
|
outBytes, _ := json.Marshal(out)
|
||||||
|
return C.CString(string(outBytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveOnboarding resets the current onboarding removing from memory all the generated keys.
|
||||||
|
//export RemoveOnboarding
|
||||||
|
func RemoveOnboarding() {
|
||||||
|
statusBackend.AccountManager().RemoveOnboarding()
|
||||||
|
}
|
||||||
|
|
||||||
//VerifyAccountPassword verifies account password
|
//VerifyAccountPassword verifies account password
|
||||||
//export VerifyAccountPassword
|
//export VerifyAccountPassword
|
||||||
func VerifyAccountPassword(keyStoreDir, address, password *C.char) *C.char {
|
func VerifyAccountPassword(keyStoreDir, address, password *C.char) *C.char {
|
||||||
|
|
11
lib/types.go
11
lib/types.go
|
@ -74,6 +74,17 @@ type AccountInfo struct {
|
||||||
Error string `json:"error"`
|
Error string `json:"error"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnboardingAccount represents accounts info generated for the onboarding.
|
||||||
|
type OnboardingAccount struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Address string `json:"address"` // DEPRECATED
|
||||||
|
PubKey string `json:"pubkey"` // DEPRECATED
|
||||||
|
WalletAddress string `json:"walletAddress"`
|
||||||
|
WalletPubKey string `json:"walletPubKey"`
|
||||||
|
ChatAddress string `json:"chatAddress"`
|
||||||
|
ChatPubKey string `json:"chatPubKey"`
|
||||||
|
}
|
||||||
|
|
||||||
// SendDataNotificationResult is a JSON returned from notify message.
|
// SendDataNotificationResult is a JSON returned from notify message.
|
||||||
type SendDataNotificationResult struct {
|
type SendDataNotificationResult struct {
|
||||||
Status bool `json:"status"`
|
Status bool `json:"status"`
|
||||||
|
|
|
@ -238,6 +238,69 @@ func RecoverAccount(password, mnemonic string) string {
|
||||||
return string(outBytes)
|
return string(outBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartOnboarding initialize the onboarding with n random accounts
|
||||||
|
func StartOnboarding(n, mnemonicPhraseLength int) string {
|
||||||
|
out := struct {
|
||||||
|
Accounts []OnboardingAccount `json:"accounts"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
}{
|
||||||
|
Accounts: make([]OnboardingAccount, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
accounts, err := statusBackend.AccountManager().StartOnboarding(n, mnemonicPhraseLength)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
out.Error = err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
for _, account := range accounts {
|
||||||
|
out.Accounts = append(out.Accounts, OnboardingAccount{
|
||||||
|
ID: account.ID,
|
||||||
|
Address: account.Info.WalletAddress,
|
||||||
|
PubKey: account.Info.WalletPubKey,
|
||||||
|
WalletAddress: account.Info.WalletAddress,
|
||||||
|
WalletPubKey: account.Info.WalletPubKey,
|
||||||
|
ChatAddress: account.Info.ChatAddress,
|
||||||
|
ChatPubKey: account.Info.ChatPubKey,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outBytes, _ := json.Marshal(out)
|
||||||
|
return string(outBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
//ImportOnboardingAccount re-creates and imports an account created during onboarding.
|
||||||
|
func ImportOnboardingAccount(id, password string) string {
|
||||||
|
info, mnemonic, err := statusBackend.AccountManager().ImportOnboardingAccount(id, password)
|
||||||
|
|
||||||
|
errString := ""
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
errString = err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
out := AccountInfo{
|
||||||
|
Address: info.WalletAddress,
|
||||||
|
PubKey: info.WalletPubKey,
|
||||||
|
WalletAddress: info.WalletAddress,
|
||||||
|
WalletPubKey: info.WalletPubKey,
|
||||||
|
ChatAddress: info.ChatAddress,
|
||||||
|
ChatPubKey: info.ChatPubKey,
|
||||||
|
Mnemonic: mnemonic,
|
||||||
|
Error: errString,
|
||||||
|
}
|
||||||
|
outBytes, _ := json.Marshal(out)
|
||||||
|
return string(outBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveOnboarding resets the current onboarding removing from memory all the generated keys.
|
||||||
|
func RemoveOnboarding() {
|
||||||
|
statusBackend.AccountManager().RemoveOnboarding()
|
||||||
|
}
|
||||||
|
|
||||||
// VerifyAccountPassword verifies account password.
|
// VerifyAccountPassword verifies account password.
|
||||||
func VerifyAccountPassword(keyStoreDir, address, password string) string {
|
func VerifyAccountPassword(keyStoreDir, address, password string) string {
|
||||||
_, err := statusBackend.AccountManager().VerifyAccountPassword(keyStoreDir, address, password)
|
_, err := statusBackend.AccountManager().VerifyAccountPassword(keyStoreDir, address, password)
|
||||||
|
|
|
@ -74,6 +74,17 @@ type AccountInfo struct {
|
||||||
Error string `json:"error"`
|
Error string `json:"error"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnboardingAccount represents accounts info generated for the onboarding.
|
||||||
|
type OnboardingAccount struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Address string `json:"address"` // DEPRECATED
|
||||||
|
PubKey string `json:"pubkey"` // DEPRECATED
|
||||||
|
WalletAddress string `json:"walletAddress"`
|
||||||
|
WalletPubKey string `json:"walletPubKey"`
|
||||||
|
ChatAddress string `json:"chatAddress"`
|
||||||
|
ChatPubKey string `json:"chatPubKey"`
|
||||||
|
}
|
||||||
|
|
||||||
// NotifyResult is a JSON returned from notify message.
|
// NotifyResult is a JSON returned from notify message.
|
||||||
type NotifyResult struct {
|
type NotifyResult struct {
|
||||||
Status bool `json:"status"`
|
Status bool `json:"status"`
|
||||||
|
|
Loading…
Reference in New Issue