feat(@desktop/onboarding): `Lost Keycard` - start using account without keycard
This commit introduces: - `Start using account without keycard` flow Closes: #7642
This commit is contained in:
parent
b00f0a80b5
commit
841a37e930
|
@ -373,8 +373,7 @@ proc convertSelectedKeyPairToKeycardAccount*(self: Controller, password: string)
|
|||
return
|
||||
let acc = self.accountsService.createAccountFromMnemonic(self.getSeedPhrase(), includeEncryption = true)
|
||||
singletonInstance.localAccountSettings.setStoreToKeychainValue(LS_VALUE_NOT_NOW)
|
||||
self.accountsService.convertToKeycardAccount(self.tmpSelectedKeyPairDto.keyUid,
|
||||
currentPassword = password,
|
||||
self.accountsService.convertToKeycardAccount(currentPassword = password,
|
||||
newPassword = acc.derivedAccounts.encryption.publicKey)
|
||||
|
||||
proc getConvertingProfileSuccess*(self: Controller): bool =
|
||||
|
|
|
@ -338,7 +338,7 @@ proc importMnemonic*(self: Controller): bool =
|
|||
self.delegate.importAccountSuccess()
|
||||
return true
|
||||
else:
|
||||
self.delegate.importAccountError(error)
|
||||
self.delegate.emitStartupError(error, StartupErrorType.ImportAccError)
|
||||
return false
|
||||
|
||||
proc setupKeychain(self: Controller, store: bool) =
|
||||
|
@ -352,7 +352,7 @@ proc setupAccount(self: Controller, accountId: string, storeToKeychain: bool) =
|
|||
self.delegate.moveToLoadingAppState()
|
||||
let error = self.accountsService.setupAccount(accountId, self.tmpPassword, self.tmpDisplayName)
|
||||
if error != "":
|
||||
self.delegate.setupAccountError(error)
|
||||
self.delegate.emitStartupError(error, StartupErrorType.SetupAccError)
|
||||
else:
|
||||
self.setupKeychain(storeToKeychain)
|
||||
|
||||
|
@ -388,7 +388,7 @@ proc setupKeycardAccount*(self: Controller, storeToKeychain: bool, newKeycard: b
|
|||
else:
|
||||
if self.tmpKeycardEvent.keyUid.len == 0 or
|
||||
self.accountsService.openedAccountsContainsKeyUid(self.tmpKeycardEvent.keyUid):
|
||||
self.delegate.importAccountError(ACCOUNT_ALREADY_EXISTS_ERROR)
|
||||
self.delegate.emitStartupError(ACCOUNT_ALREADY_EXISTS_ERROR, StartupErrorType.ImportAccError)
|
||||
return
|
||||
self.delegate.moveToLoadingAppState()
|
||||
if newKeycard:
|
||||
|
@ -441,19 +441,43 @@ proc login*(self: Controller) =
|
|||
if(error.len > 0):
|
||||
self.delegate.emitAccountLoginError(error)
|
||||
|
||||
proc loginAccountKeycard*(self: Controller, storeToKeychain = false, syncWalletAfterLogin = false) =
|
||||
proc loginAccountKeycard*(self: Controller, storeToKeychainValue: string, syncWalletAfterLogin = false) =
|
||||
if syncWalletAfterLogin:
|
||||
self.syncKeycardBasedOnAppWalletStateAfterLogin()
|
||||
singletonInstance.localAccountSettings.setStoreToKeychainValue(storeToKeychainValue)
|
||||
self.delegate.moveToLoadingAppState()
|
||||
let selAcc = self.getSelectedLoginAccount()
|
||||
let error = self.accountsService.loginAccountKeycard(selAcc, self.tmpKeycardEvent)
|
||||
if(error.len > 0):
|
||||
self.delegate.emitAccountLoginError(error)
|
||||
|
||||
proc loginAccountKeycardUsingSeedPhrase*(self: Controller, storeToKeychain: bool) =
|
||||
let acc = self.accountsService.createAccountFromMnemonic(self.getSeedPhrase(), includeEncryption = true, includeWhisper = true)
|
||||
let selAcc = self.getSelectedLoginAccount()
|
||||
|
||||
var kcData = KeycardEvent(
|
||||
keyUid: acc.keyUid,
|
||||
masterKey: KeyDetails(address: acc.address),
|
||||
whisperKey: KeyDetails(privateKey: acc.derivedAccounts.whisper.privateKey),
|
||||
encryptionKey: KeyDetails(publicKey: acc.derivedAccounts.encryption.publicKey)
|
||||
)
|
||||
if acc.derivedAccounts.whisper.privateKey.startsWith("0x"):
|
||||
kcData.whisperKey.privateKey = acc.derivedAccounts.whisper.privateKey[2..^1]
|
||||
|
||||
if storeToKeychain:
|
||||
## storing not now, user will be asked to store the pin once he is logged in
|
||||
singletonInstance.localAccountSettings.setStoreToKeychainValue(LS_VALUE_NOT_NOW)
|
||||
else:
|
||||
singletonInstance.localAccountSettings.setStoreToKeychainValue(LS_VALUE_NEVER)
|
||||
|
||||
self.delegate.moveToLoadingAppState()
|
||||
let error = self.accountsService.loginAccountKeycard(self.tmpKeycardEvent)
|
||||
let error = self.accountsService.loginAccountKeycard(selAcc, kcData)
|
||||
if(error.len > 0):
|
||||
self.delegate.emitAccountLoginError(error)
|
||||
|
||||
proc convertToRegularAccount*(self: Controller): string =
|
||||
let acc = self.accountsService.createAccountFromMnemonic(self.getSeedPhrase(), includeEncryption = true)
|
||||
return self.accountsService.convertToRegularAccount(self.getSeedPhrase(), acc.derivedAccounts.encryption.publicKey, self.getPassword())
|
||||
proc getKeyUidForSeedPhrase*(self: Controller, seedPhrase: string): string =
|
||||
let acc = self.accountsService.createAccountFromMnemonic(seedPhrase)
|
||||
return acc.keyUid
|
||||
|
|
|
@ -29,6 +29,8 @@ method executePrimaryCommand*(self: BiometricsState, controller: Controller) =
|
|||
elif self.flowType == FlowType.LostKeycardReplacement:
|
||||
self.storeToKeychain = storeToKeychain
|
||||
controller.startLoginFlowAutomatically(controller.getPin())
|
||||
elif self.flowType == FlowType.LostKeycardConvertToRegularAccount:
|
||||
controller.loginAccountKeycardUsingSeedPhrase(storeToKeychain)
|
||||
|
||||
method executeSecondaryCommand*(self: BiometricsState, controller: Controller) =
|
||||
let storeToKeychain = false # false, cause we don't have keychain support for other than mac os
|
||||
|
@ -49,6 +51,8 @@ method executeSecondaryCommand*(self: BiometricsState, controller: Controller) =
|
|||
elif self.flowType == FlowType.LostKeycardReplacement:
|
||||
self.storeToKeychain = storeToKeychain
|
||||
controller.startLoginFlowAutomatically(controller.getPin())
|
||||
elif self.flowType == FlowType.LostKeycardConvertToRegularAccount:
|
||||
controller.loginAccountKeycardUsingSeedPhrase(storeToKeychain)
|
||||
|
||||
method resolveKeycardNextState*(self: BiometricsState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
|
@ -56,4 +60,7 @@ method resolveKeycardNextState*(self: BiometricsState, keycardFlowType: string,
|
|||
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
|
||||
keycardEvent.error.len == 0:
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.loginAccountKeycard(self.storeToKeychain, syncWalletAfterLogin = true)
|
||||
var storeToKeychainValue = LS_VALUE_NEVER
|
||||
if self.storeToKeychain:
|
||||
storeToKeychainValue = LS_VALUE_NOT_NOW
|
||||
controller.loginAccountKeycard(storeToKeychainValue, syncWalletAfterLogin = true)
|
|
@ -56,5 +56,6 @@ method resolveKeycardNextState*(self: KeycardEnterPukState, keycardFlowType: str
|
|||
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.setPukValid(true)
|
||||
controller.loginAccountKeycard()
|
||||
let storeToKeychainValue = singletonInstance.localAccountSettings.getStoreToKeychainValue()
|
||||
controller.loginAccountKeycard(storeToKeychainValue)
|
||||
return nil
|
|
@ -44,7 +44,8 @@ method executePrimaryCommand*(self: KeycardPinSetState, controller: Controller)
|
|||
controller.startLoginFlowAutomatically(controller.getPin())
|
||||
return
|
||||
if controller.getValidPuk():
|
||||
controller.loginAccountKeycard()
|
||||
let storeToKeychainValue = singletonInstance.localAccountSettings.getStoreToKeychainValue()
|
||||
controller.loginAccountKeycard(storeToKeychainValue)
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
if main_constants.IS_MACOS:
|
||||
return
|
||||
|
@ -56,10 +57,10 @@ method resolveKeycardNextState*(self: KeycardPinSetState, keycardFlowType: strin
|
|||
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
|
||||
keycardEvent.error.len == 0:
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.loginAccountKeycard(storeToKeychain = true, syncWalletAfterLogin = true)
|
||||
controller.loginAccountKeycard(storeToKeychainValue = LS_VALUE_NOT_NOW, syncWalletAfterLogin = true)
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
|
||||
keycardEvent.error.len == 0:
|
||||
# we are here in case of recover account from the login flow using seed phrase
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.loginAccountKeycard(storeToKeychain = false, syncWalletAfterLogin = false)
|
||||
controller.loginAccountKeycard(storeToKeychainValue = LS_VALUE_NEVER, syncWalletAfterLogin = false)
|
|
@ -10,6 +10,5 @@ proc delete*(self: KeycardWrongKeycardState) =
|
|||
|
||||
method executeBackCommand*(self: KeycardWrongKeycardState, controller: Controller) =
|
||||
if self.flowType == FlowType.FirstRunOldUserKeycardImport or
|
||||
self.flowType == FlowType.AppLogin or
|
||||
self.flowType == FlowType.LostKeycardReplacement:
|
||||
self.flowType == FlowType.AppLogin:
|
||||
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WrongSeedPhrase, add = false))
|
|
@ -59,5 +59,6 @@ method resolveKeycardNextState*(self: KeycardWrongPukState, keycardFlowType: str
|
|||
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.setPukValid(true)
|
||||
controller.loginAccountKeycard()
|
||||
let storeToKeychainValue = singletonInstance.localAccountSettings.getStoreToKeychainValue()
|
||||
controller.loginAccountKeycard(storeToKeychainValue)
|
||||
return nil
|
|
@ -0,0 +1,14 @@
|
|||
type
|
||||
LoginKeycardConvertedToRegularAccountState* = ref object of State
|
||||
|
||||
proc newLoginKeycardConvertedToRegularAccountState*(flowType: FlowType, backState: State): LoginKeycardConvertedToRegularAccountState =
|
||||
result = LoginKeycardConvertedToRegularAccountState()
|
||||
result.setup(flowType, StateType.LoginKeycardConvertedToRegularAccount, backState)
|
||||
|
||||
proc delete*(self: LoginKeycardConvertedToRegularAccountState) =
|
||||
self.State.delete
|
||||
|
||||
method executePrimaryCommand*(self: LoginKeycardConvertedToRegularAccountState, controller: Controller) =
|
||||
if self.flowType == FlowType.LostKeycardConvertToRegularAccount:
|
||||
info "restart the app because of successfully converted keycard account to regular account"
|
||||
quit() # quit the app
|
|
@ -10,4 +10,5 @@ proc delete*(self: LoginKeycardPinVerifiedState) =
|
|||
|
||||
method executePrimaryCommand*(self: LoginKeycardPinVerifiedState, controller: Controller) =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
controller.loginAccountKeycard()
|
||||
let storeToKeychainValue = singletonInstance.localAccountSettings.getStoreToKeychainValue()
|
||||
controller.loginAccountKeycard(storeToKeychainValue)
|
|
@ -19,8 +19,9 @@ method executePrimaryCommand*(self: LostKeycardOptionsState, controller: Control
|
|||
self.setFlowType(FlowType.LostKeycardReplacement)
|
||||
controller.runLoadAccountFlow()
|
||||
|
||||
method executeSecondaryCommand*(self: LostKeycardOptionsState, controller: Controller) =
|
||||
echo "TODO: start using account without keycard..."
|
||||
method getNextSecondaryState*(self: LostKeycardOptionsState, controller: Controller): State =
|
||||
if controller.isSelectedAccountAKeycardAccount():
|
||||
return createState(StateType.UserProfileEnterSeedPhrase, FlowType.LostKeycardConvertToRegularAccount, self)
|
||||
|
||||
method resolveKeycardNextState*(self: LostKeycardOptionsState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
|
|
|
@ -14,6 +14,7 @@ type FlowType* {.pure.} = enum
|
|||
FirstRunOldUserImportSeedPhrase = "FirstRunOldUserImportSeedPhrase"
|
||||
AppLogin = "AppLogin"
|
||||
LostKeycardReplacement = "LostKeycardReplacement"
|
||||
LostKeycardConvertToRegularAccount = "LostKeycardConvertToRegularAccount"
|
||||
|
||||
type StateType* {.pure.} = enum
|
||||
NoState = "NoState"
|
||||
|
@ -29,6 +30,7 @@ type StateType* {.pure.} = enum
|
|||
UserProfileConfirmPassword = "UserProfileConfirmPassword"
|
||||
UserProfileImportSeedPhrase = "UserProfileImportSeedPhrase"
|
||||
UserProfileEnterSeedPhrase = "UserProfileEnterSeedPhrase"
|
||||
UserProfileWrongSeedPhrase = "UserProfileWrongSeedPhrase"
|
||||
Biometrics = "Biometrics"
|
||||
KeycardPluginReader = "KeycardPluginReader"
|
||||
KeycardInsertKeycard = "KeycardInsertKeycard"
|
||||
|
@ -69,6 +71,7 @@ type StateType* {.pure.} = enum
|
|||
LoginKeycardMaxPairingSlotsReached = "LoginKeycardMaxPairingSlotsReached"
|
||||
LoginKeycardEmpty = "LoginKeycardEmpty"
|
||||
LoginNotKeycard = "LoginNotKeycard"
|
||||
LoginKeycardConvertedToRegularAccount = "LoginKeycardConvertedToRegularAccount"
|
||||
ProfileFetching = "ProfileFetching"
|
||||
ProfileFetchingSuccess = "ProfileFetchingSuccess"
|
||||
ProfileFetchingTimeout = "ProfileFetchingTimeout"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import sequtils, sugar, chronicles
|
||||
import ../../../global/global_singleton
|
||||
import ../../../../constants as main_constants
|
||||
import ../../../../app_service/service/keycard/constants
|
||||
import ../controller
|
||||
|
@ -54,12 +55,14 @@ include user_profile_create_password_state
|
|||
include user_profile_create_state
|
||||
include user_profile_create_same_chat_key_state
|
||||
include user_profile_enter_seed_phrase_state
|
||||
include user_profile_wrong_seed_phrase_state
|
||||
include user_profile_import_seed_phrase_state
|
||||
include welcome_state_new_user
|
||||
include welcome_state_old_user
|
||||
include welcome_state
|
||||
include login_state
|
||||
include login_plugin_state
|
||||
include login_keycard_converted_to_regular_account_state
|
||||
include login_keycard_insert_keycard_state
|
||||
include login_keycard_inserted_keycard_state
|
||||
include login_keycard_reading_keycard_state
|
||||
|
|
|
@ -21,6 +21,8 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
|
|||
return newUserProfileImportSeedPhraseState(flowType, backState)
|
||||
if stateToBeCreated == StateType.UserProfileEnterSeedPhrase:
|
||||
return newUserProfileEnterSeedPhraseState(flowType, backState)
|
||||
if stateToBeCreated == StateType.UserProfileWrongSeedPhrase:
|
||||
return newUserProfileWrongSeedPhraseState(flowType, backState)
|
||||
if stateToBeCreated == StateType.Biometrics:
|
||||
return newBiometricsState(flowType, backState)
|
||||
if stateToBeCreated == StateType.KeycardPluginReader:
|
||||
|
@ -73,6 +75,8 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
|
|||
return newLoginState(flowType, backState)
|
||||
if stateToBeCreated == StateType.LoginPlugin:
|
||||
return newLoginPluginState(flowType, backState)
|
||||
if stateToBeCreated == StateType.LoginKeycardConvertedToRegularAccount:
|
||||
return newLoginKeycardConvertedToRegularAccountState(flowType, backState)
|
||||
if stateToBeCreated == StateType.LoginKeycardInsertKeycard:
|
||||
return newLoginKeycardInsertKeycardState(flowType, backState)
|
||||
if stateToBeCreated == StateType.LoginKeycardInsertedKeycard:
|
||||
|
|
|
@ -24,6 +24,8 @@ method executePrimaryCommand*(self: UserProfileConfirmPasswordState, controller:
|
|||
elif self.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
|
||||
controller.storeKeycardAccountAndLogin(storeToKeychain, newKeycard = true)
|
||||
elif self.flowType == FlowType.FirstRunOldUserImportSeedPhrase:
|
||||
controller.storeImportedAccountAndLogin(storeToKeychain = false)
|
||||
controller.storeImportedAccountAndLogin(storeToKeychain)
|
||||
elif self.flowType == FlowType.LostKeycardConvertToRegularAccount:
|
||||
controller.loginAccountKeycardUsingSeedPhrase(storeToKeychain)
|
||||
|
||||
|
||||
|
|
|
@ -32,6 +32,14 @@ method getNextPrimaryState*(self: UserProfileEnterSeedPhraseState, controller: C
|
|||
if self.enteredMnemonicMatchTargetedKeyUid:
|
||||
return createState(StateType.KeycardCreatePin, self.flowType, self)
|
||||
return createState(StateType.KeycardWrongKeycard, self.flowType, self)
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
if self.enteredMnemonicMatchTargetedKeyUid:
|
||||
return createState(StateType.KeycardCreatePin, self.flowType, self)
|
||||
return createState(StateType.UserProfileWrongSeedPhrase, self.flowType, self)
|
||||
if self.flowType == FlowType.LostKeycardConvertToRegularAccount:
|
||||
if self.enteredMnemonicMatchTargetedKeyUid:
|
||||
return createState(StateType.UserProfileCreatePassword, self.flowType, self)
|
||||
return createState(StateType.UserProfileWrongSeedPhrase, self.flowType, self)
|
||||
|
||||
method executePrimaryCommand*(self: UserProfileEnterSeedPhraseState, controller: Controller) =
|
||||
if self.flowType == FlowType.FirstRunNewUserImportSeedPhrase or
|
||||
|
@ -59,6 +67,10 @@ method executePrimaryCommand*(self: UserProfileEnterSeedPhraseState, controller:
|
|||
controller.storeSeedPhraseToKeycard(controller.getSeedPhraseLength(), controller.getSeedPhrase())
|
||||
else:
|
||||
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WrongSeedPhrase, add = true))
|
||||
if self.flowType == FlowType.LostKeycardConvertToRegularAccount:
|
||||
self.enteredMnemonicMatchTargetedKeyUid = controller.keyUidMatchSelectedLoginAccount(keyUid)
|
||||
if not self.enteredMnemonicMatchTargetedKeyUid:
|
||||
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WrongSeedPhrase, add = true))
|
||||
|
||||
method resolveKeycardNextState*(self: UserProfileEnterSeedPhraseState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
type
|
||||
UserProfileWrongSeedPhraseState* = ref object of State
|
||||
|
||||
proc newUserProfileWrongSeedPhraseState*(flowType: FlowType, backState: State): UserProfileWrongSeedPhraseState =
|
||||
result = UserProfileWrongSeedPhraseState()
|
||||
result.setup(flowType, StateType.UserProfileWrongSeedPhrase, backState)
|
||||
|
||||
proc delete*(self: UserProfileWrongSeedPhraseState) =
|
||||
self.State.delete
|
||||
|
||||
method executeBackCommand*(self: UserProfileWrongSeedPhraseState, controller: Controller) =
|
||||
if self.flowType == FlowType.LostKeycardReplacement or
|
||||
self.flowType == FlowType.LostKeycardConvertToRegularAccount:
|
||||
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WrongSeedPhrase, add = false))
|
||||
|
||||
method executePrimaryCommand*(self: UserProfileWrongSeedPhraseState, controller: Controller) =
|
||||
self.executeBackCommand(controller)
|
||||
|
||||
method getNextPrimaryState*(self: UserProfileWrongSeedPhraseState, controller: Controller): State =
|
||||
if self.flowType == FlowType.LostKeycardReplacement or
|
||||
self.flowType == FlowType.LostKeycardConvertToRegularAccount:
|
||||
return self.getBackState()
|
|
@ -5,6 +5,13 @@ from ../../../app_service/service/keycard/service import KeycardEvent, KeyDetail
|
|||
|
||||
const UNIQUE_STARTUP_MODULE_IDENTIFIER* = "SartupModule"
|
||||
|
||||
type
|
||||
StartupErrorType* {.pure.} = enum
|
||||
UnknownType = 0
|
||||
ImportAccError
|
||||
SetupAccError
|
||||
ConvertToRegularAccError
|
||||
|
||||
type
|
||||
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||
|
||||
|
@ -92,15 +99,12 @@ method getPin*(self: AccessInterface): string {.base.} =
|
|||
method getPasswordStrengthScore*(self: AccessInterface, password: string, userName: string): int {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setupAccountError*(self: AccessInterface, error: string) {.base.} =
|
||||
method emitStartupError*(self: AccessInterface, error: string, errType: StartupErrorType) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method validMnemonic*(self: AccessInterface, mnemonic: string): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method importAccountError*(self: AccessInterface, error: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method importAccountSuccess*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
|
|
@ -262,15 +262,12 @@ method getPin*[T](self: Module[T]): string =
|
|||
method getPasswordStrengthScore*[T](self: Module[T], password, userName: string): int =
|
||||
return self.controller.getPasswordStrengthScore(password, userName)
|
||||
|
||||
method setupAccountError*[T](self: Module[T], error: string) =
|
||||
self.view.setupAccountError(error)
|
||||
method emitStartupError*[T](self: Module[T], error: string, errType: StartupErrorType) =
|
||||
self.view.emitStartupError(error, errType)
|
||||
|
||||
method validMnemonic*[T](self: Module[T], mnemonic: string): bool =
|
||||
return self.controller.validMnemonic(mnemonic)
|
||||
|
||||
method importAccountError*[T](self: Module[T], error: string) =
|
||||
self.view.importAccountError(error)
|
||||
|
||||
method importAccountSuccess*[T](self: Module[T]) =
|
||||
self.view.importAccountSuccess()
|
||||
|
||||
|
@ -358,8 +355,15 @@ method startAppAfterDelay*[T](self: Module[T]) =
|
|||
self.view.setCurrentStartupState(newProfileFetchingState(currStateObj.flowType(), nil))
|
||||
self.moveToStartupState()
|
||||
|
||||
proc logoutAndDisplayError[T](self: Module[T], error: string) =
|
||||
proc logoutAndDisplayError[T](self: Module[T], error: string, errType: StartupErrorType) =
|
||||
self.delegate.logout()
|
||||
if self.controller.isSelectedLoginAccountKeycardAccount() and
|
||||
errType == StartupErrorType.ConvertToRegularAccError:
|
||||
self.view.setCurrentStartupState(newLoginState(FlowType.AppLogin, nil))
|
||||
self.controller.runLoginFlow()
|
||||
self.moveToStartupState()
|
||||
self.emitStartupError(error, errType)
|
||||
return
|
||||
self.moveToStartupState()
|
||||
self.emitAccountLoginError(error)
|
||||
|
||||
|
@ -377,12 +381,20 @@ method onNodeLogin*[T](self: Module[T], error: string) =
|
|||
self.delayStartingApp()
|
||||
let err = self.delegate.userLoggedIn()
|
||||
if err.len > 0:
|
||||
self.logoutAndDisplayError(err)
|
||||
self.logoutAndDisplayError(err, StartupErrorType.UnknownType)
|
||||
return
|
||||
elif currStateObj.flowType() == FlowType.LostKeycardConvertToRegularAccount:
|
||||
let err = self.controller.convertToRegularAccount()
|
||||
if err.len > 0:
|
||||
self.logoutAndDisplayError(err, StartupErrorType.ConvertToRegularAccError)
|
||||
return
|
||||
self.delegate.logout()
|
||||
self.view.setCurrentStartupState(newLoginKeycardConvertedToRegularAccountState(currStateObj.flowType(), nil))
|
||||
self.moveToStartupState()
|
||||
else:
|
||||
let err = self.delegate.userLoggedIn()
|
||||
if err.len > 0:
|
||||
self.logoutAndDisplayError(err)
|
||||
self.logoutAndDisplayError(err, StartupErrorType.UnknownType)
|
||||
return
|
||||
self.delegate.finishAppLoading()
|
||||
if currStateObj.flowType() != FlowType.AppLogin:
|
||||
|
@ -393,7 +405,7 @@ method onNodeLogin*[T](self: Module[T], error: string) =
|
|||
if currStateObj.flowType() == FlowType.AppLogin:
|
||||
self.emitAccountLoginError(error)
|
||||
else:
|
||||
self.setupAccountError(error)
|
||||
self.emitStartupError(error, StartupErrorType.SetupAccError)
|
||||
error "login error", methodName="onNodeLogin", errDesription =error
|
||||
|
||||
method onKeycardResponse*[T](self: Module[T], keycardFlowType: string, keycardEvent: KeycardEvent) =
|
||||
|
|
|
@ -192,18 +192,13 @@ QtObject:
|
|||
proc getPasswordStrengthScore*(self: View, password: string, userName: string): int {.slot.} =
|
||||
return self.delegate.getPasswordStrengthScore(password, userName)
|
||||
|
||||
proc accountSetupError*(self: View, error: string) {.signal.}
|
||||
proc setupAccountError*(self: View, error: string) =
|
||||
self.accountSetupError(error)
|
||||
proc startupError*(self: View, error: string, errType: int) {.signal.}
|
||||
proc emitStartupError*(self: View, error: string, errType: StartupErrorType) =
|
||||
self.startupError(error, errType.int)
|
||||
|
||||
proc validMnemonic*(self: View, mnemonic: string): bool {.slot.} =
|
||||
return self.delegate.validMnemonic(mnemonic)
|
||||
|
||||
proc accountImportError*(self: View, error: string) {.signal.}
|
||||
proc importAccountError*(self: View, error: string) =
|
||||
# In QML we can connect to this signal and notify user, before refactoring we didn't have this signal
|
||||
self.accountImportError(error)
|
||||
|
||||
proc accountImportSuccess*(self: View) {.signal.}
|
||||
proc importAccountSuccess*(self: View) =
|
||||
self.importedAccountChanged()
|
||||
|
|
|
@ -8,12 +8,11 @@ type
|
|||
settingsJson: JsonNode
|
||||
hashedCurrentPassword: string
|
||||
newPassword: string
|
||||
keyStoreDir: string
|
||||
|
||||
const convertToKeycardAccountTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[ConvertToKeycardAccountTaskArg](argEncoded)
|
||||
try:
|
||||
let response = status_account.convertToKeycardAccount(arg.keyStoreDir, arg.accountDataJson, arg.settingsJson,
|
||||
let response = status_account.convertToKeycardAccount(arg.accountDataJson, arg.settingsJson,
|
||||
arg.hashedCurrentPassword, arg.newPassword)
|
||||
arg.finish(response)
|
||||
except Exception as e:
|
||||
|
|
|
@ -462,7 +462,7 @@ QtObject:
|
|||
"public-key": whisperPublicKey,
|
||||
"name": alias,
|
||||
"display-name": displayName,
|
||||
"address": whisperAddress,
|
||||
"address": address,
|
||||
"eip1581-address": eip1581Address,
|
||||
"dapps-address": walletAddress,
|
||||
"wallet-root-address": walletRootAddress,
|
||||
|
@ -631,21 +631,15 @@ QtObject:
|
|||
error "error: ", procName="login", errName = e.name, errDesription = e.msg
|
||||
return e.msg
|
||||
|
||||
proc loginAccountKeycard*(self: Service, keycardData: KeycardEvent): string =
|
||||
proc loginAccountKeycard*(self: Service, accToBeLoggedIn: AccountDto, keycardData: KeycardEvent): string =
|
||||
try:
|
||||
self.setKeyStoreDir(keycardData.keyUid)
|
||||
|
||||
let openedAccounts = self.openedAccounts()
|
||||
var accToBeLoggedIn: AccountDto
|
||||
for acc in openedAccounts:
|
||||
if acc.keyUid == keycardData.keyUid:
|
||||
accToBeLoggedIn = acc
|
||||
break
|
||||
|
||||
var accountDataJson = %* {
|
||||
"name": accToBeLoggedIn.name,
|
||||
"address": keycardData.masterKey.address,
|
||||
"key-uid": keycardData.keyUid
|
||||
"key-uid": keycardData.keyUid,
|
||||
"kdfIterations": KDF_ITERATIONS,
|
||||
}
|
||||
var settingsJson: JsonNode
|
||||
self.addKeycardDetails(settingsJson, accountDataJson)
|
||||
|
@ -681,14 +675,12 @@ QtObject:
|
|||
error "error: ", procName="verifyAccountPassword", errName = e.name, errDesription = e.msg
|
||||
|
||||
|
||||
proc convertToKeycardAccount*(self: Service, keyUid: string, currentPassword: string, newPassword: string) =
|
||||
proc convertToKeycardAccount*(self: Service, currentPassword: string, newPassword: string) =
|
||||
var accountDataJson = %* {
|
||||
"name": self.getLoggedInAccount().name,
|
||||
"key-uid": keyUid
|
||||
}
|
||||
var settingsJson = %* {
|
||||
"display-name": self.getLoggedInAccount().name
|
||||
"key-uid": self.getLoggedInAccount().keyUid,
|
||||
"kdfIterations": KDF_ITERATIONS
|
||||
}
|
||||
var settingsJson = %* { }
|
||||
|
||||
self.addKeycardDetails(settingsJson, accountDataJson)
|
||||
|
||||
|
@ -704,7 +696,6 @@ QtObject:
|
|||
slot: "onConvertToKeycardAccount",
|
||||
accountDataJson: accountDataJson,
|
||||
settingsJson: settingsJson,
|
||||
keyStoreDir: self.keyStoreDir,
|
||||
hashedCurrentPassword: hashedCurrentPassword,
|
||||
newPassword: newPassword
|
||||
)
|
||||
|
@ -726,6 +717,20 @@ QtObject:
|
|||
error "error handilng migrated keypair response", errDesription=e.msg
|
||||
self.events.emit(SIGNAL_CONVERTING_PROFILE_KEYPAIR, ResultArgs(success: result))
|
||||
|
||||
proc convertToRegularAccount*(self: Service, mnemonic: string, currentPassword: string, newPassword: string): string =
|
||||
let hashedPassword = hashString(newPassword)
|
||||
try:
|
||||
let response = status_account.convertToRegularAccount(mnemonic, currentPassword, hashedPassword)
|
||||
var errMsg = ""
|
||||
if(response.result.contains("error")):
|
||||
errMsg = response.result["error"].getStr
|
||||
if errMsg.len > 0:
|
||||
error "error: ", procName="convertToRegularAccount", errDesription = errMsg
|
||||
return errMsg
|
||||
except Exception as e:
|
||||
error "error converting to regular account: ", message = e.msg
|
||||
return e.msg
|
||||
|
||||
proc verifyPassword*(self: Service, password: string): bool =
|
||||
try:
|
||||
let hashedPassword = hashString(password)
|
||||
|
|
|
@ -243,16 +243,25 @@ proc saveAccountAndLoginWithKeycard*(chatKey, password: string, account, subacco
|
|||
error "error doing rpc request", methodName = "saveAccountAndLogin", exception=e.msg
|
||||
raise newException(RpcException, e.msg)
|
||||
|
||||
proc convertToKeycardAccount*(keyStoreDir: string, account: JsonNode, settings: JsonNode, password: string, newPassword: string):
|
||||
proc convertToKeycardAccount*(account: JsonNode, settings: JsonNode, password: string, newPassword: string):
|
||||
RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
try:
|
||||
let response = status_go.convertToKeycardAccount(keyStoreDir, $account, $settings, password, newPassword)
|
||||
let response = status_go.convertToKeycardAccount($account, $settings, password, newPassword)
|
||||
result.result = Json.decode(response, JsonNode)
|
||||
|
||||
except RpcException as e:
|
||||
error "error doing rpc request", methodName = "convertToKeycardAccount", exception=e.msg
|
||||
raise newException(RpcException, e.msg)
|
||||
|
||||
proc convertToRegularAccount*(mnemonic: string, currPassword: string, newPassword: string):
|
||||
RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
try:
|
||||
let response = status_go.convertToRegularAccount(mnemonic, currPassword, newPassword)
|
||||
result.result = Json.decode(response, JsonNode)
|
||||
except RpcException as e:
|
||||
error "error doing rpc request", methodName = "convertToRegularAccount", exception=e.msg
|
||||
raise newException(RpcException, e.msg)
|
||||
|
||||
proc login*(name, keyUid: string, kdfIterations: int, hashedPassword, thumbnail, large: string, nodeCfgObj: string):
|
||||
RpcResponse[JsonNode]
|
||||
{.raises: [Exception].} =
|
||||
|
|
|
@ -2,6 +2,10 @@ import QtQuick 2.14
|
|||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Dialogs 1.3
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Popups.Dialog 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import utils 1.0
|
||||
import shared.popups.keycard 1.0
|
||||
|
||||
|
@ -77,6 +81,7 @@ OnboardingBasePage {
|
|||
case Constants.startupState.loginKeycardMaxPairingSlotsReached:
|
||||
case Constants.startupState.loginKeycardEmpty:
|
||||
case Constants.startupState.loginNotKeycard:
|
||||
case Constants.startupState.loginKeycardConvertedToRegularAccount:
|
||||
return loginViewComponent
|
||||
|
||||
case Constants.startupState.keycardPluginReader:
|
||||
|
@ -108,6 +113,7 @@ OnboardingBasePage {
|
|||
case Constants.startupState.keycardMaxPairingSlotsReached:
|
||||
case Constants.startupState.keycardMaxPinRetriesReached:
|
||||
case Constants.startupState.keycardMaxPukRetriesReached:
|
||||
case Constants.startupState.userProfileWrongSeedPhrase:
|
||||
return keycardStateViewComponent
|
||||
|
||||
case Constants.startupState.keycardEnterPuk:
|
||||
|
@ -132,29 +138,40 @@ OnboardingBasePage {
|
|||
|
||||
Connections {
|
||||
target: root.startupStore.startupModuleInst
|
||||
onAccountSetupError: {
|
||||
if (error === Constants.existingAccountError) {
|
||||
msgDialog.title = qsTr("Keys for this account already exist")
|
||||
msgDialog.text = qsTr("Keys for this account already exist and can't be added again. If you've lost your password, passcode or Keycard, uninstall the app, reinstall and access your keys by entering your seed phrase")
|
||||
} else {
|
||||
msgDialog.title = qsTr("Login failed")
|
||||
msgDialog.text = qsTr("Login failed. Please re-enter your password and try again.")
|
||||
onStartupError: {
|
||||
msgDialog.errType = errType
|
||||
if (errType === Constants.startupErrorType.setupAccError) {
|
||||
if (error === Constants.existingAccountError) {
|
||||
msgDialog.title = qsTr("Keys for this account already exist")
|
||||
msgDialog.text = qsTr("Keys for this account already exist and can't be added again. If you've lost\
|
||||
your password, passcode or Keycard, uninstall the app, reinstall and access your keys by entering your seed phrase.")
|
||||
} else {
|
||||
msgDialog.title = qsTr("Login failed")
|
||||
msgDialog.text = qsTr("Login failed. Please re-enter your password and try again.")
|
||||
}
|
||||
}
|
||||
else if (errType === Constants.startupErrorType.importAccError) {
|
||||
if (error === Constants.existingAccountError) {
|
||||
msgDialog.title = qsTr("Keys for this account already exist")
|
||||
msgDialog.text = qsTr("Keys for this account already exist and can't be added again. If you've lost\
|
||||
your password, passcode or Keycard, uninstall the app, reinstall and access your keys by entering your seed phrase. In\
|
||||
case of Keycard try recovering using PUK or reinstall the app and try login with the Keycard option.")
|
||||
} else {
|
||||
msgDialog.title = qsTr("Error importing seed")
|
||||
msgDialog.text = error
|
||||
}
|
||||
}
|
||||
else if (errType === Constants.startupErrorType.convertToRegularAccError) {
|
||||
msgDialog.title = qsTr("Converting account")
|
||||
msgDialog.text = qsTr("Really sorry about this inconvenience.\n\
|
||||
Most likely that your account is damaged while converting to a regular Status account.\n\
|
||||
First try to login after app restart, if that doesn't work, you can alway recover your accout\n\
|
||||
following the \"Add existing Status user\" flow, using your seed phrase.")
|
||||
}
|
||||
|
||||
msgDialog.open()
|
||||
}
|
||||
|
||||
onAccountImportError: {
|
||||
if (error === Constants.existingAccountError) {
|
||||
msgDialog.title = qsTr("Keys for this account already exist")
|
||||
msgDialog.text = qsTr("Keys for this account already exist and can't be added again. If you've lost \
|
||||
your password, passcode or Keycard, uninstall the app, reinstall and access your keys by entering your seed phrase. In \
|
||||
case of Keycard try recovering using PUK or reinstall the app and try login with the Keycard option.")
|
||||
} else {
|
||||
msgDialog.title = qsTr("Error importing seed")
|
||||
msgDialog.text = error
|
||||
}
|
||||
msgDialog.open()
|
||||
}
|
||||
onDisplayKeycardSharedModuleFlow: {
|
||||
keycardPopup.active = true
|
||||
}
|
||||
|
@ -163,13 +180,26 @@ case of Keycard try recovering using PUK or reinstall the app and try login with
|
|||
}
|
||||
}
|
||||
|
||||
MessageDialog {
|
||||
StatusDialog {
|
||||
id: msgDialog
|
||||
title: qsTr("Login failed")
|
||||
text: qsTr("Login failed. Please re-enter your password and try again.")
|
||||
icon: StandardIcon.Critical
|
||||
standardButtons: StandardButton.Ok
|
||||
|
||||
property int errType: Constants.startupErrorType.unknownType
|
||||
property string text: qsTr("Login failed. Please re-enter your password and try again.")
|
||||
|
||||
StatusBaseText {
|
||||
anchors.fill: parent
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
text: msgDialog.text
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
standardButtons: Dialog.Ok
|
||||
onAccepted: {
|
||||
if (msgDialog.errType == Constants.startupErrorType.convertToRegularAccError) {
|
||||
Qt.quit();
|
||||
}
|
||||
console.log("TODO: restart flow...")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -365,6 +365,44 @@ Item {
|
|||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: Constants.keycard.general.fontSize3
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: Constants.startupState.userProfileWrongSeedPhrase
|
||||
when: root.startupStore.currentStartupState.stateType === Constants.startupState.userProfileWrongSeedPhrase
|
||||
PropertyChanges {
|
||||
target: image
|
||||
pattern: Constants.keycardAnimations.strongError.pattern
|
||||
source: ""
|
||||
startImgIndexForTheFirstLoop: Constants.keycardAnimations.strongError.startImgIndexForTheFirstLoop
|
||||
startImgIndexForOtherLoops: Constants.keycardAnimations.strongError.startImgIndexForOtherLoops
|
||||
endImgIndex: Constants.keycardAnimations.strongError.endImgIndex
|
||||
duration: Constants.keycardAnimations.strongError.duration
|
||||
loops: Constants.keycardAnimations.strongError.loops
|
||||
}
|
||||
PropertyChanges {
|
||||
target: title
|
||||
text: qsTr("Seed phrase doesn’t match any user")
|
||||
color: Theme.palette.directColor1
|
||||
font.pixelSize: Constants.keycard.general.fontSize1
|
||||
}
|
||||
PropertyChanges {
|
||||
target: info
|
||||
text: qsTr("The seed phrase you enter needs to match the seed phrase of an existing user on this device")
|
||||
color: Theme.palette.directColor1
|
||||
font.pixelSize: Constants.keycard.general.fontSize2
|
||||
}
|
||||
PropertyChanges {
|
||||
target: button
|
||||
text: qsTr("Try entering seed phrase again")
|
||||
}
|
||||
PropertyChanges {
|
||||
target: link
|
||||
text: ""
|
||||
}
|
||||
PropertyChanges {
|
||||
target: message
|
||||
text: ""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1265,6 +1265,56 @@ Item {
|
|||
text: ""
|
||||
visible: false
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: Constants.startupState.loginKeycardConvertedToRegularAccount
|
||||
when: root.startupStore.currentStartupState.stateType === Constants.startupState.loginKeycardConvertedToRegularAccount
|
||||
PropertyChanges {
|
||||
target: image
|
||||
pattern: Constants.keycardAnimations.strongSuccess.pattern
|
||||
source: ""
|
||||
startImgIndexForTheFirstLoop: Constants.keycardAnimations.strongSuccess.startImgIndexForTheFirstLoop
|
||||
startImgIndexForOtherLoops: Constants.keycardAnimations.strongSuccess.startImgIndexForOtherLoops
|
||||
endImgIndex: Constants.keycardAnimations.strongSuccess.endImgIndex
|
||||
duration: Constants.keycardAnimations.strongSuccess.duration
|
||||
loops: Constants.keycardAnimations.strongSuccess.loops
|
||||
}
|
||||
PropertyChanges {
|
||||
target: userInfo
|
||||
visible: false
|
||||
}
|
||||
PropertyChanges {
|
||||
target: title
|
||||
text: qsTr("Your account has been successfully converted to a non Keycard account")
|
||||
visible: true
|
||||
}
|
||||
PropertyChanges {
|
||||
target: passwordSection
|
||||
visible: false
|
||||
}
|
||||
PropertyChanges {
|
||||
target: pinSection
|
||||
visible: false
|
||||
}
|
||||
PropertyChanges {
|
||||
target: info
|
||||
visible: false
|
||||
}
|
||||
PropertyChanges {
|
||||
target: message
|
||||
text: qsTr("To complete the process close Status and log in with your password")
|
||||
visible: true
|
||||
}
|
||||
PropertyChanges {
|
||||
target: button
|
||||
text: qsTr("Restart app & sign in using your password")
|
||||
visible: true
|
||||
}
|
||||
PropertyChanges {
|
||||
target: link
|
||||
text: ""
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -316,7 +316,8 @@ Item {
|
|||
return qsTr("Recover Keycard")
|
||||
}
|
||||
else if (root.startupStore.currentStartupState.flowType === Constants.startupFlow.firstRunNewUserImportSeedPhraseIntoKeycard ||
|
||||
root.startupStore.currentStartupState.flowType === Constants.startupFlow.lostKeycardReplacement) {
|
||||
root.startupStore.currentStartupState.flowType === Constants.startupFlow.lostKeycardReplacement ||
|
||||
root.startupStore.currentStartupState.flowType === Constants.startupFlow.lostKeycardConvertToRegularAccount) {
|
||||
return qsTr("Next")
|
||||
}
|
||||
return ""
|
||||
|
|
|
@ -6,6 +6,7 @@ import QtQml.Models 2.14
|
|||
import StatusQ.Core 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups.Dialog 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import utils 1.0
|
||||
import shared.popups.keycard 1.0
|
||||
|
|
|
@ -24,6 +24,7 @@ QtObject {
|
|||
readonly property string firstRunOldUserImportSeedPhrase: "FirstRunOldUserImportSeedPhrase"
|
||||
readonly property string appLogin: "AppLogin"
|
||||
readonly property string lostKeycardReplacement: "LostKeycardReplacement"
|
||||
readonly property string lostKeycardConvertToRegularAccount: "LostKeycardConvertToRegularAccount"
|
||||
}
|
||||
|
||||
readonly property QtObject startupState: QtObject {
|
||||
|
@ -40,6 +41,7 @@ QtObject {
|
|||
readonly property string userProfileConfirmPassword: "UserProfileConfirmPassword"
|
||||
readonly property string userProfileImportSeedPhrase: "UserProfileImportSeedPhrase"
|
||||
readonly property string userProfileEnterSeedPhrase: "UserProfileEnterSeedPhrase"
|
||||
readonly property string userProfileWrongSeedPhrase: "UserProfileWrongSeedPhrase"
|
||||
readonly property string biometrics: "Biometrics"
|
||||
readonly property string keycardPluginReader: "KeycardPluginReader"
|
||||
readonly property string keycardInsertKeycard: "KeycardInsertKeycard"
|
||||
|
@ -80,6 +82,7 @@ QtObject {
|
|||
readonly property string loginKeycardMaxPairingSlotsReached: "LoginKeycardMaxPairingSlotsReached"
|
||||
readonly property string loginKeycardEmpty: "LoginKeycardEmpty"
|
||||
readonly property string loginNotKeycard: "LoginNotKeycard"
|
||||
readonly property string loginKeycardConvertedToRegularAccount: "LoginKeycardConvertedToRegularAccount"
|
||||
readonly property string profileFetching: "ProfileFetching"
|
||||
readonly property string profileFetchingSuccess: "ProfileFetchingSuccess"
|
||||
readonly property string profileFetchingTimeout: "ProfileFetchingTimeout"
|
||||
|
@ -731,6 +734,13 @@ QtObject {
|
|||
|
||||
readonly property bool isCppApp: typeof cppApp !== "undefined" ? cppApp : false
|
||||
|
||||
readonly property QtObject startupErrorType: QtObject {
|
||||
readonly property int unknownType: 0
|
||||
readonly property int importAccError: 1
|
||||
readonly property int setupAccError: 2
|
||||
readonly property int convertToRegularAccError: 3
|
||||
}
|
||||
|
||||
readonly property string existingAccountError: "account already exists"
|
||||
readonly property string wrongDerivationPathError: "error parsing derivation path"
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 1d8c32e8557a55c86c35e5d6eaccb321995851a3
|
||||
Subproject commit 8fed87fe272c4b49008cd7cc5950a96cd0751966
|
Loading…
Reference in New Issue