refactor: use create/restore/login status-go endpoitns for keycard (#15090)
* chore: remove unused storeDefaultKeyPair * chore: added CreateAccount keycard parameters * chore: remove unused newKeycard argument * chore: create keycard account with ImportAccountAndLogin endpoint * fix: remove keycardWhisperPrivateKey CreateAccount parameter * feat: use LoginAccount endpoint for keycard * fix: use CreateAccount RootDataDir instead of BackupDisabledDataDir * fix: use loginAccountKeycard instead of loginAccountKeycardUsingSeedPhrase * fix_: use `login` instead of `loginLocalPairingAccount` an `loginAccountKeycard` * chore: refactor scheduling reencrpytion * fix: FirstRunOldUserKeycardImport * chore: improve code readability * feat: use RestoreAccountAndLogin endpoint for keycard * update status-go
This commit is contained in:
parent
8cca2664e4
commit
c8bc68b96c
|
@ -50,7 +50,6 @@ logScope:
|
|||
|
||||
type
|
||||
AppController* = ref object of RootObj
|
||||
storeDefaultKeyPair: bool
|
||||
syncKeycardBasedOnAppWalletState: bool
|
||||
applyKeycardReplacement: bool
|
||||
changedKeycardUids: seq[tuple[oldKcUid: string, newKcUid: string]] # used in case user unlocked keycard during onboarding using seed phrase
|
||||
|
@ -120,7 +119,6 @@ proc userLoggedIn*(self: AppController): string
|
|||
proc appReady*(self: AppController)
|
||||
proc logout*(self: AppController)
|
||||
proc finishAppLoading*(self: AppController)
|
||||
proc storeDefaultKeyPairForNewKeycardUser*(self: AppController)
|
||||
proc syncKeycardBasedOnAppWalletStateAfterLogin*(self: AppController)
|
||||
proc applyKeycardReplacementAfterLogin*(self: AppController)
|
||||
proc addToKeycardUidPairsToCheckForAChangeAfterLogin*(self: AppController, oldKeycardUid: string, newKeycardUid: string)
|
||||
|
@ -146,7 +144,6 @@ proc connect(self: AppController) =
|
|||
|
||||
proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
||||
result = AppController()
|
||||
result.storeDefaultKeyPair = false
|
||||
result.syncKeycardBasedOnAppWalletState = false
|
||||
result.applyKeycardReplacement = false
|
||||
result.statusFoundation = statusFoundation
|
||||
|
@ -593,9 +590,6 @@ proc applyNecessaryActionsAfterLoggingIn(self: AppController) =
|
|||
discard self.walletAccountService.updateKeycardUid(oldUid, newUid)
|
||||
discard self.walletAccountService.setKeycardUnlocked(singletonInstance.userProfile.getKeyUid(), newUid)
|
||||
|
||||
proc storeDefaultKeyPairForNewKeycardUser*(self: AppController) =
|
||||
self.storeDefaultKeyPair = true
|
||||
|
||||
proc syncKeycardBasedOnAppWalletStateAfterLogin*(self: AppController) =
|
||||
self.syncKeycardBasedOnAppWalletState = true
|
||||
|
||||
|
|
|
@ -75,9 +75,6 @@ QtObject:
|
|||
return "0"
|
||||
return $stint.fromHex(StUint[256], value)
|
||||
|
||||
proc generateAlias*(self: Utils, pk: string): string {.slot.} =
|
||||
return generateAliasFromPk(pk)
|
||||
|
||||
proc readTextFile*(self: Utils, filepath: string): string {.slot.} =
|
||||
try:
|
||||
return readFile(filepath)
|
||||
|
|
|
@ -22,7 +22,7 @@ logScope:
|
|||
|
||||
type ProfileImageDetails = object
|
||||
url*: string
|
||||
croppedImage*: string # TODO: Remove after https://github.com/status-im/status-go/issues/4977
|
||||
croppedImage*: string
|
||||
cropRectangle*: ImageCropRectangle
|
||||
|
||||
type
|
||||
|
@ -189,7 +189,9 @@ proc init*(self: Controller) =
|
|||
proc shouldStartWithOnboardingScreen*(self: Controller): bool =
|
||||
return self.accountsService.openedAccounts().len == 0
|
||||
|
||||
# This is used when fetching backup failed and we create a new displayName and profileImage.
|
||||
# This is used in 2 flows, in case fetching backup failed and we create a new displayName and profileImage:
|
||||
# 1. FirstRunOldUserImportSeedPhrase
|
||||
# 2. FirstRunOldUserKeycardImport
|
||||
# At this point the account is already created in the database. All that's left is to set the displayName and profileImage.
|
||||
proc storeProfileDataAndProceedWithAppLoading*(self: Controller) =
|
||||
self.delegate.removeAllKeycardUidPairsForCheckingForAChangeAfterLogin() # reason for this is in the table in AppController.nim file
|
||||
|
@ -201,12 +203,6 @@ proc storeProfileDataAndProceedWithAppLoading*(self: Controller) =
|
|||
proc checkFetchingStatusAndProceed*(self: Controller) =
|
||||
self.delegate.checkFetchingStatusAndProceed()
|
||||
|
||||
proc getGeneratedAccounts*(self: Controller): seq[GeneratedAccountDto] =
|
||||
return self.accountsService.generatedAccounts()
|
||||
|
||||
proc getImportedAccount*(self: Controller): GeneratedAccountDto =
|
||||
return self.accountsService.getImportedAccount()
|
||||
|
||||
proc getPasswordStrengthScore*(self: Controller, password, userName: string): int =
|
||||
return self.generalService.getPasswordStrengthScore(password, userName)
|
||||
|
||||
|
@ -348,7 +344,6 @@ proc tryToObtainDataFromKeychain*(self: Controller) =
|
|||
let selectedAccount = self.getSelectedLoginAccount()
|
||||
self.keychainService.tryToObtainData(selectedAccount.keyUid)
|
||||
|
||||
# TODO: Remove when implemented https://github.com/status-im/status-go/issues/4977
|
||||
proc storeIdentityImage*(self: Controller): seq[Image] =
|
||||
if self.tmpProfileImageDetails.url.len == 0:
|
||||
return
|
||||
|
@ -375,6 +370,7 @@ proc validMnemonic*(self: Controller, mnemonic: string): bool =
|
|||
|
||||
# validateMnemonicForImport checks if mnemonic is valid and not yet saved in local database
|
||||
proc validateMnemonicForImport*(self: Controller, mnemonic: string): bool =
|
||||
|
||||
let (keyUID, err) = self.accountsService.validateMnemonic(mnemonic)
|
||||
if err.len != 0:
|
||||
self.delegate.emitStartupError(err, StartupErrorType.ImportAccError)
|
||||
|
@ -387,16 +383,6 @@ proc validateMnemonicForImport*(self: Controller, mnemonic: string): bool =
|
|||
self.setSeedPhrase(mnemonic)
|
||||
return true
|
||||
|
||||
# TODO: Remove after https://github.com/status-im/status-go/issues/4977
|
||||
proc importMnemonic*(self: Controller): bool =
|
||||
let error = self.accountsService.importMnemonic(self.tmpSeedPhrase)
|
||||
if(error.len == 0):
|
||||
self.delegate.importAccountSuccess()
|
||||
return true
|
||||
else:
|
||||
self.delegate.emitStartupError(error, StartupErrorType.ImportAccError)
|
||||
return false
|
||||
|
||||
proc setupKeychain(self: Controller, store: bool) =
|
||||
if store:
|
||||
singletonInstance.localAccountSettings.setStoreToKeychainValue(LS_VALUE_NOT_NOW)
|
||||
|
@ -425,6 +411,7 @@ proc importAccountAndLogin*(self: Controller, storeToKeychain: bool, recoverAcco
|
|||
self.connectToFetchingFromWakuEvents()
|
||||
else:
|
||||
self.delegate.moveToLoadingAppState()
|
||||
|
||||
let error = self.accountsService.importAccountAndLogin(
|
||||
self.tmpSeedPhrase,
|
||||
self.tmpPassword,
|
||||
|
@ -433,56 +420,48 @@ proc importAccountAndLogin*(self: Controller, storeToKeychain: bool, recoverAcco
|
|||
self.tmpProfileImageDetails.url,
|
||||
self.tmpProfileImageDetails.cropRectangle,
|
||||
)
|
||||
|
||||
self.processCreateAccountResult(error, storeToKeychain)
|
||||
|
||||
proc storeKeycardAccountAndLogin*(self: Controller, storeToKeychain: bool, newKeycard: bool) =
|
||||
if self.importMnemonic():
|
||||
# NOTE: Called during FirstRunNewUserNewKeycardKeys and FirstRunNewUserImportSeedPhraseIntoKeycard
|
||||
# WARNING: Reuse `importAccountAndLogin` with custom parameters
|
||||
proc storeKeycardAccountAndLogin*(self: Controller, storeToKeychain: bool, newKeycard: bool = true) =
|
||||
self.delegate.moveToLoadingAppState()
|
||||
if newKeycard:
|
||||
self.delegate.storeDefaultKeyPairForNewKeycardUser()
|
||||
self.storeMetadataForNewKeycardUser()
|
||||
else:
|
||||
self.syncKeycardBasedOnAppWalletStateAfterLogin()
|
||||
let (_, flowEvent) = self.keycardService.getLastReceivedKeycardData() # we need this to get the correct instanceUID
|
||||
self.accountsService.setupAccountKeycard(flowEvent, self.tmpDisplayName, useImportedAcc = true)
|
||||
self.setupKeychain(storeToKeychain)
|
||||
else:
|
||||
error "an error ocurred while importing mnemonic"
|
||||
let (_, flowEvent) = self.keycardService.getLastReceivedKeycardData()
|
||||
let error = self.accountsService.importAccountAndLogin(
|
||||
self.tmpSeedPhrase,
|
||||
password = "", # For keycard it will be substituted with`encryption.publicKey` in status-go
|
||||
false,
|
||||
self.tmpDisplayName,
|
||||
self.tmpProfileImageDetails.url,
|
||||
self.tmpProfileImageDetails.cropRectangle,
|
||||
keycardInstanceUID = flowEvent.instanceUID,
|
||||
)
|
||||
self.processCreateAccountResult(error, storeToKeychain)
|
||||
|
||||
# NOTE: Called during FirstRunOldUserKeycardImport
|
||||
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 recoverAccount:
|
||||
self.delegate.prepareAndInitFetchingData()
|
||||
self.connectToFetchingFromWakuEvents()
|
||||
if self.tmpSeedPhrase.len > 0:
|
||||
# if `tmpSeedPhrase` is not empty means user has recovered keycard via seed phrase
|
||||
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.syncKeycardBasedOnAppWalletStateAfterLogin()
|
||||
self.accountsService.setupAccountKeycard(self.tmpKeycardEvent, self.tmpDisplayName, useImportedAcc = false, recoverAccount)
|
||||
self.setupKeychain(storeToKeychain)
|
||||
|
||||
let error = self.accountsService.restoreKeycardAccountAndLogin(
|
||||
self.tmpKeycardEvent,
|
||||
recoverAccount,
|
||||
self.tmpDisplayName,
|
||||
self.tmpProfileImageDetails.url,
|
||||
self.tmpProfileImageDetails.cropRectangle,
|
||||
)
|
||||
|
||||
self.processCreateAccountResult(error, storeToKeychain)
|
||||
|
||||
proc getOpenedAccounts*(self: Controller): seq[AccountDto] =
|
||||
return self.accountsService.openedAccounts()
|
||||
|
@ -509,51 +488,41 @@ proc isSelectedAccountAKeycardAccount*(self: Controller): bool =
|
|||
let selectedAccount = self.getSelectedLoginAccount()
|
||||
return selectedAccount.keycardPairing.len > 0
|
||||
|
||||
proc login*(self: Controller) =
|
||||
proc login*(self: Controller, keycard: bool = false, keycardReplacement: bool = false) =
|
||||
self.delegate.moveToLoadingAppState()
|
||||
let selectedAccount = self.getSelectedLoginAccount()
|
||||
self.accountsService.login(selectedAccount, hashPassword(self.tmpPassword))
|
||||
|
||||
var passwordHash, chatPrivateKey, mnemonic = ""
|
||||
|
||||
if not keycard:
|
||||
passwordHash = hashPassword(self.tmpPassword)
|
||||
else:
|
||||
passwordHash = self.tmpKeycardEvent.encryptionKey.publicKey
|
||||
chatPrivateKey = self.tmpKeycardEvent.whisperKey.privateKey
|
||||
mnemonic = self.tmpSeedPhrase
|
||||
|
||||
if keycard and keycardReplacement:
|
||||
self.delegate.applyKeycardReplacementAfterLogin()
|
||||
|
||||
self.accountsService.login(
|
||||
self.getSelectedLoginAccount(),
|
||||
passwordHash,
|
||||
chatPrivateKey,
|
||||
mnemonic,
|
||||
)
|
||||
|
||||
proc loginLocalPairingAccount*(self: Controller) =
|
||||
self.delegate.moveToLoadingAppState()
|
||||
if self.localPairingStatus.chatKey.len == 0:
|
||||
self.accountsService.login(self.localPairingStatus.account, self.localPairingStatus.password)
|
||||
else:
|
||||
var kcEvent = KeycardEvent()
|
||||
kcEvent.keyUid = self.localPairingStatus.account.keyUid
|
||||
kcEvent.whisperKey.privateKey = self.localPairingStatus.chatKey
|
||||
kcEvent.encryptionKey.publicKey = self.localPairingStatus.password
|
||||
discard self.accountsService.loginAccountKeycard(self.localPairingStatus.account, kcEvent)
|
||||
|
||||
proc loginAccountKeycard*(self: Controller, storeToKeychainValue: string, keycardReplacement = false) =
|
||||
if keycardReplacement:
|
||||
self.delegate.applyKeycardReplacementAfterLogin()
|
||||
singletonInstance.localAccountSettings.setStoreToKeychainValue(storeToKeychainValue)
|
||||
self.delegate.moveToLoadingAppState()
|
||||
let selAcc = self.getSelectedLoginAccount()
|
||||
let error = self.accountsService.loginAccountKeycard(selAcc, self.tmpKeycardEvent)
|
||||
if(error.len > 0):
|
||||
self.delegate.emitAccountLoginError(error)
|
||||
|
||||
proc loginAccountKeycardUsingSeedPhrase*(self: Controller, storeToKeychain: bool) =
|
||||
let acc = self.accountsService.createAccountFromMnemonic(self.getSeedPhrase(), includeEncryption = true, includeWhisper = true)
|
||||
let selAcc = self.getSelectedLoginAccount()
|
||||
|
||||
var kcData = KeycardEvent(
|
||||
keyUid: acc.keyUid,
|
||||
masterKey: KeyDetails(address: acc.address),
|
||||
whisperKey: KeyDetails(privateKey: acc.derivedAccounts.whisper.privateKey),
|
||||
encryptionKey: KeyDetails(publicKey: acc.derivedAccounts.encryption.publicKey)
|
||||
self.accountsService.login(
|
||||
self.localPairingStatus.account,
|
||||
self.localPairingStatus.password,
|
||||
chatPrivateKey = self.localPairingStatus.chatKey
|
||||
)
|
||||
if acc.derivedAccounts.whisper.privateKey.startsWith("0x"):
|
||||
kcData.whisperKey.privateKey = acc.derivedAccounts.whisper.privateKey[2..^1]
|
||||
|
||||
self.setupKeychain(storeToKeychain)
|
||||
|
||||
self.delegate.moveToLoadingAppState()
|
||||
let error = self.accountsService.loginAccountKeycard(selAcc, kcData)
|
||||
if(error.len > 0):
|
||||
self.delegate.emitAccountLoginError(error)
|
||||
# FIXME: Why do we even have storeToKeychain during login? Makes no sense
|
||||
# https://github.com/status-im/status-desktop/issues/15167
|
||||
proc loginAccountKeycard*(self: Controller, storeToKeychain: bool, keycardReplacement = false) =
|
||||
# singletonInstance.localAccountSettings.setStoreToKeychainValue(storeToKeychainValue)
|
||||
self.login(keycard = true, keycardReplacement = keycardReplacement)
|
||||
|
||||
proc convertKeycardProfileKeypairToRegular*(self: Controller) =
|
||||
let acc = self.accountsService.createAccountFromMnemonic(self.getSeedPhrase(), includeEncryption = true)
|
||||
|
@ -633,8 +602,8 @@ proc buildSeedPhrasesFromIndexes*(self: Controller, seedPhraseIndexes: seq[int])
|
|||
proc generateRandomPUK*(self: Controller): string =
|
||||
return self.keycardService.generateRandomPUK()
|
||||
|
||||
# Stores metadata, default Status account only, to the keycard for a newly created keycard user.
|
||||
proc storeMetadataForNewKeycardUser(self: Controller) =
|
||||
## Stores metadata, default Status account only, to the keycard for a newly created keycard user.
|
||||
let paths = @[account_constants.PATH_DEFAULT_WALLET]
|
||||
self.runStoreMetadataFlow(self.getDisplayName(), self.getPin(), paths)
|
||||
|
||||
|
|
|
@ -29,16 +29,16 @@ proc command(self: BiometricsState, controller: Controller, storeToKeychain: boo
|
|||
## but since current implementation is like that and this is not a bug fixing issue, left as it is.
|
||||
controller.importAccountAndLogin(storeToKeychain, recoverAccount = true)
|
||||
elif self.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
|
||||
controller.storeKeycardAccountAndLogin(storeToKeychain, newKeycard = true)
|
||||
controller.storeKeycardAccountAndLogin(storeToKeychain)
|
||||
elif self.flowType == FlowType.FirstRunNewUserImportSeedPhraseIntoKeycard:
|
||||
controller.storeKeycardAccountAndLogin(storeToKeychain, newKeycard = true)
|
||||
controller.storeKeycardAccountAndLogin(storeToKeychain)
|
||||
elif self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
controller.setupKeycardAccount(storeToKeychain, recoverAccount = true)
|
||||
elif self.flowType == FlowType.LostKeycardReplacement:
|
||||
self.storeToKeychain = storeToKeychain
|
||||
controller.startLoginFlowAutomatically(controller.getPin())
|
||||
elif self.flowType == FlowType.LostKeycardConvertToRegularAccount:
|
||||
controller.loginAccountKeycardUsingSeedPhrase(storeToKeychain)
|
||||
controller.loginAccountKeycard(storeToKeychain, keycardReplacement = false)
|
||||
|
||||
method executePrimaryCommand*(self: BiometricsState, controller: Controller) =
|
||||
self.command(controller, true)
|
||||
|
@ -49,10 +49,6 @@ method executeSecondaryCommand*(self: BiometricsState, controller: Controller) =
|
|||
method resolveKeycardNextState*(self: BiometricsState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
|
||||
keycardEvent.error.len == 0:
|
||||
if keycardFlowType == ResponseTypeValueKeycardFlowResult and keycardEvent.error.len == 0:
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
var storeToKeychainValue = LS_VALUE_NEVER
|
||||
if self.storeToKeychain:
|
||||
storeToKeychainValue = LS_VALUE_NOT_NOW
|
||||
controller.loginAccountKeycard(storeToKeychainValue, keycardReplacement = true)
|
||||
controller.loginAccountKeycard(self.storeToKeychain, keycardReplacement = true)
|
||||
|
|
|
@ -32,7 +32,10 @@ method resolveKeycardNextState*(self: KeycardEnterPinState, keycardFlowType: str
|
|||
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
|
||||
if not state.isNil:
|
||||
return state
|
||||
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
|
||||
if self.flowType != FlowType.FirstRunOldUserKeycardImport:
|
||||
return
|
||||
|
||||
if keycardFlowType == ResponseTypeValueEnterPIN and
|
||||
keycardEvent.error.len > 0 and
|
||||
keycardEvent.error == RequestParamPIN:
|
||||
|
@ -55,8 +58,8 @@ method resolveKeycardNextState*(self: KeycardEnterPinState, keycardFlowType: str
|
|||
return createState(StateType.KeycardMaxPairingSlotsReached, self.flowType, self.getBackState)
|
||||
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
if not main_constants.IS_MACOS:
|
||||
controller.setupKeycardAccount(storeToKeychain = false, recoverAccount = true)
|
||||
return createState(StateType.ProfileFetching, self.flowType, nil)
|
||||
if main_constants.SUPPORTS_FINGERPRINT:
|
||||
let backState = findBackStateWithTargetedStateType(self, StateType.RecoverOldUser)
|
||||
return createState(StateType.Biometrics, self.flowType, backState)
|
||||
controller.setupKeycardAccount(storeToKeychain = false, recoverAccount = true)
|
||||
return createState(StateType.ProfileFetching, self.flowType, nil)
|
||||
|
|
|
@ -36,11 +36,11 @@ method resolveKeycardNextState*(self: KeycardEnterPukState, keycardFlowType: str
|
|||
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.setPukValid(true)
|
||||
if not main_constants.IS_MACOS:
|
||||
controller.setupKeycardAccount(storeToKeychain = false)
|
||||
return nil
|
||||
if main_constants.SUPPORTS_FINGERPRINT:
|
||||
let backState = findBackStateWithTargetedStateType(self, StateType.RecoverOldUser)
|
||||
return createState(StateType.Biometrics, self.flowType, backState)
|
||||
controller.setupKeycardAccount(storeToKeychain = false)
|
||||
return nil
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
if keycardFlowType == ResponseTypeValueEnterNewPIN and
|
||||
keycardEvent.error.len > 0 and
|
||||
|
@ -57,5 +57,7 @@ method resolveKeycardNextState*(self: KeycardEnterPukState, keycardFlowType: str
|
|||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.setPukValid(true)
|
||||
let storeToKeychainValue = singletonInstance.localAccountSettings.getStoreToKeychainValue()
|
||||
controller.loginAccountKeycard(storeToKeychainValue)
|
||||
# FIXME: Make sure storeToKeychain is correct here. The idea is not to pass it at all
|
||||
# https://github.com/status-im/status-desktop/issues/15167
|
||||
controller.loginAccountKeycard(storeToKeychain = false)
|
||||
return nil
|
|
@ -19,9 +19,9 @@ method getNextPrimaryState*(self: KeycardPinSetState, controller: Controller): S
|
|||
return createState(StateType.UserProfileCreate, self.flowType, self.getBackState)
|
||||
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
if controller.getValidPuk():
|
||||
if not main_constants.IS_MACOS:
|
||||
return createState(StateType.ProfileFetching, self.flowType, nil)
|
||||
if main_constants.SUPPORTS_FINGERPRINT:
|
||||
return createState(StateType.Biometrics, self.flowType, self.getBackState)
|
||||
return createState(StateType.ProfileFetching, self.flowType, nil)
|
||||
return createState(StateType.KeycardWrongPuk, self.flowType, self.getBackState)
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
if controller.getRecoverKeycardUsingSeedPhraseWhileLoggingIn():
|
||||
|
@ -35,7 +35,7 @@ method getNextPrimaryState*(self: KeycardPinSetState, controller: Controller): S
|
|||
|
||||
method executePrimaryCommand*(self: KeycardPinSetState, controller: Controller) =
|
||||
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
if main_constants.IS_MACOS:
|
||||
if main_constants.SUPPORTS_FINGERPRINT:
|
||||
return
|
||||
if controller.getValidPuk():
|
||||
controller.setupKeycardAccount(storeToKeychain = false, recoverAccount = true)
|
||||
|
@ -44,24 +44,28 @@ method executePrimaryCommand*(self: KeycardPinSetState, controller: Controller)
|
|||
controller.startLoginFlowAutomatically(controller.getPin())
|
||||
return
|
||||
if controller.getValidPuk():
|
||||
let storeToKeychainValue = singletonInstance.localAccountSettings.getStoreToKeychainValue()
|
||||
controller.loginAccountKeycard(storeToKeychainValue)
|
||||
# FIXME: Make sure storeToKeychain is correct here. The idea is not to pass it at all
|
||||
# https://github.com/status-im/status-desktop/issues/15167
|
||||
# let storeToKeychainValue = singletonInstance.localAccountSettings.getStoreToKeychainValue()
|
||||
controller.loginAccountKeycard(storeToKeychain = false)
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
controller.startLoginFlowAutomatically(controller.getPin())
|
||||
|
||||
method resolveKeycardNextState*(self: KeycardPinSetState, keycardFlowType: string, keycardEvent: KeycardEvent,
|
||||
controller: Controller): State =
|
||||
var storeToKeychainValue = LS_VALUE_NEVER
|
||||
if self.flowType == FlowType.LostKeycardReplacement:
|
||||
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
|
||||
keycardEvent.error.len == 0:
|
||||
if main_constants.IS_MACOS:
|
||||
storeToKeychainValue = LS_VALUE_NOT_NOW
|
||||
|
||||
if keycardFlowType != ResponseTypeValueKeycardFlowResult:
|
||||
return
|
||||
|
||||
if keycardEvent.error.len != 0:
|
||||
return
|
||||
|
||||
let keycardReplacement = self.flowType == FlowType.LostKeycardReplacement
|
||||
if not keycardReplacement and self.flowType != FlowType.AppLogin:
|
||||
return
|
||||
|
||||
let storeToKeychain = keycardReplacement and main_constants.SUPPORTS_FINGERPRINT
|
||||
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.loginAccountKeycard(storeToKeychainValue, keycardReplacement = true)
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
|
||||
keycardEvent.error.len == 0:
|
||||
# we are here in case of recover account from the login flow using seed phrase
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.loginAccountKeycard(storeToKeychainValue, keycardReplacement = false)
|
||||
controller.loginAccountKeycard(storeToKeychain, keycardReplacement)
|
||||
|
||||
|
|
|
@ -23,7 +23,9 @@ method resolveKeycardNextState*(self: KeycardWrongPinState, keycardFlowType: str
|
|||
let state = ensureReaderAndCardPresenceOnboarding(self, keycardFlowType, keycardEvent, controller)
|
||||
if not state.isNil:
|
||||
return state
|
||||
if self.flowType == FlowType.FirstRunOldUserKeycardImport:
|
||||
if self.flowType != FlowType.FirstRunOldUserKeycardImport:
|
||||
return
|
||||
|
||||
if keycardFlowType == ResponseTypeValueEnterPIN and
|
||||
keycardEvent.error.len > 0 and
|
||||
keycardEvent.error == RequestParamPIN:
|
||||
|
@ -47,8 +49,8 @@ method resolveKeycardNextState*(self: KeycardWrongPinState, keycardFlowType: str
|
|||
return createState(StateType.KeycardMaxPairingSlotsReached, self.flowType, self.getBackState)
|
||||
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
if not main_constants.IS_MACOS:
|
||||
controller.setupKeycardAccount(storeToKeychain = false)
|
||||
return nil
|
||||
if main_constants.SUPPORTS_FINGERPRINT:
|
||||
let backState = findBackStateWithTargetedStateType(self, StateType.RecoverOldUser)
|
||||
return createState(StateType.Biometrics, self.flowType, backState)
|
||||
controller.setupKeycardAccount(storeToKeychain = false)
|
||||
return nil
|
||||
|
|
|
@ -38,11 +38,11 @@ method resolveKeycardNextState*(self: KeycardWrongPukState, keycardFlowType: str
|
|||
if keycardFlowType == ResponseTypeValueKeycardFlowResult:
|
||||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.setPukValid(true)
|
||||
if not main_constants.IS_MACOS:
|
||||
controller.setupKeycardAccount(storeToKeychain = false, recoverAccount = true)
|
||||
return createState(StateType.ProfileFetching, self.flowType, nil)
|
||||
if main_constants.SUPPORTS_FINGERPRINT:
|
||||
let backState = findBackStateWithTargetedStateType(self, StateType.RecoverOldUser)
|
||||
return createState(StateType.Biometrics, self.flowType, backState)
|
||||
controller.setupKeycardAccount(storeToKeychain = false, recoverAccount = true)
|
||||
return createState(StateType.ProfileFetching, self.flowType, nil)
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
if keycardFlowType == ResponseTypeValueEnterPUK and
|
||||
keycardEvent.error.len > 0 and
|
||||
|
@ -60,5 +60,7 @@ method resolveKeycardNextState*(self: KeycardWrongPukState, keycardFlowType: str
|
|||
controller.setKeycardEvent(keycardEvent)
|
||||
controller.setPukValid(true)
|
||||
let storeToKeychainValue = singletonInstance.localAccountSettings.getStoreToKeychainValue()
|
||||
controller.loginAccountKeycard(storeToKeychainValue)
|
||||
# FIXME: Make sure storeToKeychain is correct here. The idea is not to pass it at all
|
||||
# https://github.com/status-im/status-desktop/issues/15167
|
||||
controller.loginAccountKeycard(false)
|
||||
return nil
|
|
@ -11,4 +11,6 @@ proc delete*(self: LoginKeycardPinVerifiedState) =
|
|||
method executePrimaryCommand*(self: LoginKeycardPinVerifiedState, controller: Controller) =
|
||||
if self.flowType == FlowType.AppLogin:
|
||||
let storeToKeychainValue = singletonInstance.localAccountSettings.getStoreToKeychainValue()
|
||||
controller.loginAccountKeycard(storeToKeychainValue)
|
||||
# FIXME: Make sure storeToKeychain is correct here. The idea is not to pass it at all
|
||||
# https://github.com/status-im/status-desktop/issues/15167
|
||||
controller.loginAccountKeycard(false)
|
||||
|
|
|
@ -25,8 +25,8 @@ method executePrimaryCommand*(self: UserProfileConfirmPasswordState, controller:
|
|||
elif self.flowType == FlowType.FirstRunNewUserImportSeedPhrase:
|
||||
controller.importAccountAndLogin(storeToKeychain)
|
||||
elif self.flowType == FlowType.FirstRunNewUserNewKeycardKeys:
|
||||
controller.storeKeycardAccountAndLogin(storeToKeychain, newKeycard = true)
|
||||
controller.storeKeycardAccountAndLogin(storeToKeychain)
|
||||
elif self.flowType == FlowType.FirstRunOldUserImportSeedPhrase:
|
||||
controller.importAccountAndLogin(storeToKeychain, recoverAccount = true)
|
||||
elif self.flowType == FlowType.LostKeycardConvertToRegularAccount:
|
||||
controller.loginAccountKeycardUsingSeedPhrase(storeToKeychain)
|
||||
controller.loginAccountKeycard(storeToKeychain, keycardReplacement = true)
|
||||
|
|
|
@ -68,9 +68,6 @@ method startUpUIRaised*(self: AccessInterface) {.base.} =
|
|||
method emitLogOut*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getImportedAccount*(self: AccessInterface): GeneratedAccountDto {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method generateImage*(self: AccessInterface, imageUrl: string, aX: int, aY: int, bX: int, bY: int): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
@ -110,9 +107,6 @@ method emitStartupError*(self: AccessInterface, error: string, errType: StartupE
|
|||
method validMnemonic*(self: AccessInterface, mnemonic: string): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method importAccountSuccess*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method setSelectedLoginAccount*(self: AccessInterface, item: login_acc_item.Item) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
@ -152,9 +146,6 @@ method setRemainingAttempts*(self: AccessInterface, value: int) {.base.} =
|
|||
method runFactoryResetPopup*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method storeDefaultKeyPairForNewKeycardUser*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method syncKeycardBasedOnAppWalletStateAfterLogin*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
@ -238,7 +229,6 @@ type
|
|||
c.userLoggedIn()
|
||||
c.finishAppLoading()
|
||||
c.appReady()
|
||||
c.storeDefaultKeyPairForNewKeycardUser()
|
||||
c.syncKeycardBasedOnAppWalletStateAfterLogin()
|
||||
c.applyKeycardReplacementAfterLogin()
|
||||
c.addToKeycardUidPairsToCheckForAChangeAfterLogin(string, string)
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
type
|
||||
Item* = object
|
||||
id: string
|
||||
alias: string
|
||||
address: string
|
||||
pubKey: string
|
||||
keyUid: string
|
||||
|
||||
proc initItem*(id, alias, address, pubKey, keyUid: string): Item =
|
||||
result.id = id
|
||||
result.alias = alias
|
||||
result.address = address
|
||||
result.pubKey = pubKey
|
||||
result.keyUid = keyUid
|
||||
|
||||
proc getId*(self: Item): string =
|
||||
return self.id
|
||||
|
||||
proc getAlias*(self: Item): string =
|
||||
return self.alias
|
||||
|
||||
proc getAddress*(self: Item): string =
|
||||
return self.address
|
||||
|
||||
proc getPubKey*(self: Item): string =
|
||||
return self.pubKey
|
||||
|
||||
proc getKeyUid*(self: Item): string =
|
||||
return self.keyUid
|
|
@ -1,66 +0,0 @@
|
|||
import NimQml, Tables, strutils
|
||||
|
||||
import generated_account_item
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
Id = UserRole + 1
|
||||
Alias
|
||||
Address
|
||||
PubKey
|
||||
KeyUid
|
||||
|
||||
QtObject:
|
||||
type
|
||||
Model* = ref object of QAbstractListModel
|
||||
items: seq[Item]
|
||||
|
||||
proc delete(self: Model) =
|
||||
self.items = @[]
|
||||
self.QAbstractListModel.delete
|
||||
|
||||
proc setup(self: Model) =
|
||||
self.QAbstractListModel.setup
|
||||
|
||||
proc newModel*(): Model =
|
||||
new(result, delete)
|
||||
result.setup
|
||||
|
||||
method rowCount(self: Model, index: QModelIndex = nil): int =
|
||||
return self.items.len
|
||||
|
||||
method roleNames(self: Model): Table[int, string] =
|
||||
{
|
||||
ModelRole.Id.int:"accountId",
|
||||
ModelRole.Alias.int:"username",
|
||||
ModelRole.Address.int:"address",
|
||||
ModelRole.PubKey.int:"pubKey",
|
||||
ModelRole.KeyUid.int:"keyUid"
|
||||
}.toTable
|
||||
|
||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||
if (not index.isValid):
|
||||
return
|
||||
|
||||
if (index.row < 0 or index.row >= self.items.len):
|
||||
return
|
||||
|
||||
let item = self.items[index.row]
|
||||
let enumRole = role.ModelRole
|
||||
|
||||
case enumRole:
|
||||
of ModelRole.Id:
|
||||
result = newQVariant(item.getId())
|
||||
of ModelRole.Alias:
|
||||
result = newQVariant(item.getAlias())
|
||||
of ModelRole.Address:
|
||||
result = newQVariant(item.getAddress())
|
||||
of ModelRole.PubKey:
|
||||
result = newQVariant(item.getPubKey())
|
||||
of ModelRole.KeyUid:
|
||||
result = newQVariant(item.getKeyUid())
|
||||
|
||||
proc setItems*(self: Model, items: seq[Item]) =
|
||||
self.beginResetModel()
|
||||
self.items = items
|
||||
self.endResetModel()
|
|
@ -3,7 +3,6 @@ import NimQml, chronicles
|
|||
import io_interface
|
||||
import view, controller
|
||||
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 app/global/global_singleton
|
||||
|
@ -119,12 +118,6 @@ method load*[T](self: Module[T]) =
|
|||
singletonInstance.engine.setRootContextProperty("startupModule", self.viewVariant)
|
||||
self.controller.init()
|
||||
|
||||
let generatedAccounts = self.controller.getGeneratedAccounts()
|
||||
var accounts: seq[gen_acc_item.Item]
|
||||
for acc in generatedAccounts:
|
||||
accounts.add(gen_acc_item.initItem(acc.id, acc.alias, acc.address, acc.derivedAccounts.whisper.publicKey, acc.keyUid))
|
||||
self.view.setGeneratedAccountList(accounts)
|
||||
|
||||
if self.controller.shouldStartWithOnboardingScreen():
|
||||
self.view.setCurrentStartupState(newWelcomeState(state.FlowType.General, nil))
|
||||
else:
|
||||
|
@ -262,9 +255,6 @@ method onQuinaryActionClicked*[T](self: Module[T]) =
|
|||
self.view.setCurrentStartupState(nextState)
|
||||
debug "quinary_action - set state", setCurrFlow=nextState.flowType(), setCurrState=nextState.stateType()
|
||||
|
||||
method getImportedAccount*[T](self: Module[T]): GeneratedAccountDto =
|
||||
return self.controller.getImportedAccount()
|
||||
|
||||
method generateImage*[T](self: Module[T], imageUrl: string, aX: int, aY: int, bX: int, bY: int): string =
|
||||
return self.controller.generateImage(imageUrl, aX, aY, bX, bY)
|
||||
|
||||
|
@ -304,9 +294,6 @@ method emitStartupError*[T](self: Module[T], error: string, errType: StartupErro
|
|||
method validMnemonic*[T](self: Module[T], mnemonic: string): bool =
|
||||
return self.controller.validMnemonic(mnemonic)
|
||||
|
||||
method importAccountSuccess*[T](self: Module[T]) =
|
||||
self.view.importAccountSuccess()
|
||||
|
||||
method setSelectedLoginAccount*[T](self: Module[T], item: login_acc_item.Item) =
|
||||
self.controller.cancelCurrentFlow()
|
||||
if item.getKeyUid().len == 0:
|
||||
|
@ -535,9 +522,6 @@ method onSharedKeycarModuleFlowTerminated*[T](self: Module[T], lastStepInTheCurr
|
|||
self.view.setCurrentStartupState(newState)
|
||||
debug "new state for onboarding/login flow continuation after shared flow is terminated", setCurrFlow=newState.flowType(), newCurrState=newState.stateType()
|
||||
|
||||
method storeDefaultKeyPairForNewKeycardUser*[T](self: Module[T]) =
|
||||
self.delegate.storeDefaultKeyPairForNewKeycardUser()
|
||||
|
||||
method syncKeycardBasedOnAppWalletStateAfterLogin*[T](self: Module[T]) =
|
||||
self.delegate.syncKeycardBasedOnAppWalletStateAfterLogin()
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@ import NimQml, chronicles
|
|||
import io_interface
|
||||
import selected_login_account
|
||||
import internal/[state, state_wrapper]
|
||||
import models/generated_account_model as gen_acc_model
|
||||
import models/generated_account_item as gen_acc_item
|
||||
import models/login_account_model as login_acc_model
|
||||
import models/login_account_item as login_acc_item
|
||||
import models/fetching_data_model as fetch_model
|
||||
|
@ -25,8 +23,6 @@ QtObject:
|
|||
showBeforeGetStartedPopup: bool
|
||||
currentStartupState: StateWrapper
|
||||
currentStartupStateVariant: QVariant
|
||||
generatedAccountsModel: gen_acc_model.Model
|
||||
generatedAccountsModelVariant: QVariant
|
||||
selectedLoginAccount: SelectedLoginAccount
|
||||
selectedLoginAccountVariant: QVariant
|
||||
loginAccountsModel: login_acc_model.Model
|
||||
|
@ -41,8 +37,6 @@ QtObject:
|
|||
proc delete*(self: View) =
|
||||
self.currentStartupStateVariant.delete
|
||||
self.currentStartupState.delete
|
||||
self.generatedAccountsModel.delete
|
||||
self.generatedAccountsModelVariant.delete
|
||||
self.selectedLoginAccount.delete
|
||||
self.selectedLoginAccountVariant.delete
|
||||
self.loginAccountsModel.delete
|
||||
|
@ -62,8 +56,6 @@ QtObject:
|
|||
result.appState = AppState.StartupState
|
||||
result.currentStartupState = newStateWrapper()
|
||||
result.currentStartupStateVariant = newQVariant(result.currentStartupState)
|
||||
result.generatedAccountsModel = gen_acc_model.newModel()
|
||||
result.generatedAccountsModelVariant = newQVariant(result.generatedAccountsModel)
|
||||
result.selectedLoginAccount = newSelectedLoginAccount()
|
||||
result.selectedLoginAccountVariant = newQVariant(result.selectedLoginAccount)
|
||||
result.loginAccountsModel = login_acc_model.newModel()
|
||||
|
@ -138,35 +130,6 @@ QtObject:
|
|||
proc emitLogOut*(self: View) =
|
||||
self.logOut()
|
||||
|
||||
proc generatedAccountsModelChanged*(self: View) {.signal.}
|
||||
proc getGeneratedAccountsModel(self: View): QVariant {.slot.} =
|
||||
return self.generatedAccountsModelVariant
|
||||
proc setGeneratedAccountList*(self: View, accounts: seq[gen_acc_item.Item]) =
|
||||
self.generatedAccountsModel.setItems(accounts)
|
||||
self.generatedAccountsModelChanged()
|
||||
QtProperty[QVariant] generatedAccountsModel:
|
||||
read = getGeneratedAccountsModel
|
||||
notify = generatedAccountsModelChanged
|
||||
|
||||
proc importedAccountChanged*(self: View) {.signal.}
|
||||
proc getImportedAccountAlias*(self: View): string {.slot.} =
|
||||
return self.delegate.getImportedAccount().alias
|
||||
QtProperty[string] importedAccountAlias:
|
||||
read = getImportedAccountAlias
|
||||
notify = importedAccountChanged
|
||||
|
||||
proc getImportedAccountAddress*(self: View): string {.slot.} =
|
||||
return self.delegate.getImportedAccount().address
|
||||
QtProperty[string] importedAccountAddress:
|
||||
read = getImportedAccountAddress
|
||||
notify = importedAccountChanged
|
||||
|
||||
proc getImportedAccountPubKey*(self: View): string {.slot.} =
|
||||
return self.delegate.getImportedAccount().derivedAccounts.whisper.publicKey
|
||||
QtProperty[string] importedAccountPubKey:
|
||||
read = getImportedAccountPubKey
|
||||
notify = importedAccountChanged
|
||||
|
||||
proc generateImage*(self: View, imageUrl: string, aX: int, aY: int, bX: int, bY: int): string {.slot.} =
|
||||
return self.delegate.generateImage(imageUrl, aX, aY, bX, bY)
|
||||
|
||||
|
@ -207,9 +170,6 @@ QtObject:
|
|||
proc validMnemonic*(self: View, mnemonic: string): bool {.slot.} =
|
||||
return self.delegate.validMnemonic(mnemonic)
|
||||
|
||||
proc importAccountSuccess*(self: View) =
|
||||
self.importedAccountChanged()
|
||||
|
||||
proc selectedLoginAccountChanged*(self: View) {.signal.}
|
||||
proc getSelectedLoginAccount(self: View): QVariant {.slot.} =
|
||||
return self.selectedLoginAccountVariant
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import json, random, times, strutils, sugar, os, re, chronicles
|
||||
import json, times, strutils, sugar, os, re, chronicles
|
||||
import nimcrypto
|
||||
import signing_phrases, account_constants
|
||||
import account_constants
|
||||
|
||||
import ../../constants as main_constants
|
||||
|
||||
|
@ -26,16 +26,6 @@ proc prefix*(methodName: string, isExt:bool = true): string =
|
|||
result = result & (if isExt: "ext_" else: "_")
|
||||
result = result & methodName
|
||||
|
||||
proc generateSigningPhrase*(count: int): string =
|
||||
let now = getTime()
|
||||
var rng = initRand(now.toUnix * 1000000000 + now.nanosecond)
|
||||
var phrases: seq[string] = @[]
|
||||
|
||||
for i in 1..count:
|
||||
phrases.add(rng.sample(signing_phrases.phrases))
|
||||
|
||||
result = phrases.join(" ")
|
||||
|
||||
proc first*(jArray: JsonNode, fieldName, id: string): JsonNode =
|
||||
if jArray == nil:
|
||||
return nil
|
||||
|
|
|
@ -7,7 +7,7 @@ export image_crop_rectangle
|
|||
|
||||
type
|
||||
CreateAccountRequest* = object
|
||||
backupDisabledDataDir*: string
|
||||
rootDataDir*: string
|
||||
kdfIterations*: int
|
||||
deviceName*: string
|
||||
displayName*: string
|
||||
|
@ -38,9 +38,12 @@ type
|
|||
torrentConfigEnabled*: Option[bool]
|
||||
torrentConfigPort*: Option[int]
|
||||
|
||||
keycardInstanceUID*: string
|
||||
keycardPairingDataFile*: string
|
||||
|
||||
proc toJson*(self: CreateAccountRequest): JsonNode =
|
||||
result = %*{
|
||||
"backupDisabledDataDir": self.backupDisabledDataDir,
|
||||
"rootDataDir": self.rootDataDir,
|
||||
"kdfIterations": self.kdfIterations,
|
||||
"deviceName": self.deviceName,
|
||||
"displayName": self.displayName,
|
||||
|
@ -54,6 +57,8 @@ proc toJson*(self: CreateAccountRequest): JsonNode =
|
|||
"logEnabled": self.logEnabled,
|
||||
"previewPrivacy": self.previewPrivacy,
|
||||
"upstreamConfig": self.upstreamConfig,
|
||||
"keycardInstanceUID": self.keycardInstanceUID,
|
||||
"keycardPairingDataFile": self.keycardPairingDataFile,
|
||||
}
|
||||
|
||||
if self.logLevel.isSome():
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import json
|
||||
|
||||
type
|
||||
KeycardData* = ref object
|
||||
keyUID*: string
|
||||
address*: string
|
||||
whisperPrivateKey*: string
|
||||
whisperPublicKey*: string
|
||||
whisperAddress*: string
|
||||
walletPublicKey*: string
|
||||
walletAddress*: string
|
||||
walletRootAddress*: string
|
||||
eip1581Address*: string
|
||||
encryptionPublicKey*: string
|
||||
|
||||
proc toJson*(self: KeycardData): JsonNode =
|
||||
result = %*{
|
||||
"keyUID": self.keyUID,
|
||||
"address": self.address,
|
||||
"whisperPrivateKey": self.whisperPrivateKey,
|
||||
"whisperPublicKey": self.whisperPublicKey,
|
||||
"whisperAddress": self.whisperAddress,
|
||||
"walletPublicKey": self.walletPublicKey,
|
||||
"walletAddress": self.walletAddress,
|
||||
"walletRootAddress": self.walletRootAddress,
|
||||
"eip1581Address": self.eip1581Address,
|
||||
"encryptionPublicKey": self.encryptionPublicKey
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
import json
|
||||
import ./wallet_secretes_config
|
||||
import wallet_secretes_config
|
||||
|
||||
export wallet_secretes_config
|
||||
|
||||
type
|
||||
LoginAccountRequest* = object
|
||||
|
@ -9,6 +11,8 @@ type
|
|||
runtimeLogLevel*: string
|
||||
wakuV2Nameserver*: string
|
||||
bandwidthStatsEnabled*: bool
|
||||
keycardWhisperPrivateKey*: string
|
||||
mnemonic*: string
|
||||
walletSecretsConfig*: WalletSecretsConfig
|
||||
|
||||
proc toJson*(self: LoginAccountRequest): JsonNode =
|
||||
|
@ -19,6 +23,8 @@ proc toJson*(self: LoginAccountRequest): JsonNode =
|
|||
"runtimeLogLevel": self.runtimeLogLevel,
|
||||
"wakuV2Nameserver": self.wakuV2Nameserver,
|
||||
"bandwidthStatsEnabled": self.bandwidthStatsEnabled,
|
||||
"keycardWhisperPrivateKey": self.keycardWhisperPrivateKey,
|
||||
"mnemonic": self.mnemonic,
|
||||
}
|
||||
for key, value in self.walletSecretsConfig.toJson().pairs():
|
||||
result[key] = value
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
import json
|
||||
import create_account_request
|
||||
import create_account_request, keycard_data
|
||||
|
||||
export create_account_request, keycard_data
|
||||
|
||||
type
|
||||
RestoreAccountRequest* = object
|
||||
mnemonic*: string
|
||||
keycard*: KeycardData
|
||||
fetchBackup*: bool
|
||||
createAccountRequest*: CreateAccountRequest
|
||||
|
||||
proc toJson*(self: RestoreAccountRequest): JsonNode =
|
||||
|
||||
result = %*{
|
||||
"mnemonic": self.mnemonic,
|
||||
"fetchBackup": self.fetchBackup
|
||||
"fetchBackup": self.fetchBackup,
|
||||
}
|
||||
|
||||
if self.keycard != nil:
|
||||
result["keycard"] = self.keycard.toJson()
|
||||
|
||||
for key, value in self.createAccountRequest.toJson().pairs():
|
||||
result[key] = value
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import NimQml, Tables, os, json, stew/shims/strformat, sequtils, strutils, uuids, times, std/options
|
||||
import NimQml, Tables, os, json, stew/shims/strformat, sequtils, strutils, times, std/options
|
||||
import json_serialization, chronicles
|
||||
|
||||
import ../../../app/global/global_singleton
|
||||
import ./dto/accounts as dto_accounts
|
||||
import ./dto/generated_accounts as dto_generated_accounts
|
||||
import ./dto/login_request
|
||||
import ./dto/create_account_request
|
||||
import ./dto/restore_account_request
|
||||
|
||||
from ../keycard/service import KeycardEvent, KeyDetails
|
||||
|
@ -20,8 +19,6 @@ import ../../../app/core/fleets/fleet_configuration
|
|||
import ../../common/[account_constants, network_constants, utils]
|
||||
import ../../../constants as main_constants
|
||||
|
||||
import ../settings/dto/settings as settings
|
||||
|
||||
export dto_accounts
|
||||
export dto_generated_accounts
|
||||
|
||||
|
@ -29,8 +26,6 @@ export dto_generated_accounts
|
|||
logScope:
|
||||
topics = "accounts-service"
|
||||
|
||||
const DEFAULT_WALLET_ACCOUNT_NAME = "Account 1"
|
||||
const PATHS = @[PATH_WALLET_ROOT, PATH_EIP_1581, PATH_WHISPER, PATH_DEFAULT_WALLET, PATH_ENCRYPTION]
|
||||
const ACCOUNT_ALREADY_EXISTS_ERROR* = "account already exists"
|
||||
const KDF_ITERATIONS* {.intdefine.} = 256_000
|
||||
const DEFAULT_CUSTOMIZATION_COLOR = "primary" # to match `CustomizationColor` on the go side
|
||||
|
@ -62,15 +57,15 @@ QtObject:
|
|||
events: EventEmitter
|
||||
threadpool: ThreadPool
|
||||
fleetConfiguration: FleetConfiguration
|
||||
generatedAccounts: seq[GeneratedAccountDto]
|
||||
accounts: seq[AccountDto]
|
||||
loggedInAccount: AccountDto
|
||||
importedAccount: GeneratedAccountDto
|
||||
keyStoreDir: string
|
||||
defaultWalletEmoji: string
|
||||
tmpAccount: AccountDto
|
||||
tmpHashedPassword: string
|
||||
|
||||
proc restoreAccountAndLogin(self: Service, request: RestoreAccountRequest): string
|
||||
|
||||
proc delete*(self: Service) =
|
||||
self.QObject.delete
|
||||
|
||||
|
@ -83,6 +78,8 @@ QtObject:
|
|||
result.keyStoreDir = main_constants.ROOTKEYSTOREDIR
|
||||
result.defaultWalletEmoji = ""
|
||||
|
||||
proc scheduleReencrpytion(self: Service, account: AccountDto, hashedPassword: string, timeout: int = 1000)
|
||||
|
||||
proc setLocalAccountSettingsFile(self: Service) =
|
||||
if self.loggedInAccount.isValid():
|
||||
singletonInstance.localAccountSettings.setFileName(self.loggedInAccount.name)
|
||||
|
@ -99,9 +96,6 @@ QtObject:
|
|||
self.loggedInAccount.images = images
|
||||
singletonInstance.localAccountSettings.setFileName(displayName)
|
||||
|
||||
proc getImportedAccount*(self: Service): GeneratedAccountDto =
|
||||
return self.importedAccount
|
||||
|
||||
proc setKeyStoreDir(self: Service, key: string) =
|
||||
self.keyStoreDir = joinPath(main_constants.ROOTKEYSTOREDIR, key) & main_constants.sep
|
||||
discard status_general.initKeystore(self.keyStoreDir)
|
||||
|
@ -118,22 +112,10 @@ QtObject:
|
|||
self.updateLoggedInAccount(receivedData.backedUpProfile.displayName, receivedData.backedUpProfile.images)
|
||||
|
||||
proc init*(self: Service) =
|
||||
try:
|
||||
let response = status_account.generateAddresses(PATHS)
|
||||
|
||||
self.generatedAccounts = map(response.result.getElems(),
|
||||
proc(x: JsonNode): GeneratedAccountDto = toGeneratedAccountDto(x))
|
||||
|
||||
for account in self.generatedAccounts.mitems:
|
||||
account.alias = generateAliasFromPk(account.derivedAccounts.whisper.publicKey)
|
||||
|
||||
except Exception as e:
|
||||
error "error: ", procName="init", errName = e.name, errDesription = e.msg
|
||||
discard
|
||||
|
||||
proc clear*(self: Service) =
|
||||
self.generatedAccounts = @[]
|
||||
self.loggedInAccount = AccountDto()
|
||||
self.importedAccount = GeneratedAccountDto()
|
||||
|
||||
proc validateMnemonic*(self: Service, mnemonic: string): (string, string) =
|
||||
try:
|
||||
|
@ -144,13 +126,6 @@ QtObject:
|
|||
except Exception as e:
|
||||
error "error: ", procName="validateMnemonic", errName = e.name, errDesription = e.msg
|
||||
|
||||
proc generatedAccounts*(self: Service): seq[GeneratedAccountDto] =
|
||||
if(self.generatedAccounts.len == 0):
|
||||
error "There was some issue initiating account service"
|
||||
return
|
||||
|
||||
result = self.generatedAccounts
|
||||
|
||||
proc openedAccounts*(self: Service): seq[AccountDto] =
|
||||
try:
|
||||
let response = status_account.openedAccounts(main_constants.STATUSGODIR)
|
||||
|
@ -165,106 +140,12 @@ QtObject:
|
|||
proc openedAccountsContainsKeyUid*(self: Service, keyUid: string): bool =
|
||||
return (keyUID in self.openedAccounts().mapIt(it.keyUid))
|
||||
|
||||
proc saveKeycardAccountAndLogin(self: Service, chatKey, password: string, account, subaccounts, settings,
|
||||
config: JsonNode): AccountDto =
|
||||
try:
|
||||
let response = status_account.saveAccountAndLoginWithKeycard(chatKey, password, account, subaccounts, settings, config)
|
||||
|
||||
var error = "response doesn't contain \"error\""
|
||||
if(response.result.contains("error")):
|
||||
error = response.result["error"].getStr
|
||||
if error == "":
|
||||
debug "Account saved succesfully"
|
||||
result = toAccountDto(account)
|
||||
return
|
||||
|
||||
let err = "Error saving account and logging in via keycard : " & error
|
||||
error "error: ", procName="saveKeycardAccountAndLogin", errDesription = err
|
||||
|
||||
except Exception as e:
|
||||
error "error: ", procName="saveKeycardAccountAndLogin", errName = e.name, errDesription = e.msg
|
||||
|
||||
proc prepareSubaccountJsonObject(self: Service, account: GeneratedAccountDto, displayName: string):
|
||||
JsonNode =
|
||||
result = %* [
|
||||
{
|
||||
"public-key": account.derivedAccounts.defaultWallet.publicKey,
|
||||
"address": account.derivedAccounts.defaultWallet.address,
|
||||
"colorId": DEFAULT_CUSTOMIZATION_COLOR,
|
||||
"wallet": true,
|
||||
"path": PATH_DEFAULT_WALLET,
|
||||
"name": DEFAULT_WALLET_ACCOUNT_NAME,
|
||||
"derived-from": account.address,
|
||||
"emoji": self.defaultWalletEmoji
|
||||
},
|
||||
{
|
||||
"public-key": account.derivedAccounts.whisper.publicKey,
|
||||
"address": account.derivedAccounts.whisper.address,
|
||||
"name": if displayName == "": account.alias else: displayName,
|
||||
"path": PATH_WHISPER,
|
||||
"chat": true,
|
||||
"derived-from": ""
|
||||
}
|
||||
]
|
||||
|
||||
proc getSubaccountDataForAccountId(self: Service, accountId: string, displayName: string): JsonNode =
|
||||
for acc in self.generatedAccounts:
|
||||
if(acc.id == accountId):
|
||||
return self.prepareSubaccountJsonObject(acc, displayName)
|
||||
|
||||
if(self.importedAccount.isValid()):
|
||||
if(self.importedAccount.id == accountId):
|
||||
return self.prepareSubaccountJsonObject(self.importedAccount, displayName)
|
||||
|
||||
proc toStatusGoSupportedLogLevel*(logLevel: string): string =
|
||||
if logLevel == "TRACE":
|
||||
return "DEBUG"
|
||||
return logLevel
|
||||
|
||||
proc prepareAccountSettingsJsonObject(self: Service, account: GeneratedAccountDto,
|
||||
installationId: string, displayName: string, withoutMnemonic: bool): JsonNode =
|
||||
result = %* {
|
||||
"key-uid": account.keyUid,
|
||||
"mnemonic": if withoutMnemonic: "" else: account.mnemonic,
|
||||
"public-key": account.derivedAccounts.whisper.publicKey,
|
||||
"name": account.alias,
|
||||
"display-name": displayName,
|
||||
"address": account.address,
|
||||
"eip1581-address": account.derivedAccounts.eip1581.address,
|
||||
"dapps-address": account.derivedAccounts.defaultWallet.address,
|
||||
"wallet-root-address": account.derivedAccounts.walletRoot.address,
|
||||
"preview-privacy?": true,
|
||||
"signing-phrase": generateSigningPhrase(3),
|
||||
"log-level": main_constants.LOG_LEVEL,
|
||||
"latest-derived-path": 0,
|
||||
"currency": "usd",
|
||||
"networks/networks": @[],
|
||||
"networks/current-network": "",
|
||||
"wallet/visible-tokens": {},
|
||||
"waku-enabled": true,
|
||||
"appearance": 0,
|
||||
"installation-id": installationId,
|
||||
"current-user-status": %* {
|
||||
"publicKey": account.derivedAccounts.whisper.publicKey,
|
||||
"statusType": 1,
|
||||
"clock": 0,
|
||||
"text": ""
|
||||
},
|
||||
"profile-pictures-show-to": settings.PROFILE_PICTURES_SHOW_TO_EVERYONE,
|
||||
"profile-pictures-visibility": settings.PROFILE_PICTURES_VISIBILITY_EVERYONE,
|
||||
"url-unfurling-mode": int(settings.UrlUnfurlingMode.AlwaysAsk),
|
||||
}
|
||||
|
||||
proc getAccountSettings(self: Service, accountId: string, installationId: string, displayName: string, withoutMnemonic: bool): JsonNode =
|
||||
for acc in self.generatedAccounts:
|
||||
if(acc.id == accountId):
|
||||
return self.prepareAccountSettingsJsonObject(acc, installationId, displayName, withoutMnemonic)
|
||||
|
||||
if(self.importedAccount.isValid()):
|
||||
if(self.importedAccount.id == accountId):
|
||||
return self.prepareAccountSettingsJsonObject(self.importedAccount, installationId, displayName, withoutMnemonic)
|
||||
|
||||
# TODO: Remove after https://github.com/status-im/status-go/issues/4977
|
||||
# TODO: Remove after https://github.com/status-im/status-desktop/issues/11435
|
||||
proc getDefaultNodeConfig*(self: Service, installationId: string, recoverAccount: bool): JsonNode =
|
||||
let fleet = Fleet.ShardsTest
|
||||
let dnsDiscoveryURL = "enrtree://AMOJVZX4V6EXP7NTJPMAYJYST2QP6AJXYW76IU6VGJS7UVSNDYZG4@boot.test.shards.nodes.status.im"
|
||||
|
@ -305,49 +186,8 @@ QtObject:
|
|||
result["KeycardPairingDataFile"] = newJString(main_constants.KEYCARDPAIRINGDATAFILE)
|
||||
result["ProcessBackedupMessages"] = newJBool(recoverAccount)
|
||||
|
||||
# TODO: Remove after https://github.com/status-im/status-go/issues/4977
|
||||
proc getLoginNodeConfig(self: Service): JsonNode =
|
||||
# To create appropriate NodeConfig for Login we set only params that maybe be set via env variables or cli flags
|
||||
result = %*{}
|
||||
|
||||
# mandatory params
|
||||
result["NetworkId"] = NETWORKS[0]{"chainId"}
|
||||
result["DataDir"] = %* "./ethereum/mainnet"
|
||||
result["KeyStoreDir"] = %* self.keyStoreDir.replace(main_constants.STATUSGODIR, "")
|
||||
result["KeycardPairingDataFile"] = %* main_constants.KEYCARDPAIRINGDATAFILE
|
||||
|
||||
# other params
|
||||
result["Networks"] = NETWORKS
|
||||
|
||||
result["UpstreamConfig"] = %* {
|
||||
"URL": NETWORKS[0]{"rpcUrl"},
|
||||
"Enabled": true,
|
||||
}
|
||||
|
||||
result["ShhextConfig"] = %* {
|
||||
"VerifyENSURL": NETWORKS[0]{"fallbackUrl"},
|
||||
"VerifyTransactionURL": NETWORKS[0]{"fallbackUrl"}
|
||||
}
|
||||
|
||||
result["WakuV2Config"] = %* {
|
||||
"Port": WAKU_V2_PORT,
|
||||
"UDPPort": WAKU_V2_PORT
|
||||
}
|
||||
|
||||
result["WalletConfig"] = NODE_CONFIG["WalletConfig"]
|
||||
|
||||
result["TorrentConfig"] = %* {
|
||||
"Port": TORRENT_CONFIG_PORT,
|
||||
"DataDir": DEFAULT_TORRENT_CONFIG_DATADIR,
|
||||
"TorrentDir": DEFAULT_TORRENT_CONFIG_TORRENTDIR
|
||||
}
|
||||
|
||||
if main_constants.runtimeLogLevelSet():
|
||||
result["RuntimeLogLevel"] = newJString(toStatusGoSupportedLogLevel(main_constants.LOG_LEVEL))
|
||||
|
||||
if STATUS_PORT != 0:
|
||||
result["ListenAddr"] = newJString("0.0.0.0:" & $main_constants.STATUS_PORT)
|
||||
|
||||
# FIXME: remove this method, settings should be processed in status-go
|
||||
# https://github.com/status-im/status-go/issues/5359
|
||||
proc addKeycardDetails(self: Service, kcInstance: string, settingsJson: var JsonNode, accountData: var JsonNode) =
|
||||
let keycardPairingJsonString = readFile(main_constants.KEYCARDPAIRINGDATAFILE)
|
||||
let keycardPairingJsonObj = keycardPairingJsonString.parseJSON
|
||||
|
@ -383,7 +223,7 @@ QtObject:
|
|||
|
||||
proc buildCreateAccountRequest(self: Service, password: string, displayName: string, imagePath: string, imageCropRectangle: ImageCropRectangle): CreateAccountRequest =
|
||||
return CreateAccountRequest(
|
||||
backupDisabledDataDir: main_constants.STATUSGODIR,
|
||||
rootDataDir: main_constants.STATUSGODIR,
|
||||
kdfIterations: KDF_ITERATIONS,
|
||||
password: hashPassword(password),
|
||||
displayName: displayName,
|
||||
|
@ -396,6 +236,7 @@ QtObject:
|
|||
previewPrivacy: true,
|
||||
torrentConfigEnabled: some(false),
|
||||
torrentConfigPort: some(TORRENT_CONFIG_PORT),
|
||||
keycardPairingDataFile: main_constants.KEYCARDPAIRINGDATAFILE,
|
||||
walletSecretsConfig: self.buildWalletSecrets(),
|
||||
)
|
||||
|
||||
|
@ -420,13 +261,57 @@ QtObject:
|
|||
error "failed to create account or login", procName="createAccountAndLogin", errName = e.name, errDesription = e.msg
|
||||
return e.msg
|
||||
|
||||
proc importAccountAndLogin*(self: Service, mnemonic: string, password: string, recoverAccount: bool, displayName: string, imagePath: string, imageCropRectangle: ImageCropRectangle): string =
|
||||
try:
|
||||
let request = RestoreAccountRequest(
|
||||
proc importAccountAndLogin*(self: Service,
|
||||
mnemonic: string,
|
||||
password: string,
|
||||
recoverAccount: bool,
|
||||
displayName: string,
|
||||
imagePath: string,
|
||||
imageCropRectangle: ImageCropRectangle,
|
||||
keycardInstanceUID: string = "",
|
||||
): string =
|
||||
|
||||
var request = RestoreAccountRequest(
|
||||
mnemonic: mnemonic,
|
||||
fetchBackup: recoverAccount,
|
||||
createAccountRequest: self.buildCreateAccountRequest(password, displayName, imagePath, imageCropRectangle),
|
||||
)
|
||||
request.createAccountRequest.keycardInstanceUID = keycardInstanceUID
|
||||
|
||||
self.restoreAccountAndLogin(request)
|
||||
|
||||
proc restoreKeycardAccountAndLogin*(self: Service,
|
||||
keycardData: KeycardEvent,
|
||||
recoverAccount: bool,
|
||||
displayName: string,
|
||||
imagePath: string,
|
||||
imageCropRectangle: ImageCropRectangle,
|
||||
): string =
|
||||
|
||||
let keycard = KeycardData(
|
||||
keyUid: keycardData.keyUid,
|
||||
address: keycardData.masterKey.address,
|
||||
whisperPrivateKey: keycardData.whisperKey.privateKey,
|
||||
whisperPublicKey: keycardData.whisperKey.publicKey,
|
||||
whisperAddress: keycardData.whisperKey.address,
|
||||
walletPublicKey: keycardData.walletKey.publicKey,
|
||||
walletAddress: keycardData.walletKey.address,
|
||||
walletRootAddress: keycardData.walletRootKey.address,
|
||||
eip1581Address: keycardData.eip1581Key.address,
|
||||
encryptionPublicKey: keycardData.encryptionKey.publicKey,
|
||||
)
|
||||
|
||||
var request = RestoreAccountRequest(
|
||||
keycard: keycard,
|
||||
fetchBackup: recoverAccount,
|
||||
createAccountRequest: self.buildCreateAccountRequest("", displayName, imagePath, imageCropRectangle),
|
||||
)
|
||||
request.createAccountRequest.keycardInstanceUID = keycardData.instanceUid
|
||||
|
||||
return self.restoreAccountAndLogin(request)
|
||||
|
||||
proc restoreAccountAndLogin(self: Service, request: RestoreAccountRequest): string =
|
||||
try:
|
||||
let response = status_account.restoreAccountAndLogin(request)
|
||||
|
||||
if not response.result.contains("error"):
|
||||
|
@ -438,120 +323,11 @@ QtObject:
|
|||
debug "Account saved succesfully"
|
||||
return ""
|
||||
|
||||
error "importAccountAndLogin status-go error: ", error
|
||||
return "importAccountAndLogin failed: " & error
|
||||
error "restoreAccountAndLogin status-go error: ", error
|
||||
return "restoreAccountAndLogin failed: " & error
|
||||
|
||||
except Exception as e:
|
||||
error "failed to import account or login", procName="importAccountAndLogin", errName = e.name, errDesription = e.msg
|
||||
return e.msg
|
||||
|
||||
proc setupAccountKeycard*(self: Service, keycardData: KeycardEvent, displayName: string, useImportedAcc: bool,
|
||||
recoverAccount: bool = false) =
|
||||
try:
|
||||
var keyUid = keycardData.keyUid
|
||||
var address = keycardData.masterKey.address
|
||||
var whisperPrivateKey = keycardData.whisperKey.privateKey
|
||||
var whisperPublicKey = keycardData.whisperKey.publicKey
|
||||
var whisperAddress = keycardData.whisperKey.address
|
||||
var walletPublicKey = keycardData.walletKey.publicKey
|
||||
var walletAddress = keycardData.walletKey.address
|
||||
var walletRootAddress = keycardData.walletRootKey.address
|
||||
var eip1581Address = keycardData.eip1581Key.address
|
||||
var encryptionPublicKey = keycardData.encryptionKey.publicKey
|
||||
if useImportedAcc:
|
||||
keyUid = self.importedAccount.keyUid
|
||||
address = self.importedAccount.address
|
||||
whisperPublicKey = self.importedAccount.derivedAccounts.whisper.publicKey
|
||||
whisperAddress = self.importedAccount.derivedAccounts.whisper.address
|
||||
walletPublicKey = self.importedAccount.derivedAccounts.defaultWallet.publicKey
|
||||
walletAddress = self.importedAccount.derivedAccounts.defaultWallet.address
|
||||
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]
|
||||
|
||||
let installationId = $genUUID()
|
||||
let alias = generateAliasFromPk(whisperPublicKey)
|
||||
|
||||
var accountDataJson = %* {
|
||||
"name": if displayName == "": alias else: displayName,
|
||||
"display-name": displayName,
|
||||
"address": address,
|
||||
"key-uid": keyUid,
|
||||
"kdfIterations": KDF_ITERATIONS,
|
||||
}
|
||||
|
||||
self.setKeyStoreDir(keyUid)
|
||||
let nodeConfigJson = self.getDefaultNodeConfig(installationId, recoverAccount)
|
||||
let subaccountDataJson = %* [
|
||||
{
|
||||
"public-key": walletPublicKey,
|
||||
"address": walletAddress,
|
||||
"colorId": DEFAULT_CUSTOMIZATION_COLOR,
|
||||
"wallet": true,
|
||||
"path": PATH_DEFAULT_WALLET,
|
||||
"name": DEFAULT_WALLET_ACCOUNT_NAME,
|
||||
"derived-from": address,
|
||||
"emoji": self.defaultWalletEmoji,
|
||||
},
|
||||
{
|
||||
"public-key": whisperPublicKey,
|
||||
"address": whisperAddress,
|
||||
"name": if displayName == "": alias else: displayName,
|
||||
"path": PATH_WHISPER,
|
||||
"chat": true,
|
||||
"derived-from": ""
|
||||
}
|
||||
]
|
||||
|
||||
var settingsJson = %* {
|
||||
"key-uid": keyUid,
|
||||
"public-key": whisperPublicKey,
|
||||
"name": alias,
|
||||
"display-name": displayName,
|
||||
"address": address,
|
||||
"eip1581-address": eip1581Address,
|
||||
"dapps-address": walletAddress,
|
||||
"wallet-root-address": walletRootAddress,
|
||||
"preview-privacy?": true,
|
||||
"signing-phrase": generateSigningPhrase(3),
|
||||
"log-level": main_constants.LOG_LEVEL,
|
||||
"latest-derived-path": 0,
|
||||
"currency": "usd",
|
||||
"networks/networks": @[],
|
||||
"networks/current-network": "",
|
||||
"wallet/visible-tokens": {},
|
||||
"waku-enabled": true,
|
||||
"appearance": 0,
|
||||
"installation-id": installationId,
|
||||
"current-user-status": {
|
||||
"publicKey": whisperPublicKey,
|
||||
"statusType": 1,
|
||||
"clock": 0,
|
||||
"text": ""
|
||||
}
|
||||
}
|
||||
|
||||
self.addKeycardDetails(keycardData.instanceUID, settingsJson, accountDataJson)
|
||||
|
||||
if(accountDataJson.isNil or subaccountDataJson.isNil or settingsJson.isNil or
|
||||
nodeConfigJson.isNil):
|
||||
let description = "at least one json object is not prepared well"
|
||||
error "error: ", procName="setupAccountKeycard", errDesription = description
|
||||
return
|
||||
|
||||
self.loggedInAccount = self.saveKeycardAccountAndLogin(chatKey = whisperPrivateKey,
|
||||
password = encryptionPublicKey,
|
||||
accountDataJson,
|
||||
subaccountDataJson,
|
||||
settingsJson,
|
||||
nodeConfigJson)
|
||||
self.setLocalAccountSettingsFile()
|
||||
except Exception as e:
|
||||
error "error: ", procName="setupAccount", errName = e.name, errDesription = e.msg
|
||||
error "restore account failed", procName="restoreAccountAndLogin", errName = e.name, errDesription = e.msg
|
||||
|
||||
proc createAccountFromPrivateKey*(self: Service, privateKey: string): GeneratedAccountDto =
|
||||
if privateKey.len == 0:
|
||||
|
@ -610,27 +386,6 @@ QtObject:
|
|||
data.error = e.msg
|
||||
self.events.emit(SIGNAL_DERIVED_ADDRESSES_FROM_NOT_IMPORTED_MNEMONIC_FETCHED, data)
|
||||
|
||||
proc importMnemonic*(self: Service, mnemonic: string): string =
|
||||
if mnemonic.len == 0:
|
||||
return "empty mnemonic"
|
||||
try:
|
||||
let response = status_account.multiAccountImportMnemonic(mnemonic)
|
||||
self.importedAccount = toGeneratedAccountDto(response.result)
|
||||
|
||||
if (self.accounts.contains(self.importedAccount.keyUid)):
|
||||
return ACCOUNT_ALREADY_EXISTS_ERROR
|
||||
|
||||
let responseDerived = status_account.deriveAccounts(self.importedAccount.id, PATHS)
|
||||
self.importedAccount.derivedAccounts = toDerivedAccounts(responseDerived.result)
|
||||
|
||||
self.importedAccount.alias= generateAliasFromPk(self.importedAccount.derivedAccounts.whisper.publicKey)
|
||||
|
||||
if (not self.importedAccount.isValid()):
|
||||
return "imported account is not valid"
|
||||
except Exception as e:
|
||||
error "error: ", procName="importMnemonic", errName = e.name, errDesription = e.msg
|
||||
return e.msg
|
||||
|
||||
proc verifyAccountPassword*(self: Service, account: string, password: string): bool =
|
||||
try:
|
||||
let response = status_account.verifyAccountPassword(account, utils.hashPassword(password), self.keyStoreDir)
|
||||
|
@ -657,11 +412,13 @@ QtObject:
|
|||
except Exception as e:
|
||||
error "error: ", procName="verifyDatabasePassword", errName = e.name, errDesription = e.msg
|
||||
|
||||
proc doLogin(self: Service, account: AccountDto, passwordHash: string) =
|
||||
proc doLogin(self: Service, account: AccountDto, passwordHash: string, chatPrivateKey: string = "", mnemonic: string = "") =
|
||||
var request = LoginAccountRequest(
|
||||
keyUid: account.keyUid,
|
||||
kdfIterations: account.kdfIterations,
|
||||
passwordHash: passwordHash,
|
||||
keycardWhisperPrivateKey: chatPrivateKey,
|
||||
mnemonic: mnemonic,
|
||||
walletSecretsConfig: self.buildWalletSecrets(),
|
||||
bandwidthStatsEnabled: true,
|
||||
)
|
||||
|
@ -678,8 +435,9 @@ QtObject:
|
|||
debug "account logged in"
|
||||
self.setLocalAccountSettingsFile()
|
||||
|
||||
proc login*(self: Service, account: AccountDto, hashedPassword: string) =
|
||||
proc login*(self: Service, account: AccountDto, hashedPassword: string, chatPrivateKey: string = "", mnemonic: string = "") =
|
||||
try:
|
||||
# WARNING: Is this keystore migration still needed?
|
||||
let keyStoreDir = joinPath(main_constants.ROOTKEYSTOREDIR, account.keyUid) & main_constants.sep
|
||||
if not dirExists(keyStoreDir):
|
||||
os.createDir(keyStoreDir)
|
||||
|
@ -689,29 +447,32 @@ QtObject:
|
|||
|
||||
self.setKeyStoreDir(account.keyUid)
|
||||
|
||||
let isOldHashPassword = self.verifyDatabasePassword(account.keyUid, hashedPasswordToUpperCase(hashedPassword))
|
||||
if isOldHashPassword:
|
||||
if mnemonic == "":
|
||||
let oldHashedPassword = hashedPasswordToUpperCase(hashedPassword)
|
||||
if self.verifyDatabasePassword(account.keyUid, oldHashedPassword):
|
||||
self.scheduleReencrpytion(account, hashedPassword, timeout = 1000)
|
||||
return
|
||||
|
||||
self.doLogin(account, hashedPassword, chatPrivateKey, mnemonic)
|
||||
|
||||
except Exception as e:
|
||||
error "login failed", errName = e.name, errDesription = e.msg
|
||||
self.events.emit(SIGNAL_LOGIN_ERROR, LoginErrorArgs(error: e.msg))
|
||||
|
||||
proc scheduleReencrpytion(self: Service, account: AccountDto, hashedPassword: string, timeout: int = 1000) =
|
||||
debug "database reencryption scheduled"
|
||||
|
||||
# Save tmp properties so that we can login after the timer
|
||||
self.tmpAccount = account
|
||||
self.tmpHashedPassword = hashedPassword
|
||||
|
||||
# Start a 1 second timer for the loading screen to appear
|
||||
let arg = TimerTaskArg(
|
||||
tptr: timerTask,
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "onWaitForReencryptionTimeout",
|
||||
timeoutInMilliseconds: 1000
|
||||
timeoutInMilliseconds: timeout
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
return
|
||||
|
||||
self.doLogin(account, hashedPassword)
|
||||
|
||||
except Exception as e:
|
||||
error "login failed", errName = e.name, errDesription = e.msg
|
||||
self.events.emit(SIGNAL_LOGIN_ERROR, LoginErrorArgs(error: e.msg))
|
||||
|
||||
proc onWaitForReencryptionTimeout(self: Service, response: string) {.slot.} =
|
||||
debug "starting database reencryption"
|
||||
|
@ -727,34 +488,6 @@ QtObject:
|
|||
self.tmpAccount = AccountDto()
|
||||
self.tmpHashedPassword = ""
|
||||
|
||||
proc loginAccountKeycard*(self: Service, accToBeLoggedIn: AccountDto, keycardData: KeycardEvent): string =
|
||||
try:
|
||||
self.setKeyStoreDir(keycardData.keyUid)
|
||||
|
||||
var accountDataJson = %* {
|
||||
"key-uid": accToBeLoggedIn.keyUid,
|
||||
}
|
||||
|
||||
let nodeConfigJson = self.getLoginNodeConfig()
|
||||
|
||||
let response = status_account.loginWithKeycard(keycardData.whisperKey.privateKey,
|
||||
keycardData.encryptionKey.publicKey,
|
||||
accountDataJson,
|
||||
nodeConfigJson)
|
||||
|
||||
var error = "response doesn't contain \"error\""
|
||||
if(response.result.contains("error")):
|
||||
error = response.result["error"].getStr
|
||||
if error == "":
|
||||
debug "Account logged in succesfully"
|
||||
# this should be fetched later from waku
|
||||
self.loggedInAccount = accToBeLoggedIn
|
||||
self.setLocalAccountSettingsFile()
|
||||
return
|
||||
except Exception as e:
|
||||
error "keycard login failed", procName="loginAccountKeycard", errName = e.name, errDesription = e.msg
|
||||
return e.msg
|
||||
|
||||
proc convertRegularProfileKeypairToKeycard*(self: Service, keycardUid, currentPassword: string, newPassword: string) =
|
||||
var accountDataJson = %* {
|
||||
"key-uid": self.getLoggedInAccount().keyUid,
|
||||
|
@ -816,7 +549,7 @@ QtObject:
|
|||
if(errMsg.len == 0):
|
||||
result = true
|
||||
else:
|
||||
error "error: ", procName="onConvertKeycardProfileKeypairToRegular", errDesription = errMsg
|
||||
error "failed to convert keycard account", procName="onConvertKeycardProfileKeypairToRegular", errDesription = errMsg
|
||||
except Exception as e:
|
||||
error "error handilng migrated keypair response", procName="onConvertKeycardProfileKeypairToRegular", errDesription=e.msg
|
||||
self.events.emit(SIGNAL_CONVERTING_PROFILE_KEYPAIR, ResultArgs(success: result))
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import json
|
||||
import ../../../backend/accounts as status_account
|
||||
import ../../common/conversion
|
||||
|
||||
|
@ -42,9 +41,6 @@ proc compressCommunityKey*(publicKey: string): string =
|
|||
except Exception as e:
|
||||
echo "error: `compressCommunityKey` " & $e.name & " msg: " & $e.msg
|
||||
|
||||
proc generateAliasFromPk*(publicKey: string): string =
|
||||
return status_account.generateAlias(publicKey).result.getStr
|
||||
|
||||
proc isAlias*(value: string): bool =
|
||||
return status_account.isAlias(value)
|
||||
|
||||
|
|
|
@ -13,8 +13,6 @@ export response_type
|
|||
logScope:
|
||||
topics = "rpc-accounts"
|
||||
|
||||
const NUMBER_OF_ADDRESSES_TO_GENERATE = 1
|
||||
const MNEMONIC_PHRASE_LENGTH = 12
|
||||
const PK_LENGTH_0X_INCLUDED = 132
|
||||
|
||||
const GENERATED* = "generated"
|
||||
|
@ -132,22 +130,6 @@ proc updateAccount*(name, address, path: string, publicKey, keyUid, accountType,
|
|||
]
|
||||
return core.callPrivateRPC("accounts_saveAccount", payload)
|
||||
|
||||
proc generateAddresses*(paths: seq[string]): RpcResponse[JsonNode] =
|
||||
let payload = %* {
|
||||
"n": NUMBER_OF_ADDRESSES_TO_GENERATE,
|
||||
"mnemonicPhraseLength": MNEMONIC_PHRASE_LENGTH,
|
||||
"bip39Passphrase": "",
|
||||
"paths": paths
|
||||
}
|
||||
|
||||
try:
|
||||
let response = status_go.multiAccountGenerateAndDeriveAddresses($payload)
|
||||
result.result = Json.decode(response, JsonNode)
|
||||
|
||||
except RpcException as e:
|
||||
error "error doing rpc request", methodName = "generateAddresses", exception=e.msg
|
||||
raise newException(RpcException, e.msg)
|
||||
|
||||
proc decompressPk*(publicKey: string): RpcResponse[string] =
|
||||
discard
|
||||
if publicKey.startsWith("0x04") and publicKey.len == PK_LENGTH_0X_INCLUDED:
|
||||
|
@ -221,20 +203,6 @@ proc getRandomMnemonic*(): RpcResponse[JsonNode] =
|
|||
let payload = %* []
|
||||
return core.callPrivateRPC("accounts_getRandomMnemonic", payload)
|
||||
|
||||
proc multiAccountImportMnemonic*(mnemonic: string): RpcResponse[JsonNode] =
|
||||
let payload = %* {
|
||||
"mnemonicPhrase": mnemonic,
|
||||
"Bip39Passphrase": ""
|
||||
}
|
||||
|
||||
try:
|
||||
let response = status_go.multiAccountImportMnemonic($payload)
|
||||
result.result = Json.decode(response, JsonNode)
|
||||
|
||||
except RpcException as e:
|
||||
error "error doing rpc request", methodName = "multiAccountImportMnemonic", exception=e.msg
|
||||
raise newException(RpcException, e.msg)
|
||||
|
||||
## Imports a new mnemonic and creates local keystore file.
|
||||
proc importMnemonic*(mnemonic, password: string):
|
||||
RpcResponse[JsonNode] =
|
||||
|
@ -290,20 +258,6 @@ proc createAccountFromPrivateKey*(privateKey: string): RpcResponse[JsonNode] =
|
|||
error "error doing rpc request", methodName = "createAccountFromPrivateKey", exception=e.msg
|
||||
raise newException(RpcException, e.msg)
|
||||
|
||||
proc deriveAccounts*(accountId: string, paths: seq[string]): RpcResponse[JsonNode] =
|
||||
let payload = %* {
|
||||
"accountID": accountId,
|
||||
"paths": paths
|
||||
}
|
||||
|
||||
try:
|
||||
let response = status_go.multiAccountDeriveAddresses($payload)
|
||||
result.result = Json.decode(response, JsonNode)
|
||||
|
||||
except RpcException as e:
|
||||
error "error doing rpc request", methodName = "deriveAccounts", exception=e.msg
|
||||
raise newException(RpcException, e.msg)
|
||||
|
||||
proc openedAccounts*(path: string): RpcResponse[JsonNode] =
|
||||
try:
|
||||
let response = status_go.openAccounts(path)
|
||||
|
@ -342,16 +296,6 @@ proc restoreAccountAndLogin*(request: RestoreAccountRequest): RpcResponse[JsonNo
|
|||
error "error doing rpc request", methodName = "restoreAccountAndLogin", exception=e.msg
|
||||
raise newException(RpcException, e.msg)
|
||||
|
||||
proc saveAccountAndLoginWithKeycard*(chatKey, password: string, account, subaccounts, settings, config: JsonNode):
|
||||
RpcResponse[JsonNode] =
|
||||
try:
|
||||
let response = status_go.saveAccountAndLoginWithKeycard($account, password, $settings, $config, $subaccounts, chatKey)
|
||||
result.result = Json.decode(response, JsonNode)
|
||||
|
||||
except RpcException as e:
|
||||
error "error doing rpc request", methodName = "saveAccountAndLogin", exception=e.msg
|
||||
raise newException(RpcException, e.msg)
|
||||
|
||||
proc convertRegularProfileKeypairToKeycard*(account: JsonNode, settings: JsonNode, keycardUid: string, password: string, newPassword: string):
|
||||
RpcResponse[JsonNode] =
|
||||
try:
|
||||
|
@ -380,14 +324,6 @@ proc loginAccount*(request: LoginAccountRequest): RpcResponse[JsonNode] =
|
|||
error "loginAccount failed", exception=e.msg
|
||||
raise newException(RpcException, e.msg)
|
||||
|
||||
proc loginWithKeycard*(chatKey, password: string, account, confNode: JsonNode): RpcResponse[JsonNode] =
|
||||
try:
|
||||
let response = status_go.loginWithKeycard($account, password, chatKey, $confNode)
|
||||
result.result = Json.decode(response, JsonNode)
|
||||
except RpcException as e:
|
||||
error "error doing rpc request", methodName = "loginWithKeycard", exception=e.msg
|
||||
raise newException(RpcException, e.msg)
|
||||
|
||||
proc verifyAccountPassword*(address: string, hashedPassword: string, keystoreDir: string):
|
||||
RpcResponse[JsonNode] =
|
||||
try:
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit d38b1147f8b4d0c4abdb1dbf353aff36454e02ed
|
||||
Subproject commit 0fdd7d8def22e64018fe2a47b9c0d98da387c6bc
|
|
@ -1 +1 @@
|
|||
Subproject commit ee2330fe5d4233a7d8b105420c2b93284ad161f3
|
||||
Subproject commit 49eaabaca5100368c5b39fb8c107aad2535371e5
|
Loading…
Reference in New Issue