feat(@desktop/syncing): recovering from waku if backed up data refers to a profile migrated to a Keycard

Closes: #11661
This commit is contained in:
Sale Djenic 2023-07-27 15:35:34 +02:00 committed by saledjenic
parent f9685a0a46
commit 2749236a56
38 changed files with 243 additions and 189 deletions

View File

@ -113,7 +113,7 @@ proc applyNecessaryActionsAfterLoggingIn(self: AppController)
# Startup Module Delegate Interface
proc startupDidLoad*(self: AppController)
proc userLoggedIn*(self: AppController, recoverAccount: bool): string
proc userLoggedIn*(self: AppController): string
proc logout*(self: AppController)
proc finishAppLoading*(self: AppController)
proc storeDefaultKeyPairForNewKeycardUser*(self: AppController)
@ -237,7 +237,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
result.generalService,
result.profileService,
result.keycardService,
result.devicesService,
result.devicesService
)
result.mainModule = main_module.newModule[AppController](
result,
@ -401,9 +401,12 @@ proc start*(self: AppController) =
self.startupModule.load()
proc load(self: AppController) =
self.notificationsManager.init()
self.settingsService.init()
self.buildAndRegisterLocalAccountSensitiveSettings()
self.buildAndRegisterUserProfile()
self.notificationsManager.init()
self.profileService.init()
self.nodeConfigurationService.init()
self.mailserversService.init()
@ -428,9 +431,6 @@ proc load(self: AppController) =
singletonInstance.engine.setRootContextProperty("appSettings", self.appSettingsVariant)
singletonInstance.engine.setRootContextProperty("globalUtils", self.globalUtilsVariant)
self.buildAndRegisterLocalAccountSensitiveSettings()
self.buildAndRegisterUserProfile()
self.networkService.init()
self.tokenService.init()
self.currencyService.init()
@ -454,10 +454,10 @@ proc load(self: AppController) =
self.mailserversService,
)
proc userLoggedIn*(self: AppController, recoverAccount: bool): string =
proc userLoggedIn*(self: AppController): string =
try:
self.generalService.startMessenger()
self.statusFoundation.userLoggedIn(recoverAccount)
self.statusFoundation.userLoggedIn()
return ""
except Exception as e:
let errDescription = e.msg

View File

@ -34,7 +34,5 @@ proc initUrlSchemeManager*(self: StatusFoundation, urlSchemeEvent: StatusEvent,
self.urlsManager = newUrlsManager(self.events, urlSchemeEvent, singleInstance,
protocolUriOnStart)
proc userLoggedIn*(self: StatusFoundation, recoverAccount: bool) =
self.urlsManager.userLoggedIn()
if recoverAccount:
self.signalsManager.doHandlingForDataComingFromWakuBackup()
proc userLoggedIn*(self: StatusFoundation) =
self.urlsManager.userLoggedIn()

View File

@ -9,7 +9,6 @@ logScope:
QtObject:
type SignalsManager* = ref object of QObject
events: EventEmitter
ignoreBackedUpData: bool
#################################################
# Forward declaration section
@ -26,10 +25,6 @@ QtObject:
new(result)
result.setup()
result.events = events
result.ignoreBackedUpData = true
proc doHandlingForDataComingFromWakuBackup*(self: SignalsManager) =
self.ignoreBackedUpData = false
proc processSignal(self: SignalsManager, statusSignal: string) =
var jsonSignal: JsonNode
@ -55,14 +50,6 @@ QtObject:
if(signal.signalType == SignalType.NodeCrashed):
error "node.crashed", error=statusSignal
if self.ignoreBackedUpData and
(signal.signalType == SignalType.WakuFetchingBackupProgress or
signal.signalType == SignalType.WakuBackedUpProfile or
signal.signalType == SignalType.WakuBackedUpSettings or
signal.signalType == SignalType.WakuBackedUpKeypair or
signal.signalType == SignalType.WakuBackedUpWatchOnlyAccount):
return
self.events.emit(signal.signalType.event, signal)
proc receiveSignal(self: SignalsManager, signal: string) {.slot.} =

View File

@ -1174,7 +1174,7 @@ method onStatusUrlRequested*[T](self: Module[T], action: StatusUrlAction, commun
if singletonInstance.utils().isCompressedPubKey(userId):
let contactPk = singletonInstance.utils().getDecompressedPk(userId)
self.switchToContactOrDisplayUserProfile(contactPk)
else:
else:
self.resolveENS(userId, "", STATUS_URL_ENS_RESOLVE_REASON & $StatusUrlAction.DisplayUserProfile)
elif(action == StatusUrlAction.OpenCommunity):

View File

@ -2,11 +2,12 @@ import chronicles
import io_interface
import ../../../../core/eventemitter
import app/core/eventemitter
import ../../../shared_modules/keycard_popup/io_interface as keycard_shared_module
import ../../../../../app_service/service/contacts/service as contact_service
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import app/modules/shared_modules/keycard_popup/io_interface as keycard_shared_module
import app_service/service/contacts/service as contact_service
import app_service/service/wallet_account/service as wallet_account_service
import app_service/service/settings/service as settings_service
logScope:
topics = "profile-section-keycard-module-controller"
@ -48,9 +49,15 @@ proc init*(self: Controller) =
let args = KeypairArgs(e)
self.delegate.onKeypairSynced(args.keypair)
self.events.on(SIGNAL_DISPLAY_NAME_UPDATED) do(e: Args):
self.delegate.onLoggedInUserNameChanged()
self.events.on(SIGNAL_LOGGEDIN_USER_IMAGE_CHANGED) do(e: Args):
self.delegate.onLoggedInUserImageChanged()
self.events.on(SIGNAL_KEYCARD_REBUILD) do(e: Args):
self.delegate.rebuildAllKeycards()
self.events.on(SIGNAL_NEW_KEYCARD_SET) do(e: Args):
let args = KeycardArgs(e)
if not args.success:

View File

@ -65,6 +65,9 @@ method runCreateNewPairingCodePopup*(self: AccessInterface, keyUid: string) {.ba
method onLoggedInUserImageChanged*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method onLoggedInUserNameChanged*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method rebuildAllKeycards*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -3,20 +3,20 @@ import NimQml, chronicles, json, marshal, sequtils, sugar, strutils
import ./io_interface, ./view, ./controller
import ../io_interface as delegate_interface
import ../../../../global/app_translatable_constants as atc
import ../../../../global/global_singleton
import ../../../../core/eventemitter
import app/global/app_translatable_constants as atc
import app/global/global_singleton
import app/core/eventemitter
import ../../../../../app_service/service/keycard/service as keycard_service
import ../../../../../app_service/service/settings/service as settings_service
import ../../../../../app_service/service/network/service as network_service
import ../../../../../app_service/service/privacy/service as privacy_service
import ../../../../../app_service/service/accounts/service as accounts_service
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../../app_service/service/keychain/service as keychain_service
import app_service/service/keycard/service as keycard_service
import app_service/service/settings/service as settings_service
import app_service/service/network/service as network_service
import app_service/service/privacy/service as privacy_service
import app_service/service/accounts/service as accounts_service
import app_service/service/wallet_account/service as wallet_account_service
import app_service/service/keychain/service as keychain_service
import ../../../shared_modules/keycard_popup/module as keycard_shared_module
import ../../../shared_modules/keycard_popup/models/keycard_model
import app/modules/shared_modules/keycard_popup/module as keycard_shared_module
import app/modules/shared_modules/keycard_popup/models/keycard_model
export io_interface
@ -285,11 +285,14 @@ proc buildKeycardList(self: Module) =
if items.len > 0:
self.view.setKeycardItems(items)
method onLoggedInUserNameChanged*(self: Module) =
self.view.keycardModel().setName(singletonInstance.userProfile.getKeyUid(), singletonInstance.userProfile.getName())
method onLoggedInUserImageChanged*(self: Module) =
self.view.keycardModel().setImage(singletonInstance.userProfile.getPubKey(), singletonInstance.userProfile.getIcon())
self.view.keycardModel().setImage(singletonInstance.userProfile.getKeyUid(), singletonInstance.userProfile.getIcon())
if self.view.keycardDetailsModel().isNil:
return
self.view.keycardDetailsModel().setImage(singletonInstance.userProfile.getPubKey(), singletonInstance.userProfile.getIcon())
self.view.keycardDetailsModel().setImage(singletonInstance.userProfile.getKeyUid(), singletonInstance.userProfile.getIcon())
method resolveRelatedKeycardsForKeypair(self: Module, keypair: KeypairDto) =
if keypair.keyUid.len == 0:

View File

@ -200,6 +200,9 @@ proc switchToWalletSection*(self: Controller) =
let data = ActiveSectionChatArgs(sectionId: conf.WALLET_SECTION_ID)
self.events.emit(SIGNAL_MAKE_SECTION_CHAT_ACTIVE, data)
proc rebuildKeycards*(self: Controller) =
self.events.emit(SIGNAL_KEYCARD_REBUILD, Args())
proc getKeycardData*(self: Controller): string =
return self.delegate.getKeycardData()

View File

@ -24,6 +24,7 @@ type PredefinedKeycardData* {.pure.} = enum
UseGeneralMessageForLockedState = 64
MaxPUKReached = 128
CopyFromAKeycardPartDone = 256
MaxPairingSlotsReached = 512
# Forward declaration
# General section
@ -89,11 +90,11 @@ include max_pin_retries_reached_state
include max_puk_retries_reached_state
include max_pairing_slots_reached_state
include migrating_key_pair_state
include no_pcsc_service_state
include not_keycard_state
include no_pcsc_service_state
include not_keycard_state
include pin_set_state
include pin_verified_state
include plugin_reader_state
include plugin_reader_state
include reading_keycard_state
include recognized_keycard_state
include remove_keycard_state

View File

@ -110,18 +110,24 @@ QtObject:
return self.items[i]
return nil
proc findIndexForMember(self: KeycardModel, pubKey: string): int =
proc findIndexForKeyUid(self: KeycardModel, keyUid: string): int =
for i in 0 ..< self.items.len:
if(self.items[i].getPubKey() == pubKey):
if(self.items[i].getKeyUid() == keyUid):
return i
return -1
proc setImage*(self: KeycardModel, pubKey: string, image: string) =
let ind = self.findIndexForMember(pubKey)
proc setImage*(self: KeycardModel, keyUid: string, image: string) =
let ind = self.findIndexForKeyUid(keyUid)
if(ind == -1):
return
self.items[ind].setImage(image)
proc setName*(self: KeycardModel, keyUid: string, name: string) =
let ind = self.findIndexForKeyUid(keyUid)
if(ind == -1):
return
self.items[ind].setName(name)
proc setLockedForKeycardWithKeycardUid*(self: KeycardModel, keycardUid: string, locked: bool) =
for i in 0 ..< self.items.len:
if(self.items[i].getKeycardUid() == keycardUid):

View File

@ -287,6 +287,7 @@ proc handleKeycardSyncing[T](self: Module[T]) =
elif alreadySetKeycards.len > 1:
error "it's impossible to have more then one keycard with the same uid", keycarUid=flowEvent.instanceUID
self.controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)
self.controller.rebuildKeycards()
method syncKeycardBasedOnAppState*[T](self: Module[T], keyUid: string, pin: string) =
## This method must not be called directly. If you want to initiate keycard syncing please emit

View File

@ -2,19 +2,19 @@ import Tables, chronicles, strutils, os
import uuids
import io_interface
import ../../../constants as main_constants
import ../../global/global_singleton
import ../../core/signals/types
import ../../core/eventemitter
import ../../../app_service/service/general/service as general_service
import ../../../app_service/service/accounts/service as accounts_service
import ../../../app_service/service/keychain/service as keychain_service
import ../../../app_service/service/profile/service as profile_service
import ../../../app_service/service/keycard/service as keycard_service
import ../../../app_service/service/devices/service as devices_service
import ../../../app_service/common/[account_constants, utils]
import constants as main_constants
import app/global/global_singleton
import app/core/signals/types
import app/core/eventemitter
import app_service/service/general/service as general_service
import app_service/service/accounts/service as accounts_service
import app_service/service/keychain/service as keychain_service
import app_service/service/profile/service as profile_service
import app_service/service/keycard/service as keycard_service
import app_service/service/devices/service as devices_service
import app_service/common/[account_constants, utils]
import ../shared_modules/keycard_popup/io_interface as keycard_shared_module
import app/modules/shared_modules/keycard_popup/io_interface as keycard_shared_module
logScope:
topics = "startup-controller"
@ -54,7 +54,7 @@ type
tmpKeycardEvent: KeycardEvent
tmpCardMetadata: CardMetadata
tmpKeychainErrorOccurred: bool
tmpRecoverUsingSeedPhraseWhileLogin: bool
tmpRecoverKeycardUsingSeedPhraseWhileLoggingIn: bool
tmpConnectionString: string
localPairingStatus: LocalPairingStatus
@ -79,7 +79,7 @@ proc newController*(delegate: io_interface.AccessInterface,
result.tmpPinMatch = false
result.tmpSeedPhraseLength = 0
result.tmpKeychainErrorOccurred = false
result.tmpRecoverUsingSeedPhraseWhileLogin = false
result.tmpRecoverKeycardUsingSeedPhraseWhileLoggingIn = false
result.tmpSelectedLoginAccountIsKeycardAccount = false
# Forward declaration
@ -129,12 +129,12 @@ proc disconnect*(self: Controller) =
proc delete*(self: Controller) =
self.disconnect()
self.cleanTmpData()
proc init*(self: Controller) =
var handlerId = self.events.onWithUUID(SignalType.NodeLogin.event) do(e:Args):
let signal = NodeSignal(e)
self.delegate.onNodeLogin(signal.error)
self.cleanTmpData()
self.connectionIds.add(handlerId)
handlerId = self.events.onWithUUID(SignalType.NodeStopped.event) do(e:Args):
@ -195,8 +195,8 @@ proc storeProfileDataAndProceedWithAppLoading*(self: Controller) =
self.accountsService.updateLoggedInAccount(self.tmpDisplayName, images)
self.delegate.finishAppLoading()
proc checkFetchingStatusAndProceedWithAppLoading*(self: Controller) =
self.delegate.checkFetchingStatusAndProceedWithAppLoading()
proc checkFetchingStatusAndProceed*(self: Controller) =
self.delegate.checkFetchingStatusAndProceed()
proc getGeneratedAccounts*(self: Controller): seq[GeneratedAccountDto] =
return self.accountsService.generatedAccounts()
@ -309,11 +309,11 @@ proc syncKeycardBasedOnAppWalletStateAfterLogin(self: Controller) =
proc keychainErrorOccurred*(self: Controller): bool =
return self.tmpKeychainErrorOccurred
proc setRecoverUsingSeedPhraseWhileLogin*(self: Controller, value: bool) =
self.tmpRecoverUsingSeedPhraseWhileLogin = value
proc setRecoverKeycardUsingSeedPhraseWhileLoggingIn*(self: Controller, value: bool) =
self.tmpRecoverKeycardUsingSeedPhraseWhileLoggingIn = value
proc getRecoverUsingSeedPhraseWhileLogin*(self: Controller): bool =
return self.tmpRecoverUsingSeedPhraseWhileLogin
proc getRecoverKeycardUsingSeedPhraseWhileLoggingIn*(self: Controller): bool =
return self.tmpRecoverKeycardUsingSeedPhraseWhileLoggingIn
proc cleanTmpData(self: Controller) =
self.tmpProfileImageDetails = ProfileImageDetails()
@ -328,7 +328,7 @@ proc cleanTmpData(self: Controller) =
self.setSeedPhrase("")
self.setKeyUid("")
self.setKeycardEvent(KeycardEvent())
self.setRecoverUsingSeedPhraseWhileLogin(false)
self.setRecoverKeycardUsingSeedPhraseWhileLoggingIn(false)
proc tryToObtainDataFromKeychain*(self: Controller) =
## This proc is used to fetch pass/pin from the keychain while user is trying to login.
@ -406,22 +406,37 @@ proc storeKeycardAccountAndLogin*(self: Controller, storeToKeychain: bool, newKe
else:
error "an error ocurred while importing mnemonic"
proc setupKeycardAccount*(self: Controller, storeToKeychain: bool, newKeycard: bool, recoverAccount: bool = false) =
proc setupKeycardAccount*(self: Controller, storeToKeychain: bool, recoverAccount: bool = false) =
if self.tmpKeycardEvent.keyUid.len == 0 or
self.accountsService.openedAccountsContainsKeyUid(self.tmpKeycardEvent.keyUid):
self.delegate.emitStartupError(ACCOUNT_ALREADY_EXISTS_ERROR, StartupErrorType.ImportAccError)
return
if self.tmpSeedPhrase.len > 0:
# if `tmpSeedPhrase` is not empty means user has recovered keycard via seed phrase
self.storeKeycardAccountAndLogin(storeToKeychain, newKeycard)
else:
if self.tmpKeycardEvent.keyUid.len == 0 or
self.accountsService.openedAccountsContainsKeyUid(self.tmpKeycardEvent.keyUid):
self.delegate.emitStartupError(ACCOUNT_ALREADY_EXISTS_ERROR, StartupErrorType.ImportAccError)
return
self.delegate.moveToLoadingAppState()
if newKeycard:
self.delegate.storeDefaultKeyPairForNewKeycardUser()
else:
self.syncKeycardBasedOnAppWalletStateAfterLogin()
self.accountsService.setupAccountKeycard(self.tmpKeycardEvent, self.tmpDisplayName, useImportedAcc = false, recoverAccount)
self.setupKeychain(storeToKeychain)
let accFromSeedPhrase = self.accountsService.createAccountFromMnemonic(self.tmpSeedPhrase, includeEncryption = true,
includeWhisper = true, includeRoot = true, includeDefaultWallet = true, includeEip1581 = true)
self.tmpKeycardEvent.masterKey.privateKey = accFromSeedPhrase.privateKey
self.tmpKeycardEvent.masterKey.publicKey = accFromSeedPhrase.publicKey
self.tmpKeycardEvent.masterKey.address = accFromSeedPhrase.address
self.tmpKeycardEvent.whisperKey.privateKey = accFromSeedPhrase.derivedAccounts.whisper.privateKey
self.tmpKeycardEvent.whisperKey.publicKey = accFromSeedPhrase.derivedAccounts.whisper.publicKey
self.tmpKeycardEvent.whisperKey.address = accFromSeedPhrase.derivedAccounts.whisper.address
self.tmpKeycardEvent.walletKey.privateKey = accFromSeedPhrase.derivedAccounts.defaultWallet.privateKey
self.tmpKeycardEvent.walletKey.publicKey = accFromSeedPhrase.derivedAccounts.defaultWallet.publicKey
self.tmpKeycardEvent.walletKey.address = accFromSeedPhrase.derivedAccounts.defaultWallet.address
self.tmpKeycardEvent.walletRootKey.privateKey = accFromSeedPhrase.derivedAccounts.walletRoot.privateKey
self.tmpKeycardEvent.walletRootKey.publicKey = accFromSeedPhrase.derivedAccounts.walletRoot.publicKey
self.tmpKeycardEvent.walletRootKey.address = accFromSeedPhrase.derivedAccounts.walletRoot.address
self.tmpKeycardEvent.eip1581Key.privateKey = accFromSeedPhrase.derivedAccounts.eip1581.privateKey
self.tmpKeycardEvent.eip1581Key.publicKey = accFromSeedPhrase.derivedAccounts.eip1581.publicKey
self.tmpKeycardEvent.eip1581Key.address = accFromSeedPhrase.derivedAccounts.eip1581.address
self.tmpKeycardEvent.encryptionKey.privateKey = accFromSeedPhrase.derivedAccounts.encryption.privateKey
self.tmpKeycardEvent.encryptionKey.publicKey = accFromSeedPhrase.derivedAccounts.encryption.publicKey
self.tmpKeycardEvent.encryptionKey.address = accFromSeedPhrase.derivedAccounts.encryption.address
self.delegate.moveToLoadingAppState()
self.syncKeycardBasedOnAppWalletStateAfterLogin()
self.accountsService.setupAccountKeycard(self.tmpKeycardEvent, self.tmpDisplayName, useImportedAcc = false, recoverAccount)
self.setupKeychain(storeToKeychain)
proc getOpenedAccounts*(self: Controller): seq[AccountDto] =
return self.accountsService.openedAccounts()

View File

@ -25,7 +25,7 @@ method executePrimaryCommand*(self: BiometricsState, controller: Controller) =
elif self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
controller.storeKeycardAccountAndLogin(storeToKeychain, newKeycard = true)
elif self.flowType == FlowType.FirstRunOldUserKeycardImport:
controller.setupKeycardAccount(storeToKeychain, newKeycard = false, recoverAccount = true)
controller.setupKeycardAccount(storeToKeychain, recoverAccount = true)
elif self.flowType == FlowType.LostKeycardReplacement:
self.storeToKeychain = storeToKeychain
controller.startLoginFlowAutomatically(controller.getPin())
@ -47,7 +47,7 @@ method executeSecondaryCommand*(self: BiometricsState, controller: Controller) =
elif self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
controller.storeKeycardAccountAndLogin(storeToKeychain, newKeycard = true)
elif self.flowType == FlowType.FirstRunOldUserKeycardImport:
controller.setupKeycardAccount(storeToKeychain, newKeycard = false, recoverAccount = true)
controller.setupKeycardAccount(storeToKeychain, recoverAccount = true)
elif self.flowType == FlowType.LostKeycardReplacement:
self.storeToKeychain = storeToKeychain
controller.startLoginFlowAutomatically(controller.getPin())

View File

@ -17,7 +17,7 @@ method getNextPrimaryState*(self: KeycardEnterPinState, controller: Controller):
return createState(StateType.UserProfileCreate, self.flowType, self.getBackState)
elif self.flowType == FlowType.FirstRunOldUserKeycardImport:
return nil
method executeBackCommand*(self: KeycardEnterPinState, controller: Controller) =
controller.setPin("")
@ -27,36 +27,36 @@ method executePrimaryCommand*(self: KeycardEnterPinState, controller: Controller
if self.pinValid:
controller.enterKeycardPin(controller.getPin())
method resolveKeycardNextState*(self: KeycardEnterPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
method resolveKeycardNextState*(self: KeycardEnterPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueEnterPIN and
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPIN:
controller.setRemainingAttempts(keycardEvent.pinRetries)
if keycardEvent.pinRetries > 0:
return createState(StateType.KeycardWrongPin, self.flowType, self.getBackState)
return createState(StateType.KeycardMaxPinRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueEnterPUK and
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len == 0:
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
return createState(StateType.KeycardMaxPinRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.MaxPUKReached, add = true))
return createState(StateType.KeycardMaxPukRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamFreeSlots:
return createState(StateType.KeycardMaxPairingSlotsReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
controller.setKeycardEvent(keycardEvent)
if not main_constants.IS_MACOS:
controller.setupKeycardAccount(storeToKeychain = false, newKeycard = false)
controller.setupKeycardAccount(storeToKeychain = false)
return nil
let backState = findBackStateWithTargetedStateType(self, StateType.RecoverOldUser)
return createState(StateType.Biometrics, self.flowType, backState)

View File

@ -16,17 +16,17 @@ method executePrimaryCommand*(self: KeycardEnterPukState, controller: Controller
if controller.getPuk().len == PUKLengthForStatusApp:
controller.enterKeycardPuk(controller.getPuk())
method resolveKeycardNextState*(self: KeycardEnterPukState, keycardFlowType: string, keycardEvent: KeycardEvent,
method resolveKeycardNextState*(self: KeycardEnterPukState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueEnterNewPIN and
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorUnblocking:
return createState(StateType.KeycardCreatePin, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueEnterPUK and
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUK:
controller.setRemainingAttempts(keycardEvent.pukRetries)
@ -37,16 +37,16 @@ method resolveKeycardNextState*(self: KeycardEnterPukState, keycardFlowType: str
controller.setKeycardEvent(keycardEvent)
controller.setPukValid(true)
if not main_constants.IS_MACOS:
controller.setupKeycardAccount(storeToKeychain = false, newKeycard = false)
controller.setupKeycardAccount(storeToKeychain = false)
return nil
let backState = findBackStateWithTargetedStateType(self, StateType.RecoverOldUser)
return createState(StateType.Biometrics, self.flowType, backState)
if self.flowType == FlowType.AppLogin:
if keycardFlowType == ResponseTypeValueEnterNewPIN and
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorUnblocking:
return createState(StateType.KeycardCreatePin, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueEnterPUK and
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUK:
controller.setRemainingAttempts(keycardEvent.pukRetries)

View File

@ -24,7 +24,7 @@ method getNextPrimaryState*(self: KeycardPinSetState, controller: Controller): S
return createState(StateType.Biometrics, self.flowType, self.getBackState)
return createState(StateType.KeycardWrongPuk, self.flowType, self.getBackState)
if self.flowType == FlowType.AppLogin:
if controller.getRecoverUsingSeedPhraseWhileLogin():
if controller.getRecoverKeycardUsingSeedPhraseWhileLoggingIn():
return nil
if not controller.getValidPuk():
return createState(StateType.KeycardWrongPuk, self.flowType, self.getBackState)
@ -38,9 +38,9 @@ method executePrimaryCommand*(self: KeycardPinSetState, controller: Controller)
if main_constants.IS_MACOS:
return
if controller.getValidPuk():
controller.setupKeycardAccount(storeToKeychain = false, newKeycard = false)
controller.setupKeycardAccount(storeToKeychain = false)
if self.flowType == FlowType.AppLogin:
if controller.getRecoverUsingSeedPhraseWhileLogin():
if controller.getRecoverKeycardUsingSeedPhraseWhileLoggingIn():
controller.startLoginFlowAutomatically(controller.getPin())
return
if controller.getValidPuk():

View File

@ -11,11 +11,11 @@ proc delete*(self: KeycardRecoverState) =
method getNextPrimaryState*(self: KeycardRecoverState, controller: Controller): State =
if self.flowType == FlowType.FirstRunOldUserKeycardImport or
self.flowType == FlowType.AppLogin:
controller.setRecoverUsingSeedPhraseWhileLogin(true)
controller.setRecoverKeycardUsingSeedPhraseWhileLoggingIn(true)
return createState(StateType.UserProfileEnterSeedPhrase, self.flowType, self)
method getNextSecondaryState*(self: KeycardRecoverState, controller: Controller): State =
if self.flowType == FlowType.FirstRunOldUserKeycardImport or
self.flowType == FlowType.AppLogin:
controller.setRecoverUsingSeedPhraseWhileLogin(false)
controller.setRecoverKeycardUsingSeedPhraseWhileLoggingIn(false)
return createState(StateType.KeycardEnterPuk, self.flowType, self)

View File

@ -23,7 +23,7 @@ method executePrimaryCommand*(self: KeycardRepeatPinState, controller: Controlle
return
if self.flowType == FlowType.FirstRunOldUserKeycardImport or
self.flowType == FlowType.AppLogin:
if controller.getRecoverUsingSeedPhraseWhileLogin():
if controller.getRecoverKeycardUsingSeedPhraseWhileLoggingIn():
controller.runGetMetadataFlow()
return
controller.storePinToKeycard(controller.getPin(), puk = "")
@ -32,19 +32,19 @@ method executePrimaryCommand*(self: KeycardRepeatPinState, controller: Controlle
controller.storePinToKeycard(controller.getPin(), puk = "")
return
method resolveKeycardNextState*(self: KeycardRepeatPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
method resolveKeycardNextState*(self: KeycardRepeatPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
if keycardFlowType == ResponseTypeValueEnterMnemonic and
if keycardFlowType == ResponseTypeValueEnterMnemonic and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorLoadingKeys:
controller.buildSeedPhrasesFromIndexes(keycardEvent.seedPhraseIndexes)
return createState(StateType.KeycardPinSet, self.flowType, self.getBackState)
if self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.keyUid.len > 0:
controller.setKeyUid(keycardEvent.keyUid)
let backState = findBackStateWithTargetedStateType(self, StateType.UserProfileImportSeedPhrase)
@ -60,7 +60,7 @@ method resolveKeycardNextState*(self: KeycardRepeatPinState, keycardFlowType: st
return
if controller.getCurrentKeycardServiceFlow() == KCSFlowType.RecoverAccount or
controller.getCurrentKeycardServiceFlow() == KCSFlowType.LoadAccount:
if keycardFlowType == ResponseTypeValueEnterPUK:
if keycardFlowType == ResponseTypeValueEnterPUK:
if keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUK:
controller.setRemainingAttempts(keycardEvent.pukRetries)
@ -68,19 +68,19 @@ method resolveKeycardNextState*(self: KeycardRepeatPinState, keycardFlowType: st
if keycardEvent.pukRetries > 0:
return createState(StateType.KeycardPinSet, self.flowType, self.getBackState)
return createState(StateType.KeycardMaxPukRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.MaxPUKReached, add = true))
return createState(StateType.KeycardMaxPukRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamFreeSlots:
return createState(StateType.KeycardMaxPairingSlotsReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
controller.setKeycardEvent(keycardEvent)
controller.setPukValid(true)
if controller.getRecoverUsingSeedPhraseWhileLogin():
if controller.getRecoverKeycardUsingSeedPhraseWhileLoggingIn():
controller.addToKeycardUidPairsToCheckForAChangeAfterLogin(self.oldKeycardUid, keycardEvent.instanceUID)
let md = controller.getMetadataFromKeycard()
let paths = md.walletAccounts.map(a => a.path)
@ -104,7 +104,7 @@ method resolveKeycardNextState*(self: KeycardRepeatPinState, keycardFlowType: st
return
if controller.getCurrentKeycardServiceFlow() == KCSFlowType.Login or
controller.getCurrentKeycardServiceFlow() == KCSFlowType.LoadAccount:
if keycardFlowType == ResponseTypeValueEnterPUK:
if keycardFlowType == ResponseTypeValueEnterPUK:
if keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUK:
controller.setRemainingAttempts(keycardEvent.pukRetries)
@ -112,19 +112,19 @@ method resolveKeycardNextState*(self: KeycardRepeatPinState, keycardFlowType: st
if keycardEvent.pukRetries > 0:
return createState(StateType.KeycardPinSet, self.flowType, self.getBackState)
return createState(StateType.KeycardMaxPukRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.MaxPUKReached, add = true))
return createState(StateType.KeycardMaxPukRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamFreeSlots:
return createState(StateType.KeycardMaxPairingSlotsReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
controller.setKeycardEvent(keycardEvent)
controller.setPukValid(true)
if controller.getRecoverUsingSeedPhraseWhileLogin():
if controller.getRecoverKeycardUsingSeedPhraseWhileLoggingIn():
controller.addToKeycardUidPairsToCheckForAChangeAfterLogin(self.oldKeycardUid, keycardEvent.instanceUID)
let md = controller.getMetadataFromKeycard()
let paths = md.walletAccounts.map(a => a.path)

View File

@ -17,38 +17,38 @@ method executePrimaryCommand*(self: KeycardWrongPinState, controller: Controller
self.pinValid = controller.getPin().len == PINLengthForStatusApp
if self.pinValid:
controller.enterKeycardPin(controller.getPin())
method resolveKeycardNextState*(self: KeycardWrongPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
method resolveKeycardNextState*(self: KeycardWrongPinState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueEnterPIN and
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPIN:
controller.setRemainingAttempts(keycardEvent.pinRetries)
if keycardEvent.pinRetries > 0:
return self
return createState(StateType.KeycardMaxPinRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueEnterPUK and
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len == 0:
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
return createState(StateType.KeycardMaxPinRetriesReached, self.flowType, self.getBackState)
return nil
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.MaxPUKReached, add = true))
return createState(StateType.KeycardMaxPukRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamFreeSlots:
return createState(StateType.KeycardMaxPairingSlotsReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
controller.setKeycardEvent(keycardEvent)
if not main_constants.IS_MACOS:
controller.setupKeycardAccount(storeToKeychain = false, newKeycard = false)
return nil
controller.setupKeycardAccount(storeToKeychain = false)
return nil
let backState = findBackStateWithTargetedStateType(self, StateType.RecoverOldUser)
return createState(StateType.Biometrics, self.flowType, backState)

View File

@ -15,14 +15,14 @@ method executePrimaryCommand*(self: KeycardWrongPukState, controller: Controller
elif self.flowType == FlowType.AppLogin:
if controller.getPuk().len == PUKLengthForStatusApp:
controller.enterKeycardPuk(controller.getPuk())
method resolveKeycardNextState*(self: KeycardWrongPukState, keycardFlowType: string, keycardEvent: KeycardEvent,
method resolveKeycardNextState*(self: KeycardWrongPukState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
if keycardFlowType == ResponseTypeValueEnterPUK and
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUK:
controller.setRemainingAttempts(keycardEvent.pukRetries)
@ -30,7 +30,7 @@ method resolveKeycardNextState*(self: KeycardWrongPukState, keycardFlowType: str
if keycardEvent.pukRetries > 0:
return nil
return createState(StateType.KeycardMaxPukRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.MaxPUKReached, add = true))
@ -39,12 +39,12 @@ method resolveKeycardNextState*(self: KeycardWrongPukState, keycardFlowType: str
controller.setKeycardEvent(keycardEvent)
controller.setPukValid(true)
if not main_constants.IS_MACOS:
controller.setupKeycardAccount(storeToKeychain = false, newKeycard = false)
controller.setupKeycardAccount(storeToKeychain = false)
return nil
let backState = findBackStateWithTargetedStateType(self, StateType.RecoverOldUser)
return createState(StateType.Biometrics, self.flowType, backState)
if self.flowType == FlowType.AppLogin:
if keycardFlowType == ResponseTypeValueEnterPUK and
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUK:
controller.setRemainingAttempts(keycardEvent.pukRetries)
@ -52,7 +52,7 @@ method resolveKeycardNextState*(self: KeycardWrongPukState, keycardFlowType: str
if keycardEvent.pukRetries > 0:
return nil
return createState(StateType.LoginKeycardMaxPukRetriesReached, self.flowType, self.getBackState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
return createState(StateType.LoginKeycardMaxPukRetriesReached, self.flowType, self.getBackState)

View File

@ -14,7 +14,7 @@ method executeBackCommand*(self: LoginKeycardMaxPairingSlotsReachedState, contro
method getNextPrimaryState*(self: LoginKeycardMaxPairingSlotsReachedState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.setRecoverUsingSeedPhraseWhileLogin(true)
controller.setRecoverKeycardUsingSeedPhraseWhileLoggingIn(true)
return createState(StateType.UserProfileEnterSeedPhrase, self.flowType, nil)
method getNextTertiaryState*(self: LoginKeycardMaxPairingSlotsReachedState, controller: Controller): State =
@ -32,6 +32,6 @@ method getNextQuinaryState*(self: LoginKeycardMaxPairingSlotsReachedState, contr
controller.cancelCurrentFlow()
return createState(StateType.LostKeycardOptions, self.flowType, self)
method resolveKeycardNextState*(self: LoginKeycardMaxPairingSlotsReachedState, keycardFlowType: string, keycardEvent: KeycardEvent,
method resolveKeycardNextState*(self: LoginKeycardMaxPairingSlotsReachedState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
return ensureReaderAndCardPresenceAndResolveNextLoginState(self, keycardFlowType, keycardEvent, controller)

View File

@ -14,7 +14,7 @@ method executeBackCommand*(self: LoginKeycardMaxPukRetriesReachedState, controll
method getNextPrimaryState*(self: LoginKeycardMaxPukRetriesReachedState, controller: Controller): State =
if self.flowType == FlowType.AppLogin:
controller.setRecoverUsingSeedPhraseWhileLogin(true)
controller.setRecoverKeycardUsingSeedPhraseWhileLoggingIn(true)
return createState(StateType.UserProfileEnterSeedPhrase, self.flowType, self)
method getNextTertiaryState*(self: LoginKeycardMaxPukRetriesReachedState, controller: Controller): State =

View File

@ -11,4 +11,4 @@ proc delete*(self: ProfileFetchingSuccessState) =
method executePrimaryCommand*(self: ProfileFetchingSuccessState, controller: Controller) =
if self.flowType == FlowType.FirstRunOldUserImportSeedPhrase or
self.flowType == FlowType.FirstRunOldUserKeycardImport:
controller.checkFetchingStatusAndProceedWithAppLoading()
controller.checkFetchingStatusAndProceed()

View File

@ -11,4 +11,4 @@ proc delete*(self: ProfileFetchingTimeoutState) =
method executePrimaryCommand*(self: ProfileFetchingTimeoutState, controller: Controller) =
if self.flowType == FlowType.FirstRunOldUserImportSeedPhrase or
self.flowType == FlowType.FirstRunOldUserKeycardImport:
controller.checkFetchingStatusAndProceedWithAppLoading()
controller.checkFetchingStatusAndProceed()

View File

@ -1,6 +1,6 @@
proc ensureReaderAndCardPresenceOnboarding*(state: State, keycardFlowType: string, keycardEvent: KeycardEvent, controller: Controller): State =
let backState = findBackStateWhichDoesNotBelongToAnyOfReadingStates(state)
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.error.len > 0:
if keycardEvent.error == ErrorPCSC:
return createState(StateType.KeycardNoPCSCService, state.flowType, backState)
@ -9,7 +9,7 @@ proc ensureReaderAndCardPresenceOnboarding*(state: State, keycardFlowType: strin
if state.stateType == StateType.KeycardPluginReader:
return nil
return createState(StateType.KeycardPluginReader, state.flowType, backState)
if keycardFlowType == ResponseTypeValueInsertCard and
if keycardFlowType == ResponseTypeValueInsertCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorConnection:
controller.reRunCurrentFlowLater()
@ -24,29 +24,29 @@ proc ensureReaderAndCardPresenceAndResolveNextOnboardingState*(state: State, key
let ensureState = ensureReaderAndCardPresenceOnboarding(state, keycardFlowType, keycardEvent, controller)
if not ensureState.isNil:
return ensureState
if state.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
var backState = state.getBackState
if state.stateType == StateType.WelcomeNewStatusUser:
backState = state
if state.stateType == StateType.KeycardEmpty:
## `KeycardEmpty` state is known in the context of `FirstRunNewUserNewKeycardKeys` only if we jump to it from
## `KeycardEmpty` state is known in the context of `FirstRunNewUserNewKeycardKeys` only if we jump to it from
## `FirstRunOldUserKeycardImport` flow, in that case we need to set back state appropriatelly respecting different flow.
backState = state.getBackState
if keycardFlowType == ResponseTypeValueEnterNewPIN and
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorRequireInit:
return createState(StateType.KeycardRecognizedKeycard, state.flowType, backState)
if keycardFlowType == ResponseTypeValueEnterPIN and
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
return createState(StateType.KeycardNotEmpty, state.flowType, backState)
if keycardFlowType == ResponseTypeValueEnterPUK and
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len == 0:
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
return createState(StateType.KeycardLocked, state.flowType, backState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0:
if keycardEvent.error == ErrorNotAKeycard:
return createState(StateType.KeycardNotKeycard, state.flowType, backState)
@ -56,27 +56,27 @@ proc ensureReaderAndCardPresenceAndResolveNextOnboardingState*(state: State, key
return createState(StateType.KeycardLocked, state.flowType, backState)
if keycardEvent.error == ErrorHasKeys:
return createState(StateType.KeycardNotEmpty, state.flowType, backState)
if keycardFlowType == ResponseTypeValueEnterMnemonic and
if keycardFlowType == ResponseTypeValueEnterMnemonic and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorLoadingKeys:
controller.buildSeedPhrasesFromIndexes(keycardEvent.seedPhraseIndexes)
return createState(StateType.KeycardPinSet, state.flowType, backState)
if state.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
var backState = state.getBackState
if state.stateType == StateType.UserProfileImportSeedPhrase:
backState = state
if keycardFlowType == ResponseTypeValueEnterNewPIN and
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorRequireInit:
if state.stateType == StateType.UserProfileEnterSeedPhrase:
return createState(StateType.KeycardCreatePin, state.flowType, backState)
return createState(StateType.KeycardRecognizedKeycard, state.flowType, backState)
if keycardFlowType == ResponseTypeValueEnterPIN and
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
return createState(StateType.KeycardNotEmpty, state.flowType, backState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0:
if keycardEvent.error == ErrorNotAKeycard:
return createState(StateType.KeycardNotKeycard, state.flowType, backState)
@ -86,37 +86,39 @@ proc ensureReaderAndCardPresenceAndResolveNextOnboardingState*(state: State, key
return createState(StateType.KeycardLocked, state.flowType, backState)
if keycardEvent.error == ErrorHasKeys:
return createState(StateType.KeycardNotEmpty, state.flowType, backState)
if state.flowType == FlowType.FirstRunOldUserKeycardImport:
var backState = state.getBackState
if state.stateType == StateType.RecoverOldUser:
backState = state
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.MaxPUKReached, add = false))
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.MaxPairingSlotsReached, add = false))
controller.setKeyUid(keycardEvent.keyUid)
if keycardFlowType == ResponseTypeValueEnterPIN and
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
return createState(StateType.KeycardRecognizedKeycard, state.flowType, backState)
if keycardFlowType == ResponseTypeValueEnterPUK and
if keycardFlowType == ResponseTypeValueEnterPUK and
keycardEvent.error.len == 0:
if keycardEvent.pinRetries == 0 and keycardEvent.pukRetries > 0:
return createState(StateType.KeycardMaxPinRetriesReached, state.flowType, backState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorNoKeys:
return createState(StateType.KeycardEmpty, state.flowType, backState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.MaxPUKReached, add = true))
return createState(StateType.KeycardMaxPukRetriesReached, state.flowType, backState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamFreeSlots:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.MaxPairingSlotsReached, add = true))
return createState(StateType.KeycardMaxPairingSlotsReached, state.flowType, backState)
if state.flowType == FlowType.AppLogin:
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0 and
keycardEvent.error == RequestParamPUKRetries:
return createState(StateType.KeycardMaxPukRetriesReached, state.flowType, state.getBackState)
@ -126,16 +128,16 @@ proc ensureReaderAndCardPresenceAndResolveNextOnboardingState*(state: State, key
if state.stateType == StateType.LostKeycardOptions:
backState = state
if keycardFlowType == ResponseTypeValueEnterNewPIN and
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorRequireInit:
if state.stateType == StateType.UserProfileEnterSeedPhrase:
return createState(StateType.KeycardCreatePin, state.flowType, state)
return createState(StateType.KeycardRecognizedKeycard, state.flowType, backState)
if keycardFlowType == ResponseTypeValueEnterPIN and
if keycardFlowType == ResponseTypeValueEnterPIN and
keycardEvent.error.len == 0:
return createState(StateType.KeycardNotEmpty, state.flowType, backState)
if keycardFlowType == ResponseTypeValueSwapCard and
if keycardFlowType == ResponseTypeValueSwapCard and
keycardEvent.error.len > 0:
if keycardEvent.error == ErrorNotAKeycard:
return createState(StateType.KeycardNotKeycard, state.flowType, backState)

View File

@ -17,7 +17,7 @@ method executePrimaryCommand*(self: UserProfileChatKeyState, controller: Control
elif self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
controller.storeKeycardAccountAndLogin(storeToKeychain, newKeycard = true)
elif self.flowType == FlowType.FirstRunOldUserKeycardImport:
controller.setupKeycardAccount(storeToKeychain, newKeycard = false)
controller.setupKeycardAccount(storeToKeychain)
method getNextPrimaryState*(self: UserProfileChatKeyState, controller: Controller): State =
if self.flowType == FlowType.FirstRunNewUserNewKeys or

View File

@ -168,7 +168,7 @@ method onFetchingFromWakuMessageReceived*(self: AccessInterface, backedUpMsgCloc
method finishAppLoading*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method checkFetchingStatusAndProceedWithAppLoading*(self: AccessInterface) {.base.} =
method checkFetchingStatusAndProceed*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method startAppAfterDelay*(self: AccessInterface) {.base.} =
@ -196,7 +196,7 @@ method onReencryptionProcessFinished*(self: AccessInterface) {.base.} =
type
DelegateInterface* = concept c
c.startupDidLoad()
c.userLoggedIn(bool)
c.userLoggedIn()
c.finishAppLoading()
c.storeDefaultKeyPairForNewKeycardUser()
c.syncKeycardBasedOnAppWalletStateAfterLogin()

View File

@ -1,3 +1,5 @@
import strformat
type
Item* = ref object
entity: string
@ -12,6 +14,15 @@ proc newItem*(entity: string, icon: string, totalMessages: int = 0): Item =
result.trackOfLoadedMessages = @[]
result.totalMessages = totalMessages
proc `$`*(self: Item): string =
result = fmt"""FetchingDataItem[
entity: {self.entity},
icon: {self.icon},
totalMessages: {self.totalMessages},
trackOfLoadedMessages: {self.trackOfLoadedMessages},
]
"""
proc entity*(self: Item): string =
return self.entity

View File

@ -1,4 +1,4 @@
import NimQml, Tables, strutils
import NimQml, Tables, strutils, strformat
import fetching_data_item
@ -29,6 +29,11 @@ QtObject:
result.allTotalsSet = false
result.lastKnownBackedUpMsgClock = 0
proc `$`*(self: Model): string =
result = "FetchingDataModel:\n"
for i in 0 ..< self.items.len:
result &= fmt"""[{i}]:{$self.items[i]}"""
proc countChanged(self: Model) {.signal.}
proc getCount*(self: Model): int {.slot.} =
self.items.len
@ -142,4 +147,4 @@ QtObject:
let ind = self.findIndexForEntity(entity)
if(ind == -1):
return false
return self.items[ind].loadedMessages == self.items[ind].totalMessages
return self.items[ind].totalMessages > 0 and self.items[ind].loadedMessages == self.items[ind].totalMessages

View File

@ -31,6 +31,13 @@ QtObject:
new(result, delete)
result.setup
proc countChanged(self: Model) {.signal.}
proc getCount*(self: Model): int {.slot.} =
self.items.len
QtProperty[int]count:
read = getCount
notify = countChanged
method rowCount(self: Model, index: QModelIndex = nil): int =
return self.items.len
@ -84,6 +91,7 @@ QtObject:
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()
proc getItemAtIndex*(self: Model, index: int): Item =
if(index < 0 or index >= self.items.len):

View File

@ -6,19 +6,19 @@ import internal/[state, state_factory]
import models/generated_account_item as gen_acc_item
import models/login_account_item as login_acc_item
import models/fetching_data_model as fetch_model
import ../../../constants as main_constants
import ../../global/global_singleton
import ../../global/app_translatable_constants as atc
import ../../core/eventemitter
import constants as main_constants
import app/global/global_singleton
import app/global/app_translatable_constants as atc
import app/core/eventemitter
import ../../../app_service/service/keychain/service as keychain_service
import ../../../app_service/service/accounts/service as accounts_service
import ../../../app_service/service/general/service as general_service
import ../../../app_service/service/profile/service as profile_service
import ../../../app_service/service/keycard/service as keycard_service
import ../../../app_service/service/devices/service as devices_service
import app_service/service/keychain/service as keychain_service
import app_service/service/accounts/service as accounts_service
import app_service/service/general/service as general_service
import app_service/service/profile/service as profile_service
import app_service/service/keycard/service as keycard_service
import app_service/service/devices/service as devices_service
import ../shared_modules/keycard_popup/module as keycard_shared_module
import app/modules/shared_modules/keycard_popup/module as keycard_shared_module
export io_interface
@ -327,7 +327,7 @@ method emitObtainingPasswordSuccess*[T](self: Module[T], password: string) =
method finishAppLoading*[T](self: Module[T]) =
self.delegate.finishAppLoading()
method checkFetchingStatusAndProceedWithAppLoading*[T](self: Module[T]) =
method checkFetchingStatusAndProceed*[T](self: Module[T]) =
if self.view.fetchingDataModel().isEntityLoaded(FetchingFromWakuProfile):
self.delegate.finishAppLoading()
return
@ -404,7 +404,7 @@ method onNodeLogin*[T](self: Module[T], error: string) =
self.prepareAndInitFetchingData()
self.controller.connectToFetchingFromWakuEvents()
self.delayStartingApp()
let err = self.delegate.userLoggedIn(recoverAccount = true)
let err = self.delegate.userLoggedIn()
if err.len > 0:
self.logoutAndDisplayError(err, StartupErrorType.UnknownType)
return
@ -416,7 +416,7 @@ method onNodeLogin*[T](self: Module[T], error: string) =
self.delegate.logout()
self.view.setCurrentStartupState(newLoginKeycardConvertedToRegularAccountState(currStateObj.flowType(), nil))
else:
let err = self.delegate.userLoggedIn(recoverAccount = false)
let err = self.delegate.userLoggedIn()
if err.len > 0:
self.logoutAndDisplayError(err, StartupErrorType.UnknownType)
return

View File

@ -423,10 +423,10 @@ QtObject:
walletRootAddress = self.importedAccount.derivedAccounts.walletRoot.address
eip1581Address = self.importedAccount.derivedAccounts.eip1581.address
encryptionPublicKey = self.importedAccount.derivedAccounts.encryption.publicKey
whisperPrivateKey = self.importedAccount.derivedAccounts.whisper.privateKey
if whisperPrivateKey.startsWith("0x"):
whisperPrivateKey = whisperPrivateKey[2 .. ^1]
if whisperPrivateKey.startsWith("0x"):
whisperPrivateKey = whisperPrivateKey[2 .. ^1]
let installationId = $genUUID()
let alias = generateAliasFromPk(whisperPublicKey)

View File

@ -43,6 +43,7 @@ const SIGNAL_KEYPAIR_SYNCED* = "keypairSynced"
const SIGNAL_KEYPAIR_NAME_CHANGED* = "keypairNameChanged"
const SIGNAL_NEW_KEYCARD_SET* = "newKeycardSet"
const SIGNAL_KEYCARD_REBUILD* = "keycardRebuild"
const SIGNAL_KEYCARD_DELETED* = "keycardDeleted"
const SIGNAL_ALL_KEYCARDS_DELETED* = "allKeycardsDeleted"
const SIGNAL_KEYCARD_ACCOUNTS_REMOVED* = "keycardAccountsRemoved"

View File

@ -349,7 +349,6 @@ proc convertToKeycardAccount*(account: JsonNode, settings: JsonNode, keycardUid:
try:
let response = status_go.convertToKeycardAccount($account, $settings, keycardUid, 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)

View File

@ -355,7 +355,9 @@ Item {
PropertyChanges {
target: link
text: qsTr("Unlock using PUK")
enabled: !(root.startupStore.startupModuleInst.keycardData & Constants.predefinedKeycardData.maxPUKReached)
enabled: !(root.startupStore.startupModuleInst.keycardData & Constants.predefinedKeycardData.maxPUKReached ||
root.startupStore.currentStartupState.flowType === Constants.startupFlow.firstRunOldUserKeycardImport &&
root.startupStore.startupModuleInst.keycardData & Constants.predefinedKeycardData.maxPairingSlotsReached)
color: !enabled? Theme.palette.baseColor1 : Theme.palette.primaryColor1
}
PropertyChanges {

View File

@ -255,6 +255,7 @@ Item {
height: 24
anchors.verticalCenter: usernameText.verticalCenter
anchors.right: parent.right
visible: root.startupStore.startupModuleInst.loginAccountsModel.count > 0
onClicked: {
if (accountsPopup.opened) {

View File

@ -105,6 +105,7 @@ QtObject {
readonly property int useGeneralMessageForLockedState: 64
readonly property int maxPUKReached: 128
readonly property int copyFromAKeycardPartDone: 256
readonly property int maxPairingSlotsReached: 512
}
readonly property QtObject keycardSharedFlow: QtObject {

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit 10a42e639d6c455e2a14a89006c8d653e9d1d441
Subproject commit 4088edfa14092e9fd60604c7d1a237388168e591