feat(@desktop/wallet): account interaction - stop using a keycard for non profile keypair

Part 2 of: #11737
This commit is contained in:
Sale Djenic 2023-08-29 16:22:41 +02:00 committed by saledjenic
parent 3d336f2666
commit c59f6d72d8
38 changed files with 784 additions and 373 deletions

View File

@ -64,6 +64,12 @@ proc init*(self: Controller) =
return
self.delegate.onKeycardChange(args.keycard)
self.events.on(SIGNAL_ALL_KEYCARDS_DELETED) do(e: Args):
let args = KeycardArgs(e)
if not args.success:
return
self.delegate.onKeycardChange(args.keycard)
self.events.on(SIGNAL_KEYCARD_LOCKED) do(e: Args):
let args = KeycardArgs(e)
if not args.success:

View File

@ -29,6 +29,9 @@ method onSharedKeycarModuleFlowTerminated*(self: AccessInterface, lastStepInTheC
method runSetupKeycardPopup*(self: AccessInterface, keyUid: string) {.base.} =
raise newException(ValueError, "No implementation available")
method runStopUsingKeycardPopup*(self: AccessInterface, keyUid: string) {.base.} =
raise newException(ValueError, "No implementation available")
method runCreateNewKeycardWithNewSeedPhrasePopup*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -120,6 +120,12 @@ method runSetupKeycardPopup*(self: Module, keyUid: string) =
return
self.keycardSharedModule.runFlow(keycard_shared_module.FlowType.SetupNewKeycard, keyUid)
method runStopUsingKeycardPopup*(self: Module, keyUid: string) =
self.createSharedKeycardModule()
if self.keycardSharedModule.isNil:
return
self.keycardSharedModule.runFlow(keycard_shared_module.FlowType.MigrateFromKeycardToApp, keyUid)
method runCreateNewKeycardWithNewSeedPhrasePopup*(self: Module) =
self.createSharedKeycardModule()
if self.keycardSharedModule.isNil:

View File

@ -59,6 +59,9 @@ QtObject:
proc runSetupKeycardPopup*(self: View, keyUid: string) {.slot.} =
self.delegate.runSetupKeycardPopup(keyUid)
proc runStopUsingKeycardPopup*(self: View, keyUid: string) {.slot.} =
self.delegate.runStopUsingKeycardPopup(keyUid)
proc runCreateNewKeycardWithNewSeedPhrasePopup*(self: View) {.slot.} =
self.delegate.runCreateNewKeycardWithNewSeedPhrasePopup()

View File

@ -158,6 +158,12 @@ method load*(self: Module) =
return
self.refreshWalletAccounts()
self.events.on(SIGNAL_ALL_KEYCARDS_DELETED) do(e: Args):
let args = KeycardArgs(e)
if not args.success:
return
self.refreshWalletAccounts()
self.events.on(SIGNAL_KEYPAIR_NAME_CHANGED) do(e: Args):
let args = KeypairArgs(e)
self.onKeypairRenamed(args.keypair.keyUid, args.keypair.name)

View File

@ -185,6 +185,12 @@ proc init*(self: Controller, fullConnect = true) =
self.delegate.onSecondaryActionClicked()
self.connectionIds.add(handlerId)
handlerId = self.events.onWithUUID(SIGNAL_ALL_KEYCARDS_DELETED) do(e: Args):
let args = KeycardArgs(e)
self.tmpAddingMigratedKeypairSuccess = args.success
self.delegate.onSecondaryActionClicked()
self.connectionIds.add(handlerId)
handlerId = self.events.onWithUUID(SIGNAL_CONVERTING_PROFILE_KEYPAIR) do(e: Args):
let args = ResultArgs(e)
self.tmpConvertingProfileSuccess = args.success
@ -724,6 +730,9 @@ proc addNewSeedPhraseKeypair*(self: Controller, seedPhrase, keyUid, keypairName,
return false
return true
proc migrateNonProfileKeycardKeypairToApp*(self: Controller, keyUid, seedPhrase, password: string, doPasswordHashing: bool) =
self.walletAccountService.migrateNonProfileKeycardKeypairToAppAsync(keyUid, seedPhrase, password, doPasswordHashing)
proc getSigningPhrase*(self: Controller): string =
if not serviceApplicable(self.settingsService):
return

View File

@ -50,6 +50,13 @@ method executePrePrimaryStateCommand*(self: EnterSeedPhraseState, controller: Co
self.verifiedSeedPhrase = controller.validSeedPhrase(sp) and keyUid == controller.getKeyPairForProcessing().getKeyUid()
if not self.verifiedSeedPhrase:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WrongSeedPhrase, add = true))
if self.flowType == FlowType.MigrateFromKeycardToApp:
let keyUid = controller.getKeyUidForSeedPhrase(sp)
self.verifiedSeedPhrase = controller.validSeedPhrase(sp) and keyUid == controller.getKeyPairForProcessing().getKeyUid()
if self.verifiedSeedPhrase:
controller.authenticateUser()
else:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WrongSeedPhrase, add = true))
method getNextPrimaryState*(self: EnterSeedPhraseState, controller: Controller): State =
if self.flowType == FlowType.SetupNewKeycard:
@ -70,12 +77,20 @@ method getNextPrimaryState*(self: EnterSeedPhraseState, controller: Controller):
if self.verifiedSeedPhrase:
return createState(StateType.CreatePin, self.flowType, nil)
return createState(StateType.WrongSeedPhrase, self.flowType, nil)
if self.flowType == FlowType.MigrateFromKeycardToApp:
if not self.verifiedSeedPhrase:
return createState(StateType.WrongSeedPhrase, self.flowType, nil)
method getNextSecondaryState*(self: EnterSeedPhraseState, controller: Controller): State =
if self.flowType == FlowType.MigrateFromKeycardToApp:
return createState(StateType.MigratingKeypairToApp, self.flowType, nil)
method executeCancelCommand*(self: EnterSeedPhraseState, controller: Controller) =
if self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.SetupNewKeycardOldSeedPhrase or
self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.CreateCopyOfAKeycard:
self.flowType == FlowType.CreateCopyOfAKeycard or
self.flowType == FlowType.MigrateFromKeycardToApp:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
method resolveKeycardNextState*(self: EnterSeedPhraseState, keycardFlowType: string, keycardEvent: KeycardEvent,
@ -86,7 +101,7 @@ method resolveKeycardNextState*(self: EnterSeedPhraseState, keycardFlowType: str
if self.flowType == FlowType.SetupNewKeycard:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.keyUid.len > 0:
return createState(StateType.MigratingKeyPair, self.flowType, nil)
return createState(StateType.MigratingKeypairToKeycard, self.flowType, nil)
if self.flowType == FlowType.SetupNewKeycardOldSeedPhrase:
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and

View File

@ -9,9 +9,11 @@ proc delete*(self: KeyPairMigrateFailureState) =
self.State.delete
method executePrePrimaryStateCommand*(self: KeyPairMigrateFailureState, controller: Controller) =
if self.flowType == FlowType.SetupNewKeycard:
if self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.MigrateFromKeycardToApp:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)
method executeCancelCommand*(self: KeyPairMigrateFailureState, controller: Controller) =
if self.flowType == FlowType.SetupNewKeycard:
if self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.MigrateFromKeycardToApp:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)

View File

@ -8,6 +8,17 @@ proc newKeyPairMigrateSuccessState*(flowType: FlowType, backState: State): KeyPa
proc delete*(self: KeyPairMigrateSuccessState) =
self.State.delete
method executeCancelCommand*(self: KeyPairMigrateSuccessState, controller: Controller) =
if self.flowType == FlowType.SetupNewKeycard:
let profileMigrated = controller.getSelectedKeyPairIsProfile()
if profileMigrated:
return
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)
if self.flowType == FlowType.MigrateFromKeycardToApp:
if controller.getKeyPairForProcessing().getKeyUid() == singletonInstance.userProfile.getKeyUid():
return
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)
method executePrePrimaryStateCommand*(self: KeyPairMigrateSuccessState, controller: Controller) =
if self.flowType == FlowType.SetupNewKeycard:
let profileMigrated = controller.getSelectedKeyPairIsProfile()
@ -15,3 +26,9 @@ method executePrePrimaryStateCommand*(self: KeyPairMigrateSuccessState, controll
if profileMigrated:
info "restart the app because of successfully migrated profile keypair"
quit() # quit the app
if self.flowType == FlowType.MigrateFromKeycardToApp:
let profileMigrated = controller.getKeyPairForProcessing().getKeyUid() == singletonInstance.userProfile.getKeyUid()
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)
if profileMigrated:
info "restart the app because of successfully migrated profile keypair"
quit() # quit the app

View File

@ -0,0 +1,17 @@
type
MigrateKeypairToAppState* = ref object of State
proc newMigrateKeypairToAppState*(flowType: FlowType, backState: State): MigrateKeypairToAppState =
result = MigrateKeypairToAppState()
result.setup(flowType, StateType.MigrateKeypairToApp, backState)
proc delete*(self: MigrateKeypairToAppState) =
self.State.delete
method executeCancelCommand*(self: MigrateKeypairToAppState, controller: Controller) =
if self.flowType == FlowType.MigrateFromKeycardToApp:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = true)
method getNextPrimaryState*(self: MigrateKeypairToAppState, controller: Controller): State =
if self.flowType == FlowType.MigrateFromKeycardToApp:
return createState(StateType.EnterSeedPhrase, self.flowType, self)

View File

@ -0,0 +1,29 @@
type
MigratingKeypairToAppState* = ref object of State
migrationOk: bool
proc newMigratingKeypairToAppState*(flowType: FlowType, backState: State): MigratingKeypairToAppState =
result = MigratingKeypairToAppState()
result.setup(flowType, StateType.MigratingKeypairToApp, backState)
proc delete*(self: MigratingKeypairToAppState) =
self.State.delete
method executePrePrimaryStateCommand*(self: MigratingKeypairToAppState, controller: Controller) =
if self.flowType == FlowType.MigrateFromKeycardToApp:
let sp = controller.getSeedPhrase()
let password = controller.getPassword()
let kpForProcessing = controller.getKeyPairForProcessing()
controller.migrateNonProfileKeycardKeypairToApp(kpForProcessing.getKeyUid(), sp, password,
doPasswordHashing = not singletonInstance.userProfile.getIsKeycardUser())
method executePreSecondaryStateCommand*(self: MigratingKeypairToAppState, controller: Controller) =
## Secondary action is called after each async action during migration process.
if self.flowType == FlowType.MigrateFromKeycardToApp:
self.migrationOk = controller.getAddingMigratedKeypairSuccess()
method getNextSecondaryState*(self: MigratingKeypairToAppState, controller: Controller): State =
if self.flowType == FlowType.MigrateFromKeycardToApp:
if not self.migrationOk:
return createState(StateType.KeyPairMigrateFailure, self.flowType, nil)
return createState(StateType.KeyPairMigrateSuccess, self.flowType, nil)

View File

@ -1,5 +1,5 @@
type
MigratingKeyPairState* = ref object of State
MigratingKeypairToKeycardState* = ref object of State
authenticationDone: bool
authenticationOk: bool
addingMigratedKeypairDone: bool
@ -7,9 +7,9 @@ type
profileConversionDone: bool
profileConversionOk: bool
proc newMigratingKeyPairState*(flowType: FlowType, backState: State): MigratingKeyPairState =
result = MigratingKeyPairState()
result.setup(flowType, StateType.MigratingKeyPair, backState)
proc newMigratingKeypairToKeycardState*(flowType: FlowType, backState: State): MigratingKeypairToKeycardState =
result = MigratingKeypairToKeycardState()
result.setup(flowType, StateType.MigratingKeypairToKeycard, backState)
result.authenticationDone = false
result.authenticationOk = false
result.addingMigratedKeypairDone = false
@ -17,30 +17,30 @@ proc newMigratingKeyPairState*(flowType: FlowType, backState: State): MigratingK
result.profileConversionDone = false
result.profileConversionOk = false
proc delete*(self: MigratingKeyPairState) =
proc delete*(self: MigratingKeypairToKeycardState) =
self.State.delete
proc doMigration(self: MigratingKeyPairState, controller: Controller) =
proc doMigration(self: MigratingKeypairToKeycardState, controller: Controller) =
let selectedKeyPairDto = controller.getSelectedKeyPairDto()
controller.addKeycardOrAccounts(selectedKeyPairDto)
proc doConversion(self: MigratingKeyPairState, controller: Controller) =
proc doConversion(self: MigratingKeypairToKeycardState, controller: Controller) =
let password = controller.getPassword()
let selectedKeyPairDto = controller.getSelectedKeyPairDto()
controller.convertSelectedKeyPairToKeycardAccount(selectedKeyPairDto.keycardUid, password)
proc runStoreMetadataFlow(self: MigratingKeyPairState, controller: Controller) =
proc runStoreMetadataFlow(self: MigratingKeypairToKeycardState, controller: Controller) =
let selectedKeyPairDto = controller.getSelectedKeyPairDto()
controller.runStoreMetadataFlow(selectedKeyPairDto.keycardName, controller.getPin(), controller.getSelectedKeyPairWalletPaths())
method executePrePrimaryStateCommand*(self: MigratingKeyPairState, controller: Controller) =
method executePrePrimaryStateCommand*(self: MigratingKeypairToKeycardState, controller: Controller) =
if self.flowType == FlowType.SetupNewKeycard:
if controller.getSelectedKeyPairIsProfile():
controller.authenticateUser()
return
self.doMigration(controller)
method executePreSecondaryStateCommand*(self: MigratingKeyPairState, controller: Controller) =
method executePreSecondaryStateCommand*(self: MigratingKeypairToKeycardState, controller: Controller) =
## Secondary action is called after each async action during migration process.
if self.flowType == FlowType.SetupNewKeycard:
if controller.getSelectedKeyPairIsProfile():
@ -63,7 +63,7 @@ method executePreSecondaryStateCommand*(self: MigratingKeyPairState, controller:
if self.addingMigratedKeypairOk:
self.runStoreMetadataFlow(controller)
method getNextSecondaryState*(self: MigratingKeyPairState, controller: Controller): State =
method getNextSecondaryState*(self: MigratingKeypairToKeycardState, controller: Controller): State =
if self.flowType == FlowType.SetupNewKeycard:
if controller.getSelectedKeyPairIsProfile():
if self.authenticationDone and not self.authenticationOk or
@ -73,7 +73,7 @@ method getNextSecondaryState*(self: MigratingKeyPairState, controller: Controlle
if self.addingMigratedKeypairDone and not self.addingMigratedKeypairOk:
return createState(StateType.KeyPairMigrateFailure, self.flowType, nil)
method resolveKeycardNextState*(self: MigratingKeyPairState, keycardFlowType: string, keycardEvent: KeycardEvent,
method resolveKeycardNextState*(self: MigratingKeypairToKeycardState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresenceAndResolveNextState(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:

View File

@ -32,7 +32,7 @@ method resolveKeycardNextState*(self: SeedPhraseEnterWordsState, keycardFlowType
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.keyUid.len > 0:
controller.removeProfileMnemonic()
return createState(StateType.MigratingKeyPair, self.flowType, nil)
return createState(StateType.MigratingKeypairToKeycard, self.flowType, nil)
if self.flowType == FlowType.SetupNewKeycardNewSeedPhrase:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.keyUid.len > 0:

View File

@ -47,7 +47,9 @@ type StateType* {.pure.} = enum
SeedPhraseEnterWords = "SeedPhraseEnterWords"
KeyPairMigrateSuccess = "KeyPairMigrateSuccess"
KeyPairMigrateFailure = "KeyPairMigrateFailure"
MigratingKeyPair = "MigratingKeyPair"
MigrateKeypairToApp = "MigrateKeypairToApp"
MigratingKeypairToApp = "MigratingKeypairToApp"
MigratingKeypairToKeycard = "MigratingKeypairToKeycard"
EnterPassword = "EnterPassword"
WrongPassword = "WrongPassword"
BiometricsPasswordFailed = "BiometricsPasswordFailed"

View File

@ -89,7 +89,9 @@ include keycard_already_unlocked_state
include max_pin_retries_reached_state
include max_puk_retries_reached_state
include max_pairing_slots_reached_state
include migrating_key_pair_state
include migrate_keypair_to_app_state
include migrating_keypair_to_app_state
include migrating_keypair_to_keycard_state
include no_pcsc_service_state
include not_keycard_state
include pin_set_state

View File

@ -143,8 +143,12 @@ proc createState*(stateToBeCreated: StateType, flowType: FlowType, backState: St
return newMaxPukRetriesReachedState(flowType, backState)
if stateToBeCreated == StateType.MaxPairingSlotsReached:
return newMaxPairingSlotsReachedState(flowType, backState)
if stateToBeCreated == StateType.MigratingKeyPair:
return newMigratingKeyPairState(flowType, backState)
if stateToBeCreated == StateType.MigrateKeypairToApp:
return newMigrateKeypairToAppState(flowType, backState)
if stateToBeCreated == StateType.MigratingKeypairToApp:
return newMigratingKeypairToAppState(flowType, backState)
if stateToBeCreated == StateType.MigratingKeypairToKeycard:
return newMigratingKeypairToKeycardState(flowType, backState)
if stateToBeCreated == StateType.NoPCSCService:
return newNoPCSCServiceState(flowType, backState)
if stateToBeCreated == StateType.NotKeycard:

View File

@ -31,10 +31,17 @@ method executePrePrimaryStateCommand*(self: WrongSeedPhraseState, controller: Co
self.verifiedSeedPhrase = controller.validSeedPhrase(sp) and keyUid == controller.getKeyPairForProcessing().getKeyUid()
if not self.verifiedSeedPhrase:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WrongSeedPhrase, add = true))
if self.flowType == FlowType.MigrateFromKeycardToApp:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WrongSeedPhrase, add = false))
let keyUid = controller.getKeyUidForSeedPhrase(sp)
self.verifiedSeedPhrase = controller.validSeedPhrase(sp) and keyUid == controller.getKeyPairForProcessing().getKeyUid()
if self.verifiedSeedPhrase:
controller.authenticateUser()
method getNextPrimaryState*(self: WrongSeedPhraseState, controller: Controller): State =
if self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.CreateCopyOfAKeycard:
self.flowType == FlowType.CreateCopyOfAKeycard or
self.flowType == FlowType.MigrateFromKeycardToApp:
if not self.verifiedSeedPhrase:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WrongSeedPhrase, add = true))
return self
@ -43,10 +50,15 @@ method getNextPrimaryState*(self: WrongSeedPhraseState, controller: Controller):
return createState(StateType.CreatePin, self.flowType, nil)
return self
method getNextSecondaryState*(self: WrongSeedPhraseState, controller: Controller): State =
if self.flowType == FlowType.MigrateFromKeycardToApp:
return createState(StateType.MigratingKeypairToApp, self.flowType, nil)
method executeCancelCommand*(self: WrongSeedPhraseState, controller: Controller) =
if self.flowType == FlowType.SetupNewKeycard or
self.flowType == FlowType.UnlockKeycard or
self.flowType == FlowType.CreateCopyOfAKeycard:
self.flowType == FlowType.CreateCopyOfAKeycard or
self.flowType == FlowType.MigrateFromKeycardToApp:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
method resolveKeycardNextState*(self: WrongSeedPhraseState, keycardFlowType: string, keycardEvent: KeycardEvent,
@ -58,7 +70,7 @@ method resolveKeycardNextState*(self: WrongSeedPhraseState, keycardFlowType: str
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.keyUid.len > 0:
controller.setKeycardData(updatePredefinedKeycardData(controller.getKeycardData(), PredefinedKeycardData.WrongSeedPhrase, add = false))
return createState(StateType.MigratingKeyPair, self.flowType, nil)
return createState(StateType.MigratingKeypairToKeycard, self.flowType, nil)
if self.flowType == FlowType.CreateCopyOfAKeycard:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.keyUid.len > 0:

View File

@ -64,6 +64,7 @@ type FlowType* {.pure.} = enum
ChangeKeycardPuk = "ChangeKeycardPuk"
ChangePairingCode = "ChangePairingCode"
CreateCopyOfAKeycard = "CreateCopyOfAKeycard"
MigrateFromKeycardToApp = "MigrateFromKeycardToApp"
# For the following flows we don't run card syncing.
const FlowsWeShouldNotTryAKeycardSyncFor* = @[
@ -75,7 +76,8 @@ const FlowsWeShouldNotTryAKeycardSyncFor* = @[
FlowType.SetupNewKeycardOldSeedPhrase,
FlowType.ImportFromKeycard,
FlowType.Authentication,
FlowType.CreateCopyOfAKeycard
FlowType.CreateCopyOfAKeycard,
FlowType.MigrateFromKeycardToApp
]
type

View File

@ -156,7 +156,10 @@ method validSeedPhrase*[T](self: Module[T], value: string): bool =
return self.controller.validSeedPhrase(value)
method migratingProfileKeyPair*[T](self: Module[T]): bool =
let flowType = self.getCurrentFlowType()
if flowType == FlowType.SetupNewKeycard:
return self.controller.getSelectedKeyPairIsProfile()
return self.controller.getKeyPairForProcessing().getKeyUid() == singletonInstance.userProfile.getKeyUid()
method getSigningPhrase*[T](self: Module[T]): string =
return self.controller.getSigningPhrase()
@ -532,6 +535,15 @@ method runFlow*[T](self: Module[T], flowToRun: FlowType, keyUid = "", bip44Paths
self.tmpLocalState = newReadingKeycardState(flowToRun, nil)
self.controller.runGetMetadataFlow(resolveAddress = true, exportMasterAddr = true)
return
if flowToRun == FlowType.MigrateFromKeycardToApp:
if keyUid.len == 0:
error "sm_cannot run a migration from keycar to app flow without knowing in advance a keypair being migrated"
self.controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
return
self.prepareKeyPairForProcessing(keyUid)
self.view.setCurrentState(newMigrateKeypairToAppState(flowToRun, nil))
self.controller.readyToDisplayPopup()
return
method setSelectedKeyPair*[T](self: Module[T], item: KeyPairItem) =
var paths: seq[string]
@ -609,9 +621,15 @@ method updateKeyPairHelper*[T](self: Module[T], cardMetadata: CardMetadata) =
method onUserAuthenticated*[T](self: Module[T], password: string, pin: string) =
let flowType = self.getCurrentFlowType()
if password.len == 0:
self.view.setDisablePopup(false)
return
if flowType == FlowType.SetupNewKeycard:
self.controller.setPassword(password)
self.onSecondaryActionClicked()
if flowType == FlowType.MigrateFromKeycardToApp:
self.controller.setPassword(password)
self.onSecondaryActionClicked()
method keychainObtainedDataFailure*[T](self: Module[T], errorDescription: string, errorType: string) =
let currStateObj = self.view.currentStateObj()

View File

@ -181,3 +181,27 @@ const fetchChainIdForUrlTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall
"chainId": -1,
"url": arg.url
})
#################################################
# Async migration of a non profile keycard keypair to the app
#################################################
type
MigrateNonProfileKeycardKeypairToAppTaskArg* = ref object of QObjectTaskArg
keyUid: string
seedPhrase: string
password: string
const migrateNonProfileKeycardKeypairToAppTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[MigrateNonProfileKeycardKeypairToAppTaskArg](argEncoded)
var responseJson = %*{
"success": false,
"keyUid": arg.keyUid
}
try:
let response = status_go_accounts.migrateNonProfileKeycardKeypairToApp(arg.seedPhrase, arg.password)
let success = responseHasNoErrors("migrateNonProfileKeycardKeypairToApp", response)
responseJson["success"] = %* success
except Exception as e:
error "error migrating a non profile keycard keypair: ", message = e.msg
arg.finish(responseJson)

View File

@ -62,6 +62,7 @@ QtObject:
proc onKeycardAdded*(self: Service, response: string) {.slot.}
proc onMigratedAccountsForKeycardRemoved*(self: Service, response: string) {.slot.}
proc onFetchChainIdForUrl*(self: Service, jsonString: string) {.slot.}
proc onNonProfileKeycardKeypairMigratedToApp*(self: Service, response: string) {.slot.}
proc delete*(self: Service) =
self.closingApp = true

View File

@ -448,6 +448,38 @@ proc makePartiallyOperableAccoutsFullyOperable(self: Service, password: string,
except Exception as e:
error "error: ", procName="makeSeedPhraseKeypairFullyOperable", errName=e.name, errDesription=e.msg
proc onNonProfileKeycardKeypairMigratedToApp*(self: Service, response: string) {.slot.} =
var data = KeycardArgs(
success: false,
keycard: KeycardDto()
)
try:
let responseObj = response.parseJson
discard responseObj.getProp("success", data.success)
discard responseObj.getProp("keyUid", data.keycard.keyUid)
let kp = self.getKeypairByKeyUid(data.keycard.keyUid)
if kp.isNil:
data.success = false
else:
kp.keycards = @[]
except Exception as e:
error "error handilng migrated keycard response", errDesription=e.msg
self.events.emit(SIGNAL_ALL_KEYCARDS_DELETED, data)
proc migrateNonProfileKeycardKeypairToAppAsync*(self: Service, keyUid, seedPhrase, password: string, doPasswordHashing: bool) =
var finalPassword = password
if doPasswordHashing:
finalPassword = utils.hashPassword(password)
let arg = MigrateNonProfileKeycardKeypairToAppTaskArg(
tptr: cast[ByteAddress](migrateNonProfileKeycardKeypairToAppTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onNonProfileKeycardKeypairMigratedToApp",
keyUid: keyUid,
seedPhrase: seedPhrase,
password: finalPassword
)
self.threadpool.start(arg)
proc getRandomMnemonic*(self: Service): string =
try:
let response = status_go_accounts.getRandomMnemonic()

View File

@ -248,6 +248,11 @@ proc makePartiallyOperableAccoutsFullyOperable*(password: string):
let payload = %* [password]
return core.callPrivateRPC("accounts_makePartiallyOperableAccoutsFullyOperable", payload)
proc migrateNonProfileKeycardKeypairToApp*(mnemonic: string, password: string):
RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* [mnemonic, password]
return core.callPrivateRPC("accounts_migrateNonProfileKeycardKeypairToApp", payload)
proc createAccountFromMnemonicAndDeriveAccountsForPaths*(mnemonic: string, paths: seq[string]): RpcResponse[JsonNode] {.raises: [Exception].} =
let payload = %* {
"mnemonicPhrase": mnemonic,

View File

@ -29,6 +29,7 @@ Rectangle {
signal runRenameKeypairFlow()
signal runRemoveKeypairFlow()
signal runMoveKeypairToKeycardFlow()
signal runStopUsingKeycardFlow()
QtObject {
id: d
@ -94,6 +95,7 @@ Rectangle {
onRunRenameKeypairFlow: root.runRenameKeypairFlow()
onRunRemoveKeypairFlow: root.runRemoveKeypairFlow()
onRunMoveKeypairToKeycardFlow: root.runMoveKeypairToKeycardFlow()
onRunStopUsingKeycardFlow: root.runStopUsingKeycardFlow()
}
}
},

View File

@ -18,6 +18,7 @@ StatusMenu {
signal runRenameKeypairFlow()
signal runRemoveKeypairFlow()
signal runMoveKeypairToKeycardFlow()
signal runStopUsingKeycardFlow()
StatusAction {
text: enabled? qsTr("Show encrypted QR on device") : ""
@ -40,7 +41,7 @@ StatusMenu {
icon.color: Theme.palette.primaryColor1
onTriggered: {
if (root.keyPair.migratedToKeycard)
console.warn("TODO: stop using Keycard")
root.runStopUsingKeycardFlow()
else
root.runMoveKeypairToKeycardFlow()
}

View File

@ -10,6 +10,10 @@ QtObject {
root.keycardModule.runSetupKeycardPopup(keyUid)
}
function runStopUsingKeycardPopup(keyUid) {
root.keycardModule.runStopUsingKeycardPopup(keyUid)
}
function runCreateNewKeycardWithNewSeedPhrasePopup() {
root.keycardModule.runCreateNewKeycardWithNewSeedPhrasePopup()
}

View File

@ -125,6 +125,9 @@ SettingsContentBase {
onRunMoveKeypairToKeycardFlow: {
root.rootStore.keycardStore.runSetupKeycardPopup(model.keyPair.keyUid)
}
onRunStopUsingKeycardFlow: {
root.rootStore.keycardStore.runStopUsingKeycardPopup(model.keyPair.keyUid)
}
}
NetworksView {
@ -193,6 +196,9 @@ SettingsContentBase {
onRunMoveKeypairToKeycardFlow: {
root.rootStore.keycardStore.runSetupKeycardPopup(keyPair.keyUid)
}
onRunStopUsingKeycardFlow: {
root.rootStore.keycardStore.runStopUsingKeycardPopup(keyPair.keyUid)
}
}
DappPermissionsView {

View File

@ -122,6 +122,20 @@ ColumnLayout {
}
}
StatusListItem {
Layout.fillWidth: true
title: qsTr("Stop using Keycard for this keypair")
components: [
StatusIcon {
icon: "tiny/chevron-right"
color: Theme.palette.baseColor1
}
]
onClicked: {
root.keycardStore.runStopUsingKeycardPopup(root.keyUid)
}
}
StatusListItem {
visible: root.keycardStore.keycardModule.keycardDetailsModel?
root.keycardStore.keycardModule.keycardDetailsModel.lockedItemsCount > 0 : false

View File

@ -28,6 +28,7 @@ ColumnLayout {
signal runRemoveKeypairFlow()
signal runImportMissingKeypairFlow()
signal runMoveKeypairToKeycardFlow()
signal runStopUsingKeycardFlow()
property var account
property var keyPair
@ -309,5 +310,6 @@ ColumnLayout {
onRunRenameKeypairFlow: root.runRenameKeypairFlow()
onRunRemoveKeypairFlow: root.runRemoveKeypairFlow()
onRunMoveKeypairToKeycardFlow: root.runMoveKeypairToKeycardFlow()
onRunStopUsingKeycardFlow: root.runStopUsingKeycardFlow()
}
}

View File

@ -29,6 +29,7 @@ Column {
signal runRenameKeypairFlow(var model)
signal runRemoveKeypairFlow(var model)
signal runMoveKeypairToKeycardFlow(var model)
signal runStopUsingKeycardFlow(var model)
spacing: 8
@ -242,6 +243,9 @@ Column {
onRunMoveKeypairToKeycardFlow: {
root.runMoveKeypairToKeycardFlow(model)
}
onRunStopUsingKeycardFlow: {
root.runStopUsingKeycardFlow(model)
}
}
}
}

View File

@ -44,6 +44,8 @@ StatusModal {
return qsTr("Create a new pairing code")
case Constants.keycardSharedFlow.createCopyOfAKeycard:
return qsTr("Create a backup copy of this Keycard")
case Constants.keycardSharedFlow.migrateFromKeycardToApp:
return qsTr("Migrate a keypair from Keycard to Status")
}
return ""

View File

@ -30,7 +30,9 @@ Item {
case Constants.keycardSharedState.readingKeycard:
case Constants.keycardSharedState.keyPairMigrateSuccess:
case Constants.keycardSharedState.keyPairMigrateFailure:
case Constants.keycardSharedState.migratingKeyPair:
case Constants.keycardSharedState.migrateKeypairToApp:
case Constants.keycardSharedState.migratingKeypairToApp:
case Constants.keycardSharedState.migratingKeypairToKeycard:
case Constants.keycardSharedState.creatingAccountNewSeedPhraseSuccess:
case Constants.keycardSharedState.creatingAccountNewSeedPhraseFailure:
case Constants.keycardSharedState.creatingAccountNewSeedPhrase:

View File

@ -30,7 +30,8 @@ QtObject {
case Constants.keycardSharedState.changingKeycardPin:
case Constants.keycardSharedState.changingKeycardPuk:
case Constants.keycardSharedState.changingKeycardPairingCode:
case Constants.keycardSharedState.migratingKeyPair:
case Constants.keycardSharedState.migratingKeypairToApp:
case Constants.keycardSharedState.migratingKeypairToKeycard:
case Constants.keycardSharedState.creatingAccountNewSeedPhrase:
case Constants.keycardSharedState.creatingAccountOldSeedPhrase:
case Constants.keycardSharedState.importingFromKeycard:
@ -366,6 +367,15 @@ QtObject {
break
}
break
case Constants.keycardSharedFlow.migrateFromKeycardToApp:
switch (root.sharedKeycardModule.currentState.stateType) {
case Constants.keycardSharedState.migrateKeypairToApp:
case Constants.keycardSharedState.enterSeedPhrase:
case Constants.keycardSharedState.wrongSeedPhrase:
return true
}
break
}
return false
@ -458,6 +468,14 @@ QtObject {
return qsTr("View imported accounts in Wallet")
}
break
case Constants.keycardSharedFlow.migrateFromKeycardToApp:
switch (root.sharedKeycardModule.currentState.stateType) {
case Constants.keycardSharedState.keyPairMigrateSuccess:
if (!root.sharedKeycardModule.migratingProfileKeyPair())
return qsTr("Factory reset this Keycard")
}
break
}
return ""
@ -575,7 +593,7 @@ QtObject {
return qsTr("Unlock Keycard")
return qsTr("Next")
case Constants.keycardSharedState.migratingKeyPair:
case Constants.keycardSharedState.migratingKeypairToKeycard:
case Constants.keycardSharedState.keyPairMigrateFailure:
return qsTr("Done")
@ -989,6 +1007,26 @@ QtObject {
return qsTr("Factory reset this Keycard")
}
break
case Constants.keycardSharedFlow.migrateFromKeycardToApp:
switch (root.sharedKeycardModule.currentState.stateType) {
case Constants.keycardSharedState.migrateKeypairToApp:
case Constants.keycardSharedState.enterSeedPhrase:
case Constants.keycardSharedState.wrongSeedPhrase:
return qsTr("Next")
case Constants.keycardSharedState.migratingKeypairToApp:
return qsTr("Done")
case Constants.keycardSharedState.keyPairMigrateFailure:
return qsTr("Close")
case Constants.keycardSharedState.keyPairMigrateSuccess:
if (root.sharedKeycardModule.migratingProfileKeyPair())
return qsTr("Restart App & Sign In Using Your New Password")
return qsTr("Done")
}
break
}
return ""
@ -1130,6 +1168,14 @@ QtObject {
return root.primaryButtonEnabled
}
break
case Constants.keycardSharedFlow.migrateFromKeycardToApp:
switch (root.sharedKeycardModule.currentState.stateType) {
case Constants.keycardSharedState.enterSeedPhrase:
return root.primaryButtonEnabled
}
break
}
return true

View File

@ -1,5 +1,7 @@
import QtQuick 2.14
import StatusQ.Core 0.1
import utils 1.0
import shared.panels 1.0 as SharedPanels
@ -20,9 +22,27 @@ Item {
}
StatusBaseText {
id: title
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: Style.current.padding
anchors.leftMargin: Style.current.xlPadding
anchors.rightMargin: Style.current.xlPadding
visible: text != ""
font.pixelSize: Constants.keycard.general.fontSize1
font.weight: Font.Bold
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
SharedPanels.EnterSeedPhrase {
id: seedPhrase
anchors.fill: parent
anchors.top: title.visible? title.bottom : parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: Style.current.xlPadding
anchors.bottomMargin: Style.current.halfPadding
anchors.leftMargin: Style.current.xlPadding
@ -48,10 +68,32 @@ Item {
State {
name: Constants.keycardSharedState.enterSeedPhrase
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.enterSeedPhrase
PropertyChanges {
target: title
text: {
switch (root.sharedKeycardModule.currentState.flowType) {
case Constants.keycardSharedFlow.migrateFromKeycardToApp:
return qsTr("Enter seed phrase for %1 keypair").arg(root.sharedKeycardModule.keyPairForProcessing.name)
}
return ""
}
}
},
State {
name: Constants.keycardSharedState.wrongSeedPhrase
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.wrongSeedPhrase
PropertyChanges {
target: title
text: {
switch (root.sharedKeycardModule.currentState.flowType) {
case Constants.keycardSharedFlow.migrateFromKeycardToApp:
return qsTr("Enter seed phrase for %1 keypair").arg(root.sharedKeycardModule.keyPairForProcessing.name)
}
return ""
}
}
}
]
}

View File

@ -16,7 +16,8 @@ Item {
property var sharedKeycardModule
Component.onCompleted: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToApp ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.creatingAccountNewSeedPhrase ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.creatingAccountOldSeedPhrase ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.importingFromKeycard ||
@ -32,7 +33,8 @@ Item {
readonly property bool hideKeyPair: root.sharedKeycardModule.keycardData & Constants.predefinedKeycardData.hideKeyPair
readonly property bool copyFromAKeycardPartDone: root.sharedKeycardModule.keycardData & Constants.predefinedKeycardData.copyFromAKeycardPartDone
readonly property bool continuousProcessingAnimation: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
readonly property bool continuousProcessingAnimation: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToApp ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.creatingAccountNewSeedPhrase ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.creatingAccountOldSeedPhrase ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.importingFromKeycard ||
@ -94,12 +96,11 @@ Item {
}
ColumnLayout {
anchors.fill: parent
anchors.topMargin: Style.current.xlPadding
anchors.bottomMargin: Style.current.halfPadding
id: layout
anchors.centerIn: parent
width: parent.width
anchors.leftMargin: Style.current.xlPadding
anchors.rightMargin: Style.current.xlPadding
spacing: Style.current.padding
clip: true
KeycardImage {
@ -118,7 +119,7 @@ Item {
Row {
spacing: Style.current.halfPadding
Layout.alignment: Qt.AlignCenter
Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: Constants.keycard.general.titleHeight
StatusIcon {
@ -132,7 +133,8 @@ Item {
StatusLoadingIndicator {
id: loading
visible: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToApp ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.creatingAccountNewSeedPhrase ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.creatingAccountOldSeedPhrase ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.importingFromKeycard ||
@ -153,14 +155,24 @@ Item {
id: message
Layout.alignment: Qt.AlignCenter
Layout.preferredWidth: parent.width
Layout.preferredHeight: Constants.keycard.general.messageHeight
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
}
Loader {
id: loader
Layout.preferredWidth: parent.width
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.current.xlPadding
anchors.rightMargin: Style.current.xlPadding
active: {
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.setupNewKeycard) {
if((root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.pluginReader && !d.hideKeyPair) ||
@ -168,7 +180,7 @@ Item {
(root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardInserted && !d.hideKeyPair) ||
(root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard && !d.hideKeyPair) ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.recognizedKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateSuccess ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateFailure ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardMetadataDisplay) {
@ -292,6 +304,14 @@ Item {
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.copyingKeycardSuccess)
return true
}
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.migrateFromKeycardToApp) {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migrateKeypairToApp ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToApp ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateSuccess ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateFailure) {
return true
}
}
return false
}
@ -309,7 +329,7 @@ Item {
(root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keycardInserted && !d.hideKeyPair) ||
(root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard && !d.hideKeyPair) ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.recognizedKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateSuccess ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateFailure) {
return keyPairForProcessingComponent
@ -461,18 +481,19 @@ Item {
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.copyingKeycardSuccess)
return keyPairForProcessingComponent
}
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.migrateFromKeycardToApp) {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migrateKeypairToApp ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToApp ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateSuccess ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateFailure) {
return keyPairForProcessingComponent
}
}
return undefined
}
}
Item {
visible: !loader.active
Layout.fillWidth: true
Layout.fillHeight: visible
}
}
states: [
State {
name: Constants.keycardSharedState.pluginReader
@ -556,7 +577,8 @@ Item {
State {
name: "processing"
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToKeycard ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToApp ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.creatingAccountNewSeedPhrase ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.creatingAccountOldSeedPhrase ||
root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.importingFromKeycard ||
@ -572,9 +594,12 @@ Item {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.readingKeycard) {
return qsTr("Reading Keycard...")
}
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeyPair) {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToKeycard) {
return qsTr("Migrating key pair to Keycard")
}
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migratingKeypairToApp) {
return qsTr("Migrating keypair to Status")
}
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.creatingAccountNewSeedPhrase) {
return qsTr("Creating new account...")
}
@ -1023,6 +1048,9 @@ Item {
target: message
text: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateSuccess) {
if (root.sharedKeycardModule.currentState.flowType === Constants.keycardSharedFlow.migrateFromKeycardToApp) {
return qsTr("Keypair was removed from Keycard and is now stored on device.\nYou no longer need this Keycard to transact with the below accounts.")
}
return qsTr("To complete migration close Status and log in with your new Keycard")
}
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.factoryResetSuccess) {
@ -1054,7 +1082,7 @@ Item {
target: title
text: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.keyPairMigrateFailure) {
return qsTr("Key pair failed to migrated")
return qsTr("Failed to migrate keypair")
}
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.creatingAccountNewSeedPhraseFailure) {
return qsTr("Creating new account failed")
@ -1311,6 +1339,48 @@ Item {
target: message
text: ""
}
},
State {
name: Constants.keycardSharedState.migrateKeypairToApp
when: root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migrateKeypairToApp
PropertyChanges {
target: title
text: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migrateKeypairToApp) {
return qsTr("Are you sure you want to migrate\nthis keypair to Status?")
}
return ""
}
font.pixelSize: Constants.keycard.general.fontSize1
font.weight: Font.Bold
color: Theme.palette.directColor1
horizontalAlignment: Text.AlignHCenter
}
PropertyChanges {
target: image
visible: false
}
PropertyChanges {
target: message
text: {
if (root.sharedKeycardModule.currentState.stateType === Constants.keycardSharedState.migrateKeypairToApp) {
let t = qsTr("%1 keypair and its derived account(s) will be fully removed from Keycard and stored on device.",
"",
root.sharedKeycardModule.keyPairForProcessing.accounts.count)
.arg(root.sharedKeycardModule.keyPairForProcessing.name)
t += qsTr("This will make your keypair and derived account(s) less secure as you will no longer require this Keycard to transact.",
"",
root.sharedKeycardModule.keyPairForProcessing.accounts.count)
return t
}
return ""
}
font.pixelSize: Constants.keycard.general.fontSize2
color: Theme.palette.directColor1
Layout.leftMargin: 2 * Style.current.xlPadding
Layout.rightMargin: 2* Style.current.xlPadding
Layout.preferredWidth: layout.width - 4 * Style.current.xlPadding
}
}
]
}

View File

@ -123,6 +123,7 @@ QtObject {
readonly property string changeKeycardPuk: "ChangeKeycardPuk"
readonly property string changePairingCode: "ChangePairingCode"
readonly property string createCopyOfAKeycard: "CreateCopyOfAKeycard"
readonly property string migrateFromKeycardToApp: "MigrateFromKeycardToApp"
}
readonly property QtObject keycardSharedState: QtObject {
@ -167,7 +168,9 @@ QtObject {
readonly property string seedPhraseEnterWords: "SeedPhraseEnterWords"
readonly property string keyPairMigrateSuccess: "KeyPairMigrateSuccess"
readonly property string keyPairMigrateFailure: "KeyPairMigrateFailure"
readonly property string migratingKeyPair: "MigratingKeyPair"
readonly property string migrateKeypairToApp: "MigrateKeypairToApp"
readonly property string migratingKeypairToApp: "MigratingKeypairToApp"
readonly property string migratingKeypairToKeycard: "MigratingKeypairToKeycard"
readonly property string enterPassword: "EnterPassword"
readonly property string wrongPassword: "WrongPassword"
readonly property string biometricsPasswordFailed: "BiometricsPasswordFailed"
@ -634,7 +637,7 @@ QtObject {
readonly property int popupWidth: 640
readonly property int popupHeight: 500
readonly property int popupBiggerHeight: 626
readonly property int titleHeight: 44
readonly property int titleHeight: 60
readonly property int messageHeight: 48
readonly property int footerButtonsHeight: 44
readonly property int loginInfoHeight1: 24

View File

@ -851,10 +851,8 @@ QtObject {
return qsTr("Restored from backup. Import keypair to use derived accounts.")
}
}
if (keypair.syncedFrom !== "") {
return qsTr("Import keypair to use derived accounts")
}
}
return ""
}

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit 3ab312f6d17ab509cd233647bab1b0dcb46435af
Subproject commit fbcda780ec9918a86fa7935d49bed4982bb8bd7c