feat(@desktop/wallet): make a partially operable account fully operable on the first use

This commit makes any partially operable account a fully operable when user
provides a password/pin from whatever reason.

Closes: #11781
This commit is contained in:
Sale Djenic 2023-08-22 11:58:10 +02:00 committed by saledjenic
parent 3113fffef9
commit 00513ed306
6 changed files with 68 additions and 12 deletions

View File

@ -429,6 +429,8 @@ proc init*(self: Controller) =
keycardUid: args.keycardUid,
additinalPathsDetails: args.additinalPathsDetails)
self.authenticateUserFlowRequestedBy = ""
## Whenever user provides a password/pin we need to make all partially operable accounts (if any exists) a fully operable.
self.events.emit(SIGNAL_IMPORT_PARTIALLY_OPERABLE_ACCOUNTS, ImportAccountsArgs(keyUid: data.keyUid, password: data.password))
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED, data)
self.events.on(SIGNAL_SHARED_KEYCARD_MODULE_DISPLAY_POPUP) do(e: Args):

View File

@ -53,6 +53,7 @@ QtObject:
proc handleWalletAccount(self: Service, account: WalletAccountDto, notify: bool = true)
proc handleKeypair(self: Service, keypair: KeypairDto)
proc updateAccountsPositions(self: Service)
proc importPartiallyOperableAccounts(self: Service, keyUid: string, password: string)
# All slots defined in included files have to be forward declared
proc onAllTokensBuilt*(self: Service, response: string) {.slot.}
proc onDerivedAddressesFetched*(self: Service, jsonString: string) {.slot.}

View File

@ -145,6 +145,10 @@ proc init*(self: Service) =
self.events.on(SIGNAL_CURRENCY_UPDATED) do(e:Args):
self.buildAllTokens(self.getWalletAddresses(), store = true)
self.events.on(SIGNAL_IMPORT_PARTIALLY_OPERABLE_ACCOUNTS) do(e: Args):
let args = ImportAccountsArgs(e)
self.importPartiallyOperableAccounts(args.keyUid, args.password)
proc addNewKeypairsAccountsToLocalStoreAndNotify(self: Service, notify: bool = true) =
let chainId = self.networkService.getNetworkForEns().chainId
let allLocalAaccounts = self.getWalletAccounts()
@ -242,19 +246,22 @@ proc updateAccountsPositions(self: Service) =
continue
localAcc.position = dbAcc.position
proc updateAccountInLocalStoreAndNotify(self: Service, address, name, colorId, emoji: string,
proc updateAccountInLocalStoreAndNotify(self: Service, address, name, colorId, emoji: string, operable: string = "",
positionUpdated: Option[bool] = none(bool), notify: bool = true) =
if address.len > 0:
var account = self.getAccountByAddress(address)
if account.isNil:
return
if name.len > 0 or colorId.len > 0 or emoji.len > 0:
if name.len > 0 or colorId.len > 0 or emoji.len > 0 or operable.len > 0:
if name.len > 0 and name != account.name:
account.name = name
if colorId.len > 0 and colorId != account.colorId:
account.colorId = colorId
if emoji.len > 0 and emoji != account.emoji:
account.emoji = emoji
if operable.len > 0 and operable != account.operable and
(operable == AccountNonOperable or operable == AccountPartiallyOperable or operable == AccountFullyOperable):
account.operable = operable
if notify:
self.events.emit(SIGNAL_WALLET_ACCOUNT_UPDATED, AccountArgs(account: account))
else:
@ -304,8 +311,9 @@ proc addWalletAccount*(self: Service, password: string, doPasswordHashing: bool,
proc addNewPrivateKeyKeypair*(self: Service, privateKey, password: string, doPasswordHashing: bool,
keyUid, keypairName, rootWalletMasterKey: string, account: WalletAccountDto): string =
if password.len == 0:
error "for adding new private key account, password must be provided"
return
let err = "for adding new private key account, password must be provided"
error "error", err
return err
var finalPassword = password
if doPasswordHashing:
finalPassword = utils.hashPassword(password)
@ -326,8 +334,9 @@ proc addNewPrivateKeyKeypair*(self: Service, privateKey, password: string, doPas
proc makePrivateKeyKeypairFullyOperable*(self: Service, keyUid, privateKey, password: string, doPasswordHashing: bool): string =
if password.len == 0:
error "for making a private key keypair fully operable, password must be provided"
return
let err = "for making a private key keypair fully operable, password must be provided"
error "error", err
return err
var finalPassword = password
if doPasswordHashing:
finalPassword = utils.hashPassword(password)
@ -345,6 +354,10 @@ proc makePrivateKeyKeypairFullyOperable*(self: Service, keyUid, privateKey, pass
## Mandatory fields for all accounts: `address`, `keyUid`, `walletType`, `path`, `publicKey`, `name`, `emoji`, `colorId`
proc addNewSeedPhraseKeypair*(self: Service, seedPhrase, password: string, doPasswordHashing: bool,
keyUid, keypairName, rootWalletMasterKey: string, accounts: seq[WalletAccountDto]): string =
if password.len == 0:
let err = "for adding a new seed phrase keypair, password must be provided"
error "error", err
return err
var finalPassword = password
if password.len > 0 and doPasswordHashing:
finalPassword = utils.hashPassword(password)
@ -367,8 +380,9 @@ proc addNewSeedPhraseKeypair*(self: Service, seedPhrase, password: string, doPas
proc makeSeedPhraseKeypairFullyOperable*(self: Service, keyUid, mnemonic, password: string, doPasswordHashing: bool): string =
if password.len == 0:
error "for making a private key keypair fully operable, password must be provided"
return
let err = "for making a private key keypair fully operable, password must be provided"
error "error", err
return err
var finalPassword = password
if doPasswordHashing:
finalPassword = utils.hashPassword(password)
@ -383,6 +397,24 @@ proc makeSeedPhraseKeypairFullyOperable*(self: Service, keyUid, mnemonic, passwo
error "error: ", procName="makeSeedPhraseKeypairFullyOperable", errName=e.name, errDesription=e.msg
return e.msg
proc makePartiallyOperableAccoutsFullyOperable(self: Service, password: string, doPasswordHashing: bool) =
if password.len == 0:
error "for making partially operable accounts a fully operable, password must be provided"
return
var finalPassword = password
if doPasswordHashing:
finalPassword = utils.hashPassword(password)
try:
var response = status_go_accounts.makePartiallyOperableAccoutsFullyOperable(finalPassword)
if not response.error.isNil:
error "status-go error", procName="makePartiallyOperableAccoutsFullyOperable", errCode=response.error.code, errDesription=response.error.message
return
let affectedAccounts = map(response.result.getElems(), x => x.getStr())
for acc in affectedAccounts:
self.updateAccountInLocalStoreAndNotify(acc, name = "", colorId = "", emoji = "", operable = AccountFullyOperable)
except Exception as e:
error "error: ", procName="makeSeedPhraseKeypairFullyOperable", errName=e.name, errDesription=e.msg
proc getRandomMnemonic*(self: Service): string =
try:
let response = status_go_accounts.getRandomMnemonic()
@ -497,7 +529,7 @@ proc moveAccountFinally*(self: Service, fromPosition: int, toPosition: int) =
updated = true
except Exception as e:
error "error: ", procName="moveAccountFinally", errName=e.name, errDesription=e.msg
self.updateAccountInLocalStoreAndNotify(address = "", name = "", colorId = "", emoji = "", some(updated))
self.updateAccountInLocalStoreAndNotify(address = "", name = "", colorId = "", emoji = "", operable = "", some(updated))
proc updateKeypairName*(self: Service, keyUid: string, name: string) =
try:
@ -595,7 +627,7 @@ proc handleWalletAccount(self: Service, account: WalletAccountDto, notify: bool
var localAcc = self.getAccountByAddress(account.address)
if not localAcc.isNil:
self.updateAccountInLocalStoreAndNotify(account.address, account.name, account.colorId, account.emoji,
none(bool), notify)
account.operable, none(bool), notify)
else:
self.addNewKeypairsAccountsToLocalStoreAndNotify(notify)
@ -654,4 +686,10 @@ proc areTestNetworksEnabled*(self: Service): bool =
return self.settingsService.areTestNetworksEnabled()
proc hasPairedDevices*(self: Service): bool =
return hasPairedDevices()
return hasPairedDevices()
proc importPartiallyOperableAccounts(self: Service, keyUid: string, password: string) =
## Whenever user provides a password/pin we need to make all partially operable accounts (if any exists) a fully operable.
if keyUid != singletonInstance.userProfile.getKeyUid():
return
self.makePartiallyOperableAccoutsFullyOperable(password, not singletonInstance.userProfile.getIsKeycardUser())

View File

@ -1,3 +1,9 @@
#################################################
# Special signal emitted by main module and handled in wallet account service
#################################################
const SIGNAL_IMPORT_PARTIALLY_OPERABLE_ACCOUNTS* = "importPartiallyOperableAccounts"
#################################################
# Signals emitted by wallet account service
#################################################
@ -35,6 +41,10 @@ const SIGNAL_KEYCARD_NAME_CHANGED* = "keycardNameChanged"
# Payload sent via above defined signals
#################################################
type ImportAccountsArgs* = ref object of Args
keyUid*: string
password*: string
type AccountArgs* = ref object of Args
account*: WalletAccountDto

View File

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

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit b297cf0ae28445c4ec9d3d6ac6f6910d2720304c
Subproject commit e732000d3168888a3fb3b0c1aa1e56bf75c09d27