chore(@desktop/syncing): keycards syncing improvements part 2/2

Handling keycards related syncing improvements done on the status-go side.

Closes: #11268
This commit is contained in:
Sale Djenic 2023-07-07 10:54:23 +02:00 committed by saledjenic
parent d7aa0582be
commit 1561b170e4
34 changed files with 510 additions and 570 deletions

View File

@ -36,7 +36,6 @@ type MessageSignal* = ref object of Signal
verificationRequests*: seq[VerificationRequest]
savedAddresses*: seq[SavedAddressDto]
keypairs*: seq[KeypairDto]
# keycardActions*: seq[KeycardActionDto] //TODO: will be removed in the second part of synchronization improvements
watchOnlyAccounts*: seq[WalletAccountDto]
type MessageDeliveredSignal* = ref object of Signal
@ -148,11 +147,6 @@ proc fromEvent*(T: type MessageSignal, event: JsonNode): MessageSignal =
for jsonKc in e["keypairs"]:
signal.keypairs.add(jsonKc.toKeypairDto())
## TODO: will be removed in the second part of synchronization improvements
# if e.contains("keycardActions"):
# for jsonKc in e["keycardActions"]:
# signal.keycardActions.add(jsonKc.toKeycardActionDto())
if e.contains("watchOnlyAccounts"):
for jsonAcc in e["watchOnlyAccounts"]:
signal.watchOnlyAccounts.add(jsonAcc.toWalletAccountDto())

View File

@ -1,4 +1,4 @@
import NimQml, Tables, sequtils, sugar
import NimQml, Tables, sequtils, strutils, sugar
import ../../../../global/global_singleton
import ../../../../core/eventemitter
@ -83,6 +83,18 @@ proc switchAccount*(self: Module, accountIndex: int) =
method load*(self: Module) =
singletonInstance.engine.setRootContextProperty("browserSectionCurrentAccount", newQVariant(self.view))
self.events.on(SIGNAL_KEYPAIR_SYNCED) do(e: Args):
let args = KeypairArgs(e)
let walletAccount = self.controller.getWalletAccount(self.currentAccountIndex)
if walletAccount.isNil:
self.switchAccount(0)
return
for acc in args.keypair.accounts:
if cmpIgnoreCase(acc.address, walletAccount.address) == 0:
return
self.switchAccount(0)
self.view.connectedAccountDeleted()
self.events.on(SIGNAL_WALLET_ACCOUNT_DELETED) do(e:Args):
if(self.view.isAddressCurrentAccount(AccountArgs(e).account.address)):
self.switchAccount(0)

View File

@ -73,7 +73,7 @@ method load*(self: Module) =
let signingPhrase = self.controller.getSigningPhrase()
let link = self.controller.getNetwork().blockExplorerUrl & "/tx/"
self.view.load(link, signingPhrase)
self.events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e: Args):
self.view.emitChainIdChanged()
self.controller.fixPreferredName(true)
@ -85,15 +85,15 @@ method viewDidLoad*(self: Module) =
# add registered ens usernames
let registeredEnsUsernames = self.controller.getAllMyEnsUsernames(includePendingEnsUsernames = false)
for dto in registeredEnsUsernames:
let item = Item(chainId: dto.chainId,
ensUsername: dto.username,
let item = Item(chainId: dto.chainId,
ensUsername: dto.username,
isPending: false)
self.view.model().addItem(item)
# add pending ens usernames
let pendingEnsUsernames = self.controller.getMyPendingEnsUsernames()
for dto in pendingEnsUsernames:
let item = Item(chainId: dto.chainId,
ensUsername: dto.username,
let item = Item(chainId: dto.chainId,
ensUsername: dto.username,
isPending: true)
self.view.model().addItem(item)
@ -167,11 +167,11 @@ proc setPubKey*(self: Module, password: string) =
var success: bool
if(not responseObj.getProp("success", success)):
info "remote call is not executed with success", methodName="setPubKey"
var respResult: string
if(responseObj.getProp("result", respResult)):
let item = Item(chainId: self.tmpSendEnsTransactionDetails.chainId,
ensUsername: self.tmpSendEnsTransactionDetails.ensUsername,
let item = Item(chainId: self.tmpSendEnsTransactionDetails.chainId,
ensUsername: self.tmpSendEnsTransactionDetails.ensUsername,
isPending: true)
self.view.model().addItem(item)
self.view.emitTransactionWasSentSignal(response)
@ -205,7 +205,7 @@ proc onEnsUsernameRemoved(self: Module, chainId: int, ensUsername: string) =
self.controller.fixPreferredName(true)
self.view.model().removeItemByEnsUsername(chainId, ensUsername)
method removeEnsUsername*(self: Module, chainId: int, ensUsername: string): bool =
method removeEnsUsername*(self: Module, chainId: int, ensUsername: string): bool =
if (not self.controller.removeEnsUsername(chainId, ensUsername)):
info "an error occurred removing ens username", methodName="removeEnsUsername", ensUsername, chainId
return false
@ -313,7 +313,7 @@ method authenticateAndRegisterEns*(self: Module, chainId: int, ensUsername: stri
## if acc.isNil:
## echo "error: selected account to send a transaction from is not known"
## return
## let keyPair = self.controller.getKeycardByKeyUid(acc.keyUid)
## let keyPair = self.controller.getKeycardsWithSameKeyUid(acc.keyUid)
## if keyPair.len == 0:
## self.controller.authenticateUser()
## else:
@ -356,7 +356,7 @@ method getWalletDefaultAddress*(self: Module): string =
method getCurrentCurrency*(self: Module): string =
return self.controller.getCurrentCurrency()
method getFiatValue*(self: Module, cryptoBalance: string, cryptoSymbol: string, fiatSymbol: string): string =
method getFiatValue*(self: Module, cryptoBalance: string, cryptoSymbol: string, fiatSymbol: string): string =
var floatCryptoBalance: float = 0
try:
floatCryptoBalance = parseFloat(cryptoBalance)

View File

@ -44,62 +44,70 @@ proc init*(self: Controller) =
return
self.delegate.onDisplayKeycardSharedModuleFlow()
self.events.on(SIGNAL_KEYPAIR_SYNCED) do(e: Args):
let args = KeypairArgs(e)
self.delegate.onKeypairSynced(args.keypair)
self.events.on(SIGNAL_LOGGEDIN_USER_IMAGE_CHANGED) do(e: Args):
self.delegate.onLoggedInUserImageChanged()
self.events.on(SIGNAL_NEW_KEYCARD_SET) do(e: Args):
let args = KeycardActivityArgs(e)
let args = KeycardArgs(e)
if not args.success:
return
self.delegate.onNewKeycardSet(args.keycard)
self.events.on(SIGNAL_KEYPAIR_CHANGED) do(e: Args):
let args = KeypairArgs(e)
self.delegate.resolveRelatedKeycardsForKeypair(args.keypair)
self.delegate.onKeycardChange(args.keycard)
self.events.on(SIGNAL_KEYCARD_LOCKED) do(e: Args):
let args = KeycardActivityArgs(e)
let args = KeycardArgs(e)
if not args.success:
return
self.delegate.onKeycardLocked(args.keycard.keyUid, args.keycard.keycardUid)
self.events.on(SIGNAL_KEYCARD_UNLOCKED) do(e: Args):
let args = KeycardActivityArgs(e)
let args = KeycardArgs(e)
if not args.success:
return
self.delegate.onKeycardUnlocked(args.keycard.keyUid, args.keycard.keycardUid)
self.events.on(SIGNAL_KEYCARD_NAME_CHANGED) do(e: Args):
let args = KeycardActivityArgs(e)
let args = KeycardArgs(e)
if not args.success:
return
self.delegate.onKeycardNameChanged(args.keycard.keycardUid, args.keycard.keycardName)
self.events.on(SIGNAL_KEYCARD_UID_UPDATED) do(e: Args):
let args = KeycardActivityArgs(e)
let args = KeycardArgs(e)
if not args.success:
return
self.delegate.onKeycardUidUpdated(args.oldKeycardUid, args.keycard.keycardUid)
self.events.on(SIGNAL_KEYCARD_ACCOUNTS_REMOVED) do(e: Args):
let args = KeycardActivityArgs(e)
let args = KeycardArgs(e)
if not args.success:
return
self.delegate.onKeycardAccountsRemoved(args.keycard.keyUid, args.keycard.keycardUid, args.keycard.accountsAddresses)
self.delegate.onKeycardChange(args.keycard)
self.events.on(SIGNAL_WALLET_ACCOUNT_UPDATED) do(e: Args):
let args = AccountArgs(e)
self.delegate.onWalletAccountUpdated(args.account)
self.delegate.onWalletAccountChange(args.account)
## TODO: will be removed in the second part of synchronization improvements
# self.events.on(SIGNAL_WALLET_ACCOUNT_SAVED) do(e: Args):
# self.delegate.rebuildKeycardsList()
self.events.on(SIGNAL_WALLET_ACCOUNT_POSITION_UPDATED) do(e: Args):
let args = AccountArgs(e)
self.delegate.onWalletAccountChange(args.account)
## TODO: will be removed in the second part of synchronization improvements
# self.events.on(SIGNAL_WALLET_ACCOUNT_DELETED) do(e: Args):
# self.delegate.rebuildKeycardsList()
self.events.on(SIGNAL_WALLET_ACCOUNT_SAVED) do(e: Args):
let args = AccountArgs(e)
self.delegate.onWalletAccountChange(args.account)
proc getAllKnownKeycardsGroupedByKeyUid*(self: Controller): seq[KeycardDto] =
return self.walletAccountService.getAllKnownKeycardsGroupedByKeyUid()
self.events.on(SIGNAL_WALLET_ACCOUNT_DELETED) do(e: Args):
let args = AccountArgs(e)
self.delegate.onWalletAccountChange(args.account)
proc getAllKnownKeycards*(self: Controller): seq[KeycardDto] =
return self.walletAccountService.getAllKnownKeycards()
proc getKeycardsWithSameKeyUid*(self: Controller, keyUid: string): seq[KeycardDto] =
return self.walletAccountService.getKeycardsWithSameKeyUid(keyUid)
## TODO: will be removed in the second part of synchronization improvements
# proc getKeypairs*(self: Controller): seq[wallet_account_service.KeypairDto] =
# return self.walletAccountService.getKeypairs()
proc getKeypairs*(self: Controller): seq[wallet_account_service.KeypairDto] =
return self.walletAccountService.getKeypairs()
proc getKeypairByKeyUid*(self: Controller, keyUid: string): wallet_account_service.KeypairDto =
return self.walletAccountService.getKeypairByKeyUid(keyUid)

View File

@ -65,10 +65,13 @@ method runCreateNewPairingCodePopup*(self: AccessInterface, keyUid: string) {.ba
method onLoggedInUserImageChanged*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method resolveRelatedKeycardsForKeypair*(self: AccessInterface, keypair: KeypairDto) {.base.} =
method onKeypairSynced*(self: AccessInterface, keypair: KeypairDto) {.base.} =
raise newException(ValueError, "No implementation available")
method onNewKeycardSet*(self: AccessInterface, keyPair: KeycardDto) {.base.} =
method onKeycardChange*(self: AccessInterface, keycard: KeycardDto) {.base.} =
raise newException(ValueError, "No implementation available")
method onWalletAccountChange*(self: AccessInterface, account: WalletAccountDto) {.base.} =
raise newException(ValueError, "No implementation available")
method onKeycardLocked*(self: AccessInterface, keyUid: string, keycardUid: string) {.base.} =
@ -83,12 +86,6 @@ method onKeycardNameChanged*(self: AccessInterface, keycardUid: string, keycardN
method onKeycardUidUpdated*(self: AccessInterface, keycardUid: string, keycardNewUid: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onKeycardAccountsRemoved*(self: AccessInterface, keyUid: string, keycardUid: string, accountsToRemove: seq[string]) {.base.} =
raise newException(ValueError, "No implementation available")
method onWalletAccountUpdated*(self: AccessInterface, account: WalletAccountDto) {.base.} =
raise newException(ValueError, "No implementation available")
method prepareKeycardDetailsModel*(self: AccessInterface, keyUid: string) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -23,11 +23,6 @@ export io_interface
logScope:
topics = "profile-section-profile-module"
type
BuildItemReason {.pure.} = enum
MainView
DetailsView
type
Module* = ref object of io_interface.AccessInterface
delegate: delegate_interface.AccessInterface
@ -197,32 +192,65 @@ proc findAccountByAccountAddress(accounts: seq[WalletAccountDto], address: strin
return acc
return nil
proc buildKeycardItem(self: Module, keypair: KeypairDto, keycard: KeycardDto, reason: BuildItemReason):
KeycardItem =
proc addAccountsToKeycardItem(self: Module, item: KeycardItem, accounts: seq[WalletAccountDto]) =
if accounts.len == 0:
return
var accType = accounts[0].walletType
if accType == WalletTypeGenerated:
item.setPairType(KeyPairType.Profile.int)
item.setPubKey(singletonInstance.userProfile.getPubKey())
item.setImage(singletonInstance.userProfile.getIcon())
if accType == WalletTypeSeed:
item.setPairType(KeyPairType.SeedImport.int)
item.setIcon("keycard")
if accType == WalletTypeKey:
item.setPairType(KeyPairType.PrivateKeyImport.int)
item.setIcon("keycard")
for acc in accounts:
if acc.isChat:
continue
var icon = ""
if acc.emoji.len == 0:
icon = "wallet"
item.addAccount(newKeyPairAccountItem(acc.name, acc.path, acc.address, acc.publicKey, acc.emoji, acc.colorId,
icon = icon, balance = 0.0))
proc buildMainViewKeycardItem(self: Module, keypair: KeypairDto): KeycardItem =
if keypair.isNil or keypair.keycards.len == 0:
return
var item = initKeycardItem(keycardUid = "",
keyUid = keypair.keyUid,
pubKey = "",
locked = false,
name = keypair.name)
## If all created keycards for certain keypair are locked, then we need to display that item as locked.
item.setLocked(keypair.keycards.all(kp => kp.keycardLocked))
self.addAccountsToKeycardItem(item, keypair.accounts)
return item
proc buildDetailsViewKeycardItem(self: Module, keycard: KeycardDto): KeycardItem =
let isAccountInKnownAccounts = proc(knownAccounts: seq[WalletAccountDto], address: string): bool =
for i in 0 ..< knownAccounts.len:
if cmpIgnoreCase(knownAccounts[i].address, address) == 0:
return true
return false
if keycard.keyUid.len == 0:
return
let keypair = self.controller.getKeypairByKeyUid(keycard.keyUid)
if keypair.isNil:
return
var knownAccounts: seq[WalletAccountDto]
var unknownAccountsAddresses: seq[string]
for accAddr in keycard.accountsAddresses:
let account = findAccountByAccountAddress(keypair.accounts, accAddr)
if account.isNil:
## We are here if the keycard is not sync yet with the app's state. That may happen if there are more copies of the
## We are here if the keycard is not synced yet with the app's state. That may happen if there are more copies of the
## same keycard, then deleting an account for a keypair syncs the inserted keycard, but other copies of the card
## remain with that account till the moment they are synced.
unknownAccountsAddresses.add(accAddr)
continue
if reason == BuildItemReason.MainView and
isAccountInKnownAccounts(knownAccounts, accAddr):
# if there are more then one keycard for a single keypair we don't want to add the same keypair more than once
# that's why caller of this proc should set `upgradeItem` to true, if item with the same `keyUid` was already added
# to a model for the `MainView`
continue
knownAccounts.add(account)
var item = initKeycardItem(keycardUid = keycard.keycardUid,
keyUid = keycard.keyUid,
@ -230,52 +258,29 @@ proc buildKeycardItem(self: Module, keypair: KeypairDto, keycard: KeycardDto, re
locked = keycard.keycardLocked,
name = keycard.keycardName)
if knownAccounts.len == 0:
if reason == BuildItemReason.MainView:
return nil
item.setPairType(KeyPairType.SeedImport.int)
item.setIcon("keycard")
else:
item.setDerivedFrom(keypair.derivedFrom)
for ka in knownAccounts:
var icon = ""
if ka.walletType == WalletTypeDefaultStatusAccount:
item.setPairType(KeyPairType.Profile.int)
item.setPubKey(singletonInstance.userProfile.getPubKey())
item.setImage(singletonInstance.userProfile.getIcon())
icon = "wallet"
if ka.walletType == WalletTypeSeed:
item.setPairType(KeyPairType.SeedImport.int)
item.setIcon("keycard")
if ka.walletType == WalletTypeKey:
item.setPairType(KeyPairType.PrivateKeyImport.int)
item.setIcon("keycard")
item.addAccount(newKeyPairAccountItem(ka.name, ka.path, ka.address, ka.publicKey, ka.emoji, ka.colorId, icon = icon, balance = 0.0))
if reason == BuildItemReason.DetailsView:
var i = 0
for ua in unknownAccountsAddresses:
i.inc
let name = atc.KEYCARD_ACCOUNT_NAME_OF_UNKNOWN_WALLET_ACCOUNT & $i
item.addAccount(newKeyPairAccountItem(name, path = "", ua, pubKey = "", emoji = "", colorId = "", icon = "wallet", balance = 0.0))
return item
# add known accounts
self.addAccountsToKeycardItem(item, knownAccounts)
proc areAllKnownKeycardsLockedForKeypair(self: Module, keyUid: string): bool =
let allKnownKeycards = self.controller.getAllKnownKeycards()
let keyUidRelatedKeycards = allKnownKeycards.filter(kp => kp.keyUid == keyUid)
if keyUidRelatedKeycards.len == 0:
return false
return keyUidRelatedKeycards.all(kp => kp.keycardLocked)
# add unknown accounts
var i = 0
for ua in unknownAccountsAddresses:
i.inc
let name = atc.KEYCARD_ACCOUNT_NAME_OF_UNKNOWN_WALLET_ACCOUNT & $i
item.addAccount(newKeyPairAccountItem(name, path = "", ua, pubKey = "", emoji = "", colorId = "undefined", icon = "wallet", balance = 0.0))
return item
proc buildKeycardList(self: Module) =
var items: seq[KeycardItem]
let migratedKeyPairs = self.controller.getAllKnownKeycardsGroupedByKeyUid()
for kp in migratedKeyPairs:
let keypair = self.controller.getKeypairByKeyUid(kp.keyUid)
let item = self.buildKeycardItem(keypair, kp, BuildItemReason.MainView)
let keypairs = self.controller.getKeypairs()
for kp in keypairs:
let item = self.buildMainViewKeycardItem(kp)
if item.isNil:
continue
## If all created keycards for certain keypair are locked, then we need to display that item as locked.
item.setLocked(self.areAllKnownKeycardsLockedForKeypair(item.getKeyUid()))
items.add(item)
if items.len > 0:
self.view.setKeycardItems(items)
@ -286,46 +291,32 @@ method onLoggedInUserImageChanged*(self: Module) =
return
self.view.keycardDetailsModel().setImage(singletonInstance.userProfile.getPubKey(), singletonInstance.userProfile.getIcon())
method resolveRelatedKeycardsForKeypair*(self: Module, keypair: KeypairDto) =
method resolveRelatedKeycardsForKeypair(self: Module, keypair: KeypairDto) =
if keypair.keyUid.len == 0:
error "cannot rebuild keycards for a keypair with empty keyUid"
return
var
mainViewItem: KeycardItem
detailsViewItems: seq[KeycardItem]
let
appHasDisplayedKeycards = not self.view.keycardModel().getItemForKeyUid(keypair.keyUid).isNil
thereAreDisplayedKeycardsForKeypair = not self.view.keycardModel().getItemForKeyUid(keypair.keyUid).isNil
detailsViewCurrentlyDisplayed = not self.view.keycardDetailsModel().isNil
# create main view item
let mainViewItem = self.buildMainViewKeycardItem(keypair)
# prepare main view item and if needed details view item
var detailsViewItems: seq[KeycardItem]
for kc in keypair.keycards:
# create main view item
if mainViewItem.isNil:
mainViewItem = self.buildKeycardItem(keypair, kc, BuildItemReason.MainView)
else:
for accAddr in kc.accountsAddresses:
if mainViewItem.containsAccountAddress(accAddr):
continue
let account = findAccountByAccountAddress(keypair.accounts, accAddr)
if account.isNil:
## we should never be here cause all accounts are firstly added to wallet
continue
mainViewItem.addAccount(newKeyPairAccountItem(account.name, account.path, account.address, account.publicKey,
account.emoji, account.colorId, icon = "", balance = 0.0))
let item = self.buildDetailsViewKeycardItem(kc)
if not item.isNil:
detailsViewItems.add(item)
# create details view item if model is not nil (means the details view is currently active)
if detailsViewCurrentlyDisplayed:
let item = self.buildKeycardItem(keypair, kc, BuildItemReason.DetailsView)
if not item.isNil:
detailsViewItems.add(item)
if appHasDisplayedKeycards:
if thereAreDisplayedKeycardsForKeypair:
if keypair.keycards.len == 0:
# remove all related keycards from the app
self.view.keycardModel().removeItemWithKeyUid(keypair.keyUid)
self.view.keycardModel().removeItemsWithKeyUid(keypair.keyUid)
if not detailsViewCurrentlyDisplayed:
return
self.view.keycardDetailsModel().removeItemWithKeyUid(keypair.keyUid)
self.view.keycardDetailsModel().removeItemsWithKeyUid(keypair.keyUid)
return
if keypair.keycards.len > 0:
# replace displayed keycards
@ -343,100 +334,65 @@ method resolveRelatedKeycardsForKeypair*(self: Module, keypair: KeypairDto) =
return
self.view.keycardDetailsModel().setItems(detailsViewItems)
method onNewKeycardSet*(self: Module, keyPair: KeycardDto) =
## TODO: will be removed in the second part of synchronization improvements
discard
# let keypairs = self.controller.getKeypairs()
# var mainViewItem = self.view.keycardModel().getItemForKeyUid(keyPair.keyUid)
# if mainViewItem.isNil:
# mainViewItem = self.buildKeycardItem(keypairs, keyPair, BuildItemReason.MainView)
# if not mainViewItem.isNil:
# self.view.keycardModel().addItem(mainViewItem)
# else:
# for accAddr in keyPair.accountsAddresses:
# if mainViewItem.containsAccountAddress(accAddr):
# continue
# let account = findAccountByAccountAddress(keypairs, accAddr)
# if account.isNil:
# ## we should never be here cause all keypairs are firstly added to wallet
# continue
# mainViewItem.addAccount(newKeyPairAccountItem(account.name, account.path, account.address, account.publicKey,
# account.emoji, account.colorId, icon = "", balance = 0.0))
# if self.view.keycardDetailsModel().isNil:
# return
# var detailsViewItem = self.view.keycardDetailsModel().getItemForKeycardUid(keyPair.keycardUid)
# if detailsViewItem.isNil:
# detailsViewItem = self.buildKeycardItem(keypairs, keyPair, BuildItemReason.DetailsView)
# if not detailsViewItem.isNil:
# self.view.keycardDetailsModel().addItem(detailsViewItem)
# else:
# for accAddr in keyPair.accountsAddresses:
# if detailsViewItem.containsAccountAddress(accAddr):
# continue
# let account = findAccountByAccountAddress(keypairs, accAddr)
# if account.isNil:
# ## we should never be here cause all keypairs are firstly added to wallet
# continue
# detailsViewItem.addAccount(newKeyPairAccountItem(account.name, account.path, account.address, account.publicKey,
# account.emoji, account.colorId, icon = "", balance = 0.0))
method onKeypairSynced*(self: Module, keypair: KeypairDto) =
self.resolveRelatedKeycardsForKeypair(keypair)
method onKeycardChange*(self: Module, keycard: KeycardDto) =
assert keycard.keyUid.len > 0, "cannot proceed with keycard with an empty keyUid"
let keypair = self.controller.getKeypairByKeyUid(keycard.keyUid)
if keypair.isNil:
return
self.resolveRelatedKeycardsForKeypair(keypair)
method onWalletAccountChange*(self: Module, account: WalletAccountDto) =
if account.isNil or account.keyUid.len == 0:
return
let keypair = self.controller.getKeypairByKeyUid(account.keyUid)
if not keypair.isNil:
self.resolveRelatedKeycardsForKeypair(keypair)
return
# we should be here if the last account for a keypair was deleted
if self.view.keycardModel().getItemForKeyUid(account.keyUid).isNil:
return
self.view.keycardModel().removeItemsWithKeyUid(account.keyUid)
if self.view.keycardDetailsModel().isNil:
return
self.view.keycardDetailsModel().removeItemsWithKeyUid(account.keyUid)
method onKeycardLocked*(self: Module, keyUid: string, keycardUid: string) =
## TODO: will be removed in the second part of synchronization improvements
discard
# self.view.keycardModel().setLockedForKeycardsWithKeyUid(keyUid, true)
# if self.view.keycardDetailsModel().isNil:
# return
# self.view.keycardDetailsModel().setLockedForKeycardWithKeycardUid(keycardUid, true)
assert keyUid.len > 0, "cannot proceed with keycard with an empty keyUid"
assert keycardUid.len > 0, "cannot proceed with keycard with an empty keycardUid"
let keypair = self.controller.getKeypairByKeyUid(keyUid)
if keypair.isNil:
return
if keypair.keycards.all(kp => kp.keycardLocked):
self.view.keycardModel().setLockedForKeycardsWithKeyUid(keyUid, true)
if self.view.keycardDetailsModel().isNil:
return
self.view.keycardDetailsModel().setLockedForKeycardWithKeycardUid(keycardUid, true)
method onKeycardUnlocked*(self: Module, keyUid: string, keycardUid: string) =
## TODO: will be removed in the second part of synchronization improvements
discard
# self.view.keycardModel().setLockedForKeycardsWithKeyUid(keyUid, false)
# if self.view.keycardDetailsModel().isNil:
# return
# self.view.keycardDetailsModel().setLockedForKeycardWithKeycardUid(keycardUid, false)
self.view.keycardModel().setLockedForKeycardsWithKeyUid(keyUid, false)
if self.view.keycardDetailsModel().isNil:
return
self.view.keycardDetailsModel().setLockedForKeycardWithKeycardUid(keycardUid, false)
method onKeycardNameChanged*(self: Module, keycardUid: string, keycardNewName: string) =
## TODO: will be removed in the second part of synchronization improvements
discard
# self.view.keycardModel().setNameForKeycardWithKeycardUid(keycardUid, keycardNewName)
# if self.view.keycardDetailsModel().isNil:
# return
# self.view.keycardDetailsModel().setNameForKeycardWithKeycardUid(keycardUid, keycardNewName)
# keycard on the main view should always follow corresponding keypair
if self.view.keycardDetailsModel().isNil:
return
self.view.keycardDetailsModel().setNameForKeycardWithKeycardUid(keycardUid, keycardNewName)
method onKeycardUidUpdated*(self: Module, keycardUid: string, keycardNewUid: string) =
## TODO: will be removed in the second part of synchronization improvements
discard
# if self.view.keycardDetailsModel().isNil:
# return
# self.view.keycardDetailsModel().setKeycardUid(keycardUid, keycardNewUid)
method onKeycardAccountsRemoved*(self: Module, keyUid: string, keycardUid: string, accountsToRemove: seq[string]) =
## TODO: will be removed in the second part of synchronization improvements
discard
# self.view.keycardModel().removeAccountsFromKeycardsWithKeyUid(keyUid, accountsToRemove, removeKeycardItemIfHasNoAccounts = true)
# if self.view.keycardDetailsModel().isNil:
# return
# self.view.keycardDetailsModel().removeAccountsFromKeycardWithKeycardUid(keycardUid, accountsToRemove, removeKeycardItemIfHasNoAccounts = true)
method onWalletAccountUpdated*(self: Module, account: WalletAccountDto) =
## TODO: will be removed in the second part of synchronization improvements
discard
# self.view.keycardModel().updateDetailsForAddressForKeyPairsWithKeyUid(account.keyUid, account.address, account.name,
# account.colorId, account.emoji)
# if self.view.keycardDetailsModel().isNil:
# return
# self.view.keycardDetailsModel().updateDetailsForAddressForKeyPairsWithKeyUid(account.keyUid, account.address, account.name,
# account.colorId, account.emoji)
if self.view.keycardDetailsModel().isNil:
return
self.view.keycardDetailsModel().setKeycardUid(keycardUid, keycardNewUid)
method prepareKeycardDetailsModel*(self: Module, keyUid: string) =
let keypair = self.controller.getKeypairByKeyUid(keyUid)
var items: seq[KeycardItem]
let allKnownKeycards = self.controller.getAllKnownKeycards()
for kp in allKnownKeycards:
if kp.keyUid != keyUid:
continue
let item = self.buildKeycardItem(keypair, kp, BuildItemReason.DetailsView)
let keycards = self.controller.getKeycardsWithSameKeyUid(keyUid)
for kc in keycards:
let item = self.buildDetailsViewKeycardItem(kc)
if item.isNil:
continue
items.add(item)

View File

@ -34,8 +34,8 @@ proc updateAccountPosition*(self: Controller, address: string, position: int) =
proc deleteAccount*(self: Controller, address: string) =
self.walletAccountService.deleteAccount(address)
proc getKeycardByKeyUid*(self: Controller, keyUid: string): seq[KeycardDto] =
return self.walletAccountService.getKeycardByKeyUid(keyUid)
proc getKeycardsWithSameKeyUid*(self: Controller, keyUid: string): seq[KeycardDto] =
return self.walletAccountService.getKeycardsWithSameKeyUid(keyUid)
proc isKeycardAccount*(self: Controller, account: WalletAccountDto): bool =
return self.walletAccountService.isKeycardAccount(account)
@ -46,9 +46,6 @@ proc getWalletAccount*(self: Controller, address: string): WalletAccountDto =
proc getKeypairs*(self: Controller): seq[KeypairDto] =
return self.walletAccountService.getKeypairs()
proc getAllKnownKeycardsGroupedByKeyUid*(self: Controller): seq[KeycardDto] =
return self.walletAccountService.getAllKnownKeycardsGroupedByKeyUid()
proc toggleIncludeWatchOnlyAccount*(self: Controller) =
self.walletAccountService.toggleIncludeWatchOnlyAccount()

View File

@ -65,7 +65,7 @@ QtObject:
self.endResetModel()
self.countChanged()
proc onUpdatedAccount*(self: Model, account: Item) =
proc onUpdatedAccount*(self: Model, account: Item) =
var i = 0
for item in self.items.mitems:
if account.address == item.address:

View File

@ -60,8 +60,8 @@ method convertWalletAccountDtoToKeyPairAccountItem(self: Module, account: Wallet
balanceFetched = false)
method createKeypairItems*(self: Module, walletAccounts: seq[WalletAccountDto]): seq[KeyPairItem] =
var keyPairItems = keypairs.buildKeyPairsList(self.controller.getKeypairs(), self.controller.getAllKnownKeycardsGroupedByKeyUid(),
excludeAlreadyMigratedPairs = false, excludePrivateKeyKeypairs = false)
var keyPairItems = keypairs.buildKeyPairsList(self.controller.getKeypairs(), excludeAlreadyMigratedPairs = false,
excludePrivateKeyKeypairs = false)
var item = newKeyPairItem()
item.setIcon("show")
@ -82,6 +82,9 @@ method refreshWalletAccounts*(self: Module) =
self.view.setItems(items)
method load*(self: Module) =
self.events.on(SIGNAL_KEYPAIR_SYNCED) do(e: Args):
self.refreshWalletAccounts()
self.events.on(SIGNAL_WALLET_ACCOUNT_SAVED) do(e:Args):
self.refreshWalletAccounts()
@ -94,7 +97,7 @@ method load*(self: Module) =
self.view.onUpdatedAccount(walletAccountToWalletSettingsAccountsItem(args.account, keycardAccount))
self.events.on(SIGNAL_NEW_KEYCARD_SET) do(e: Args):
let args = KeycardActivityArgs(e)
let args = KeycardArgs(e)
if not args.success:
return
self.refreshWalletAccounts()

View File

@ -96,7 +96,7 @@ method authenticateAndBuy*(self: Module, packId: string, address: string, gas: s
## if acc.isNil:
## echo "error: selected account to send a transaction from is not known"
## return
## let keyPair = self.controller.getKeycardByKeyUid(acc.keyUid)
## let keyPair = self.controller.getKeycardsWithSameKeyUid(acc.keyUid)
## if keyPair.len == 0:
## self.controller.authenticateUser()
## else:

View File

@ -50,8 +50,8 @@ proc getCurrentCurrency*(self: Controller): string =
proc getCurrencyFormat*(self: Controller, symbol: string): CurrencyFormatDto =
return self.currencyService.getCurrencyFormat(symbol)
proc getKeycardByKeyUid*(self: Controller, keyUid: string): seq[KeycardDto] =
return self.walletAccountService.getKeycardByKeyUid(keyUid)
proc getKeycardsWithSameKeyUid*(self: Controller, keyUid: string): seq[KeycardDto] =
return self.walletAccountService.getKeycardsWithSameKeyUid(keyUid)
proc getWalletAccount*(self: Controller, address: string): WalletAccountDto =
return self.walletAccountService.getAccountByAddress(address)

View File

@ -168,6 +168,13 @@ method setFillterAllAddresses*(self: Module) =
method load*(self: Module) =
singletonInstance.engine.setRootContextProperty("walletSection", newQVariant(self.view))
self.events.on(SIGNAL_KEYPAIR_SYNCED) do(e: Args):
let args = KeypairArgs(e)
self.setTotalCurrencyBalance()
for acc in args.keypair.accounts:
if acc.removed:
self.filter.removeAddress(acc.address)
self.notifyFilterChanged()
self.events.on(SIGNAL_WALLET_ACCOUNT_UPDATED) do(e:Args):
self.notifyFilterChanged()
self.events.on(SIGNAL_WALLET_ACCOUNT_SAVED) do(e:Args):
@ -192,7 +199,7 @@ method load*(self: Module) =
self.setTotalCurrencyBalance()
self.notifyFilterChanged()
self.events.on(SIGNAL_NEW_KEYCARD_SET) do(e: Args):
let args = KeycardActivityArgs(e)
let args = KeycardArgs(e)
if not args.success:
return
self.notifyFilterChanged()

View File

@ -58,10 +58,10 @@ proc init*(self: Controller) =
proc getWalletAccounts*(self: Controller): seq[wallet_account_service.WalletAccountDto] =
return self.walletAccountService.getWalletAccounts()
proc getChainIds*(self: Controller): seq[int] =
proc getChainIds*(self: Controller): seq[int] =
return self.networkService.getNetworks().map(n => n.chainId)
proc getEnabledChainIds*(self: Controller): seq[int] =
proc getEnabledChainIds*(self: Controller): seq[int] =
return self.networkService.getNetworks().filter(n => n.enabled).map(n => n.chainId)
proc getCurrentCurrency*(self: Controller): string =
@ -70,8 +70,8 @@ proc getCurrentCurrency*(self: Controller): string =
proc getCurrencyFormat*(self: Controller, symbol: string): CurrencyFormatDto =
return self.currencyService.getCurrencyFormat(symbol)
proc getKeycardByKeyUid*(self: Controller, keyUid: string): seq[KeycardDto] =
return self.walletAccountService.getKeycardByKeyUid(keyUid)
proc getKeycardsWithSameKeyUid*(self: Controller, keyUid: string): seq[KeycardDto] =
return self.walletAccountService.getKeycardsWithSameKeyUid(keyUid)
proc getAccountByAddress*(self: Controller, address: string): WalletAccountDto =
return self.walletAccountService.getAccountByAddress(address)
@ -87,7 +87,7 @@ proc authenticateUser*(self: Controller, keyUid = "") =
keyUid: keyUid)
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_AUTHENTICATE_USER, data)
proc getEstimatedTime*(self: Controller, chainId: int, maxFeePerGas: string): EstimatedTime =
proc getEstimatedTime*(self: Controller, chainId: int, maxFeePerGas: string): EstimatedTime =
return self.transactionService.getEstimatedTime(chainId, maxFeePerGas)
proc suggestedRoutes*(self: Controller, account: string, amount: Uint256, token: string, disabledFromChainIDs, disabledToChainIDs, preferredChainIDs: seq[uint64], sendType: int, lockedInAmounts: string): string =
@ -98,6 +98,6 @@ proc transfer*(self: Controller, from_addr: string, to_addr: string, tokenSymbol
value: string, uuid: string, selectedRoutes: string, password: string) =
self.transactionService.transfer(from_addr, to_addr, tokenSymbol, value, uuid, selectedRoutes, password)
proc suggestedFees*(self: Controller, chainId: int): string =
proc suggestedFees*(self: Controller, chainId: int): string =
let suggestedFees = self.transactionService.suggestedFees(chainId)
return suggestedFees.toJson()

View File

@ -85,6 +85,9 @@ method load*(self: Module) =
singletonInstance.engine.setRootContextProperty("walletSectionSend", newQVariant(self.view))
# these connections should be part of the controller's init method
self.events.on(SIGNAL_KEYPAIR_SYNCED) do(e: Args):
self.refreshWalletAccounts()
self.events.on(SIGNAL_WALLET_ACCOUNT_SAVED) do(e:Args):
self.refreshWalletAccounts()
@ -104,7 +107,7 @@ method load*(self: Module) =
self.refreshWalletAccounts()
self.events.on(SIGNAL_NEW_KEYCARD_SET) do(e: Args):
let args = KeycardActivityArgs(e)
let args = KeycardArgs(e)
if not args.success:
return
self.refreshWalletAccounts()
@ -152,7 +155,7 @@ method authenticateAndTransfer*(
## if acc.isNil:
## echo "error: selected account to send a transaction from is not known"
## return
## let keyPair = self.controller.getKeycardByKeyUid(acc.keyUid)
## let keyPair = self.controller.getKeycardsWithSameKeyUid(acc.keyUid)
## if keyPair.len == 0:
## self.controller.authenticateUser()
## else:

View File

@ -10,14 +10,8 @@ export keypair_item
logScope:
topics = "shared-keypairs"
proc buildKeyPairsList*(keypairs: seq[KeypairDto], allMigratedKeypairs: seq[KeycardDto],
excludeAlreadyMigratedPairs: bool, excludePrivateKeyKeypairs: bool): seq[KeyPairItem] =
let keyPairMigrated = proc(keyUid: string): bool =
result = false
for kp in allMigratedKeypairs:
if kp.keyUid == keyUid:
return true
proc buildKeyPairsList*(keypairs: seq[KeypairDto], excludeAlreadyMigratedPairs: bool,
excludePrivateKeyKeypairs: bool): seq[KeyPairItem] =
var items: seq[KeyPairItem]
for kp in keypairs:
if kp.accounts.len == 0:
@ -25,7 +19,7 @@ proc buildKeyPairsList*(keypairs: seq[KeypairDto], allMigratedKeypairs: seq[Keyc
error "there must not be any keypair without accounts", keyUid=kp.keyUid
return
let publicKey = kp.accounts[0].publicKey # in case of other but the profile keypair we take public key of first account as keypair's public key
let kpMigrated = keyPairMigrated(kp.keyUid)
let kpMigrated = kp.keycards.len > 0
if excludeAlreadyMigratedPairs and kpMigrated:
continue
if kp.keypairType == KeypairTypeProfile:
@ -54,7 +48,7 @@ proc buildKeyPairsList*(keypairs: seq[KeypairDto], allMigratedKeypairs: seq[Keyc
locked = false,
name = kp.name,
image = "",
icon = if keyPairMigrated(kp.keyUid): "keycard" else: "key_pair_seed_phrase",
icon = if kpMigrated: "keycard" else: "key_pair_seed_phrase",
pairType = KeyPairType.SeedImport,
derivedFrom = kp.derivedFrom,
lastUsedDerivationIndex = kp.lastUsedDerivationIndex,
@ -74,7 +68,7 @@ proc buildKeyPairsList*(keypairs: seq[KeypairDto], allMigratedKeypairs: seq[Keyc
locked = false,
name = kp.name,
image = "",
icon = if keyPairMigrated(kp.keyUid): "keycard" else: "objects",
icon = if kpMigrated: "keycard" else: "objects",
pairType = KeyPairType.PrivateKeyImport,
derivedFrom = kp.derivedFrom,
lastUsedDerivationIndex = kp.lastUsedDerivationIndex,

View File

@ -14,7 +14,7 @@ type
QtObject:
type KeyPairItem* = ref object of QObject
keyUid: string
pubKey: string
pubKey: string
locked: bool
name: string
image: string

View File

@ -123,9 +123,6 @@ proc getKeypairs*(self: Controller): seq[KeypairDto] =
proc getKeypairByKeyUid*(self: Controller, keyUid: string): KeypairDto =
return self.walletAccountService.getKeypairByKeyUid(keyUid)
proc getAllKnownKeycardsGroupedByKeyUid*(self: Controller): seq[KeycardDto] =
return self.walletAccountService.getAllKnownKeycardsGroupedByKeyUid()
proc finalizeAction*(self: Controller) =
self.delegate.finalizeAction()
@ -147,7 +144,7 @@ proc fetchDetailsForAddresses*(self: Controller, addresses: seq[string]) =
self.uniqueFetchingDetailsId = $now().toTime().toUnix()
self.walletAccountService.fetchDetailsForAddresses(self.uniqueFetchingDetailsId, addresses)
proc addWalletAccount*(self: Controller, createKeystoreFile, doPasswordHashing: bool, name, address, path, publicKey,
proc addWalletAccount*(self: Controller, createKeystoreFile, doPasswordHashing: bool, name, address, path, publicKey,
keyUid, accountType, colorId, emoji: string): bool =
var password: string
if createKeystoreFile:
@ -155,33 +152,33 @@ proc addWalletAccount*(self: Controller, createKeystoreFile, doPasswordHashing:
if password.len == 0:
info "cannot create keystore file if provided password is empty", name=name, address=address
return false
let err = self.walletAccountService.addWalletAccount(password, doPasswordHashing, name, address, path, publicKey,
let err = self.walletAccountService.addWalletAccount(password, doPasswordHashing, name, address, path, publicKey,
keyUid, accountType, colorId, emoji)
if err.len > 0:
info "adding wallet account failed", name=name, address=address
return false
return true
proc addNewPrivateKeyKeypair*(self: Controller, privateKey: string, doPasswordHashing: bool, keyUid, keypairName,
proc addNewPrivateKeyKeypair*(self: Controller, privateKey: string, doPasswordHashing: bool, keyUid, keypairName,
rootWalletMasterKey: string, account: WalletAccountDto): bool =
let password = self.getPassword() # password must not be empty in this context
if password.len == 0:
info "cannot create keystore file if provided password is empty", keypairName=keypairName, keyUid=keyUid
return false
let err = self.walletAccountService.addNewPrivateKeyKeypair(privateKey, password, doPasswordHashing, keyUid,
let err = self.walletAccountService.addNewPrivateKeyKeypair(privateKey, password, doPasswordHashing, keyUid,
keyPairName, rootWalletMasterKey, account)
if err.len > 0:
info "adding new keypair from private key failed", keypairName=keypairName, keyUid=keyUid
return false
return true
proc addNewSeedPhraseKeypair*(self: Controller, seedPhrase: string, doPasswordHashing: bool, keyUid, keypairName,
proc addNewSeedPhraseKeypair*(self: Controller, seedPhrase: string, doPasswordHashing: bool, keyUid, keypairName,
rootWalletMasterKey: string, accounts: seq[WalletAccountDto]): bool =
let password = self.getPassword() # password must not be empty in this context
if password.len == 0:
info "cannot create keystore file if provided password is empty", keypairName=keypairName, keyUid=keyUid
return false
let err = self.walletAccountService.addNewSeedPhraseKeypair(seedPhrase, password, doPasswordHashing, keyUid,
let err = self.walletAccountService.addNewSeedPhraseKeypair(seedPhrase, password, doPasswordHashing, keyUid,
keypairName, rootWalletMasterKey, accounts)
if err.len > 0:
info "adding new keypair from seed phrase failed", keypairName=keypairName, keyUid=keyUid
@ -221,14 +218,14 @@ proc disconnectKeycardReponseSignal(self: Controller) =
proc connectKeycardReponseSignal(self: Controller) =
self.connectionKeycardResponse = self.events.onWithUUID(SIGNAL_KEYCARD_RESPONSE) do(e: Args):
let args = KeycardArgs(e)
let args = KeycardLibArgs(e)
self.disconnectKeycardReponseSignal()
self.delegate.onDerivedAddressesFromKeycardFetched(args.flowType, args.flowEvent, self.tmpPaths)
proc cancelCurrentFlow*(self: Controller) =
self.keycardService.cancelCurrentFlow()
# in most cases we're running another flow after canceling the current one,
# this way we're giving to the keycard some time to cancel the current flow
# in most cases we're running another flow after canceling the current one,
# this way we're giving to the keycard some time to cancel the current flow
sleep(200)
proc fetchAddressesFromKeycard*(self: Controller, bip44Paths: seq[string]) =

View File

@ -65,11 +65,11 @@ proc newModule*[T](delegate: T,
result.events = events
result.walletAccountService = walletAccountService
result.view = newView(result)
result.viewVariant = newQVariant(result.view)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events, accountsService, walletAccountService, keycardService)
result.authenticationReason = AuthenticationReason.AddingAccount
result.fetchingAddressesIsInProgress = false
method delete*[T](self: Module[T]) =
self.view.delete
self.viewVariant.delete
@ -80,8 +80,8 @@ method loadForAddingAccount*[T](self: Module[T], addingWatchOnlyAccount: bool) =
self.view.setEditMode(false)
self.view.setCurrentState(newMainState(nil))
var items = keypairs.buildKeyPairsList(self.controller.getKeypairs(), self.controller.getAllKnownKeycardsGroupedByKeyUid(),
excludeAlreadyMigratedPairs = false, excludePrivateKeyKeypairs = true)
var items = keypairs.buildKeyPairsList(self.controller.getKeypairs(), excludeAlreadyMigratedPairs = false,
excludePrivateKeyKeypairs = true)
if items.len == 0:
error "list of identified keypairs is empty, but it must have at least a profile keypair"
return
@ -112,10 +112,10 @@ method loadForEditingAccount*[T](self: Module[T], address: string) =
self.view.setCurrentState(newMainState(nil))
let accountDto = self.controller.getWalletAccount(address)
var addressDetailsItem = newDerivedAddressItem(order = 0,
address = accountDto.address,
var addressDetailsItem = newDerivedAddressItem(order = 0,
address = accountDto.address,
publicKey = accountDto.publicKey,
path = accountDto.path,
path = accountDto.path,
alreadyCreated = true,
hasActivity = false,
loaded = true)
@ -124,7 +124,7 @@ method loadForEditingAccount*[T](self: Module[T], address: string) =
self.view.setStoredAccountName(accountDto.name)
self.view.setStoredSelectedColorId(accountDto.colorId)
self.view.setStoredSelectedEmoji(accountDto.emoji)
self.view.setAccountName(accountDto.name)
self.view.setAccountName(accountDto.name)
self.view.setSelectedColorId(accountDto.colorId)
self.view.setSelectedEmoji(accountDto.emoji)
@ -135,8 +135,8 @@ method loadForEditingAccount*[T](self: Module[T], address: string) =
self.view.setSelectedOrigin(item)
self.view.setWatchOnlyAccAddress(addressDetailsItem)
else:
var items = keypairs.buildKeyPairsList(self.controller.getKeypairs(), self.controller.getAllKnownKeycardsGroupedByKeyUid(),
excludeAlreadyMigratedPairs = false, excludePrivateKeyKeypairs = false)
var items = keypairs.buildKeyPairsList(self.controller.getKeypairs(), excludeAlreadyMigratedPairs = false,
excludePrivateKeyKeypairs = false)
if items.len == 0:
error "list of identified keypairs is empty, but it must have at least a profile keypair"
return
@ -146,7 +146,7 @@ method loadForEditingAccount*[T](self: Module[T], address: string) =
if item.containsAccountAddress(address):
selectedOrigin = item
break
if selectedOrigin.isNil or selectedOrigin.getKeyUid().len == 0:
error "selected address for editing is not known among identified keypairs", address=address
return
@ -161,13 +161,13 @@ method loadForEditingAccount*[T](self: Module[T], address: string) =
self.view.setDerivationPath(accountDto.path)
self.view.setSelectedOrigin(selectedOrigin)
self.delegate.onAddAccountModuleLoaded()
self.delegate.onAddAccountModuleLoaded()
proc tryKeycardSync[T](self: Module[T]) =
proc tryKeycardSync[T](self: Module[T]) =
if self.controller.getPin().len == 0:
return
let dataForKeycardToSync = SharedKeycarModuleArgs(
pin: self.controller.getPin(),
pin: self.controller.getPin(),
keyUid: self.controller.getAuthenticatedKeyUid()
)
self.events.emit(SIGNAL_SHARED_KEYCARD_MODULE_TRY_KEYCARD_SYNC, dataForKeycardToSync)
@ -203,7 +203,7 @@ method onCancelActionClicked*[T](self: Module[T]) =
return
debug "waa_cancel_action", currState=currStateObj.stateType()
currStateObj.executeCancelCommand(self.controller)
method onPrimaryActionClicked*[T](self: Module[T]) =
let currStateObj = self.view.currentStateObj()
if currStateObj.isNil:
@ -365,7 +365,7 @@ proc resolveSuggestedPathForSelectedOrigin[T](self: Module[T]): tuple[suggestedP
return (suggestedPath, nextIndex)
nextIndex = selectedOrigin.getLastUsedDerivationIndex() + 1
for i in nextIndex ..< self.getNumOfAddressesToGenerate():
let suggestedPath = account_constants.PATH_WALLET_ROOT & "/" & $i
let suggestedPath = account_constants.PATH_WALLET_ROOT & "/" & $i
if keypair.accounts.filter(x => x.path == suggestedPath).len == 0:
return (suggestedPath, i)
error "we couldn't find available path for new account"
@ -449,7 +449,7 @@ method validSeedPhrase*[T](self: Module[T], seedPhrase: string): bool =
proc setDerivedAddresses[T](self: Module[T], derivedAddresses: seq[DerivedAddressDto]) =
defer: self.fetchingAddressesIsInProgress = false
var items: seq[DerivedAddressItem]
let derivationPath = self.view.getDerivationPath()
if derivationPath.endsWith("/"):
@ -468,7 +468,7 @@ proc setDerivedAddresses[T](self: Module[T], derivedAddresses: seq[DerivedAddres
self.view.derivedAddressModel().setItems(items)
if items.len == 0:
info "couldn't resolve an address for the set path"
return
return
self.changeSelectedDerivedAddress(items[0].getAddress())
method onDerivedAddressesFetched*[T](self: Module[T], derivedAddresses: seq[DerivedAddressDto], error: string) =
@ -543,13 +543,13 @@ method onAddressDetailsFetched*[T](self: Module[T], derivedAddresses: seq[Derive
if currStateObj.isNil:
error "waa_cannot resolve current state"
return
# we always receive responses one by one
if derivedAddresses.len == 1:
var addressDetailsItem = newDerivedAddressItem(order = 0,
address = derivedAddresses[0].address,
publicKey = derivedAddresses[0].publicKey,
path = derivedAddresses[0].path,
var addressDetailsItem = newDerivedAddressItem(order = 0,
address = derivedAddresses[0].address,
publicKey = derivedAddresses[0].publicKey,
path = derivedAddresses[0].path,
alreadyCreated = derivedAddresses[0].alreadyCreated,
hasActivity = derivedAddresses[0].hasActivity,
loaded = true)
@ -585,7 +585,7 @@ method authenticateForEditingDerivationPath*[T](self: Module[T]) =
proc doAddAccount[T](self: Module[T]) =
self.view.setDisablePopup(true)
let
let
selectedOrigin = self.view.getSelectedOrigin()
selectedAddrItem = self.view.getSelectedDerivedAddress()
var
@ -631,17 +631,17 @@ proc doAddAccount[T](self: Module[T]) =
success = self.controller.addNewPrivateKeyKeypair(
privateKey = self.controller.getGeneratedAccount().privateKey,
doPasswordHashing = not singletonInstance.userProfile.getIsKeycardUser(),
keyUid = keyUid,
keypairName = keypairName,
keyUid = keyUid,
keypairName = keypairName,
rootWalletMasterKey = rootWalletMasterKey,
account = WalletAccountDto(
address: address,
keyUid: keyUid,
publicKey: publicKey,
walletType: accountType,
path: path,
walletType: accountType,
path: path,
name: self.view.getAccountName(),
colorId: self.view.getSelectedColorId(),
colorId: self.view.getSelectedColorId(),
emoji: self.view.getSelectedEmoji()
)
)
@ -651,17 +651,17 @@ proc doAddAccount[T](self: Module[T]) =
success = self.controller.addNewSeedPhraseKeypair(
seedPhrase = self.controller.getSeedPhrase(),
doPasswordHashing = not singletonInstance.userProfile.getIsKeycardUser(),
keyUid = keyUid,
keypairName = keypairName,
keyUid = keyUid,
keypairName = keypairName,
rootWalletMasterKey = rootWalletMasterKey,
accounts = @[WalletAccountDto(
address: address,
keyUid: keyUid,
publicKey: publicKey,
walletType: accountType,
path: path,
walletType: accountType,
path: path,
name: self.view.getAccountName(),
colorId: self.view.getSelectedColorId(),
colorId: self.view.getSelectedColorId(),
emoji: self.view.getSelectedEmoji()
)]
)
@ -671,23 +671,23 @@ proc doAddAccount[T](self: Module[T]) =
success = self.controller.addWalletAccount(
createKeystoreFile = createKeystoreFile,
doPasswordHashing = doPasswordHashing,
name = self.view.getAccountName(),
address = address,
name = self.view.getAccountName(),
address = address,
path = path,
publicKey = publicKey,
keyUid = keyUid,
accountType = accountType,
publicKey = publicKey,
keyUid = keyUid,
accountType = accountType,
colorId = self.view.getSelectedColorId(),
emoji = self.view.getSelectedEmoji())
if not success:
error "failed to store account", address=selectedAddrItem.getAddress()
self.closeAddAccountPopup()
proc doEditAccount[T](self: Module[T]) =
self.view.setDisablePopup(true)
let selectedOrigin = self.view.getSelectedOrigin()
var address = self.view.getWatchOnlyAccAddress().getAddress()
if selectedOrigin.getPairType() == KeyPairType.Profile.int or
selectedOrigin.getPairType() == KeyPairType.SeedImport.int:
@ -696,7 +696,7 @@ proc doEditAccount[T](self: Module[T]) =
elif selectedOrigin.getPairType() == KeyPairType.PrivateKeyImport.int:
let selectedAddrItem = self.view.getPrivateKeyAccAddress()
address = selectedAddrItem.getAddress()
if self.controller.updateAccount(
address = address,
accountName = self.view.getAccountName(),

View File

@ -130,7 +130,7 @@ proc disconnectKeycardReponseSignal(self: Controller) =
proc connectKeycardReponseSignal(self: Controller) =
self.connectionKeycardResponse = self.events.onWithUUID(SIGNAL_KEYCARD_RESPONSE) do(e: Args):
let args = KeycardArgs(e)
let args = KeycardLibArgs(e)
self.delegate.onKeycardResponse(args.flowType, args.flowEvent)
proc disconnectKeycardSyncSignal(self: Controller) =
@ -179,7 +179,7 @@ proc init*(self: Controller, fullConnect = true) =
if fullConnect:
handlerId = self.events.onWithUUID(SIGNAL_NEW_KEYCARD_SET) do(e: Args):
let args = KeycardActivityArgs(e)
let args = KeycardArgs(e)
self.tmpAddingMigratedKeypairSuccess = args.success
self.delegate.onSecondaryActionClicked()
self.connectionIds.add(handlerId)
@ -662,15 +662,10 @@ proc removeMigratedAccountsForKeycard*(self: Controller, keyUid: string, keycard
proc getAddingMigratedKeypairSuccess*(self: Controller): bool =
return self.tmpAddingMigratedKeypairSuccess
proc getKeycardByKeyUid*(self: Controller, keyUid: string): seq[KeycardDto] =
proc getKeycardsWithSameKeyUid*(self: Controller, keyUid: string): seq[KeycardDto] =
if not serviceApplicable(self.walletAccountService):
return
return self.walletAccountService.getKeycardByKeyUid(keyUid)
proc getAllKnownKeycardsGroupedByKeyUid*(self: Controller): seq[KeycardDto] =
if not serviceApplicable(self.walletAccountService):
return
return self.walletAccountService.getAllKnownKeycardsGroupedByKeyUid()
return self.walletAccountService.getKeycardsWithSameKeyUid(keyUid)
proc getAllKnownKeycards*(self: Controller): seq[KeycardDto] =
if not serviceApplicable(self.walletAccountService):

View File

@ -28,7 +28,7 @@ method executePrePrimaryStateCommand*(self: EnterSeedPhraseState, controller: Co
if self.verifiedSeedPhrase:
## should always be true, since it's not possible to do primary command otherwise (button is disabled on the UI)
let keyUid = controller.getKeyUidForSeedPhrase(sp)
self.keyPairAlreadyMigrated = controller.getKeycardByKeyUid(keyUid).len > 0
self.keyPairAlreadyMigrated = controller.getKeycardsWithSameKeyUid(keyUid).len > 0
if self.keyPairAlreadyMigrated:
controller.prepareKeyPairForProcessing(keyUid)
return
@ -78,22 +78,22 @@ method executeCancelCommand*(self: EnterSeedPhraseState, controller: Controller)
self.flowType == FlowType.CreateCopyOfAKeycard:
controller.terminateCurrentFlow(lastStepInTheCurrentFlow = false)
method resolveKeycardNextState*(self: EnterSeedPhraseState, keycardFlowType: string, keycardEvent: KeycardEvent,
method resolveKeycardNextState*(self: EnterSeedPhraseState, keycardFlowType: string, keycardEvent: KeycardEvent,
controller: Controller): State =
let state = ensureReaderAndCardPresence(self, keycardFlowType, keycardEvent, controller)
if not state.isNil:
return state
if self.flowType == FlowType.SetupNewKeycard:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.keyUid.len > 0:
return createState(StateType.MigratingKeyPair, self.flowType, nil)
if self.flowType == FlowType.SetupNewKeycardOldSeedPhrase:
if keycardFlowType == ResponseTypeValueEnterNewPIN and
if keycardFlowType == ResponseTypeValueEnterNewPIN and
keycardEvent.error.len > 0 and
keycardEvent.error == ErrorRequireInit:
return createState(StateType.CreatePin, self.flowType, nil)
if self.flowType == FlowType.CreateCopyOfAKeycard:
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
if keycardFlowType == ResponseTypeValueKeycardFlowResult and
keycardEvent.keyUid.len > 0:
controller.setDestinationKeycardUid(keycardEvent.instanceUID)
return createState(StateType.CopyingKeycard, self.flowType, nil)

View File

@ -68,8 +68,8 @@ QtObject:
self.endRemoveRows()
self.countChanged()
proc removeItemWithKeyUid*(self: KeycardModel, keyUid: string) =
for i in 0 ..< self.items.len:
proc removeItemsWithKeyUid*(self: KeycardModel, keyUid: string) =
for i in countdown(self.items.len-1, 0):
if self.items[i].getKeyUid() == keyUid:
self.removeItem(i)

View File

@ -394,8 +394,8 @@ method onKeycardResponse*[T](self: Module[T], keycardFlowType: string, keycardEv
proc prepareKeyPairItemForAuthentication[T](self: Module[T], keyUid: string) =
var item = newKeyPairItem()
let items = keypairs.buildKeyPairsList(self.controller.getKeypairs(), self.controller.getAllKnownKeycardsGroupedByKeyUid(),
excludeAlreadyMigratedPairs = false, excludePrivateKeyKeypairs = false)
let items = keypairs.buildKeyPairsList(self.controller.getKeypairs(), excludeAlreadyMigratedPairs = false,
excludePrivateKeyKeypairs = false)
for it in items:
if it.getKeyUid() == keyUid:
item = it
@ -416,8 +416,8 @@ method setKeyPairForProcessing*[T](self: Module[T], item: KeyPairItem) =
method prepareKeyPairForProcessing*[T](self: Module[T], keyUid: string, keycardUid = "") =
var item = newKeyPairItem()
let items = keypairs.buildKeyPairsList(self.controller.getKeypairs(), self.controller.getAllKnownKeycardsGroupedByKeyUid(),
excludeAlreadyMigratedPairs = false, excludePrivateKeyKeypairs = false)
let items = keypairs.buildKeyPairsList(self.controller.getKeypairs(), excludeAlreadyMigratedPairs = false,
excludePrivateKeyKeypairs = false)
for it in items:
if it.getKeyUid() == keyUid:
item = it
@ -447,8 +447,8 @@ method runFlow*[T](self: Module[T], flowToRun: FlowType, keyUid = "", bip44Paths
self.controller.runGetMetadataFlow(resolveAddress = true)
return
if flowToRun == FlowType.SetupNewKeycard:
let items = keypairs.buildKeyPairsList(self.controller.getKeypairs(), self.controller.getAllKnownKeycardsGroupedByKeyUid(),
excludeAlreadyMigratedPairs = true, excludePrivateKeyKeypairs = false)
let items = keypairs.buildKeyPairsList(self.controller.getKeypairs(), excludeAlreadyMigratedPairs = true,
excludePrivateKeyKeypairs = false)
self.view.createKeyPairModel(items)
self.view.setCurrentState(newSelectExistingKeyPairState(flowToRun, nil))
self.controller.readyToDisplayPopup()
@ -535,19 +535,6 @@ method setSelectedKeyPair*[T](self: Module[T], item: KeyPairItem) =
paths, keycardDto)
self.setKeyPairForProcessing(item)
proc updateKeyPairItemIfDataAreKnown[T](self: Module[T], address: string, item: var KeyPairItem): bool =
let accounts = self.controller.getWalletAccounts()
for a in accounts:
if a.isChat or a.walletType == WalletTypeWatch or cmpIgnoreCase(a.address, address) != 0:
continue
var icon = ""
if a.walletType == WalletTypeDefaultStatusAccount:
icon = "wallet"
item.setKeyUid(a.keyUid)
item.addAccount(newKeyPairAccountItem(a.name, a.path, a.address, a.publicKey, a.emoji, a.colorId, icon, balance = 0.0, balanceFetched = true))
return true
return false
method onTokensRebuilt*[T](self: Module[T], accountsTokens: OrderedTable[string, seq[WalletTokenDto]]) =
if self.getKeyPairForProcessing().isNil:
return
@ -570,16 +557,32 @@ proc buildKeyPairItemBasedOnCardMetadata[T](self: Module[T], cardMetadata: CardM
result.item.setKeyUid(currKp.getKeyUid())
result.item.setPubKey(currKp.getPubKey())
result.knownKeyPair = true
var unknonwAccountNumber = 0
for wa in cardMetadata.walletAccounts:
if self.updateKeyPairItemIfDataAreKnown(wa.address, result.item):
continue
let (balance, balanceFetched) = self.controller.getOrFetchBalanceForAddressInPreferredCurrency(wa.address)
result.knownKeyPair = false
unknonwAccountNumber.inc
let name = atc.KEYCARD_ACCOUNT_NAME_OF_UNKNOWN_WALLET_ACCOUNT & $unknonwAccountNumber
result.item.addAccount(newKeyPairAccountItem(name, wa.path, wa.address, pubKey = wa.publicKey, emoji = "",
colorId = "", icon = "undefined", balance, balanceFetched))
# resolve known accounts first
let accounts = self.controller.getWalletAccounts()
for acc in accounts:
for cardAcc in cardMetadata.walletAccounts:
if acc.isChat or acc.walletType == WalletTypeWatch or cmpIgnoreCase(acc.address, cardAcc.address) != 0:
continue
var icon = ""
if acc.emoji.len == 0:
icon = "wallet"
result.item.addAccount(newKeyPairAccountItem(acc.name, acc.path, acc.address, acc.publicKey, acc.emoji, acc.colorId, icon,
balance = 0.0, balanceFetched = true))
# handle unknown accounts
var unknownAccountNumber = 0
for cardAcc in cardMetadata.walletAccounts:
var found = false
for acc in accounts:
if cmpIgnoreCase(acc.address, cardAcc.address) == 0:
found = true
break
if not found:
let (balance, balanceFetched) = self.controller.getOrFetchBalanceForAddressInPreferredCurrency(cardAcc.address)
result.knownKeyPair = false
unknownAccountNumber.inc
let name = atc.KEYCARD_ACCOUNT_NAME_OF_UNKNOWN_WALLET_ACCOUNT & $unknownAccountNumber
result.item.addAccount(newKeyPairAccountItem(name, cardAcc.path, cardAcc.address, pubKey = cardAcc.publicKey,
emoji = "", colorId = "undefined", icon = "wallet", balance, balanceFetched))
method updateKeyPairForProcessing*[T](self: Module[T], cardMetadata: CardMetadata) =
let(item, knownKeyPair) = self.buildKeyPairItemBasedOnCardMetadata(cardMetadata)

View File

@ -149,7 +149,7 @@ proc init*(self: Controller) =
self.connectionIds.add(handlerId)
handlerId = self.events.onWithUUID(SIGNAL_KEYCARD_RESPONSE) do(e: Args):
let args = KeycardArgs(e)
let args = KeycardLibArgs(e)
self.delegate.onKeycardResponse(args.flowType, args.flowEvent)
self.connectionIds.add(handlerId)

View File

@ -189,6 +189,12 @@ QtObject:
of "wallet-tick-reload":
self.refetchAllOwnedCollectibles()
self.events.on(SIGNAL_KEYPAIR_SYNCED) do(e: Args):
let args = KeypairArgs(e)
for acc in args.keypair.accounts:
if acc.removed:
self.removeAddress(acc.address)
self.events.on(SIGNAL_WALLET_ACCOUNT_DELETED) do(e:Args):
self.removeAddress(AccountArgs(e).account.address)

View File

@ -49,7 +49,7 @@ include internal
include ../../common/async_tasks
type
KeycardArgs* = ref object of Args
KeycardLibArgs* = ref object of Args
flowType*: string
flowEvent*: KeycardEvent
@ -97,14 +97,14 @@ QtObject:
debug "keycard_signal", response=signal
var typeObj, eventObj: JsonNode
if(not jsonSignal.getProp(ResponseKeyType, typeObj) or
if(not jsonSignal.getProp(ResponseKeyType, typeObj) or
not jsonSignal.getProp(ResponseKeyEvent, eventObj)):
return
let flowType = typeObj.getStr
let flowEvent = toKeycardEvent(eventObj)
self.lastReceivedKeycardData = (flowType: flowType, flowEvent: flowEvent)
self.events.emit(SIGNAL_KEYCARD_RESPONSE, KeycardArgs(flowType: flowType, flowEvent: flowEvent))
self.events.emit(SIGNAL_KEYCARD_RESPONSE, KeycardLibArgs(flowType: flowType, flowEvent: flowEvent))
proc receiveKeycardSignal(self: Service, signal: string) {.slot.} =
self.processSignal(signal)
@ -172,7 +172,7 @@ QtObject:
)
self.threadpool.start(arg)
proc startLoadAccountFlow*(self: Service, seedPhraseLength: int, seedPhrase: string, pin: string, puk: string,
proc startLoadAccountFlow*(self: Service, seedPhraseLength: int, seedPhrase: string, pin: string, puk: string,
factoryReset: bool) =
var payload = %* { }
if seedPhrase.len > 0 and seedPhraseLength > 0:
@ -196,7 +196,7 @@ QtObject:
self.startFlow(payload)
proc startLoginFlowAutomatically*(self: Service, pin: string) =
let payload = %* {
let payload = %* {
RequestParamPIN: pin
}
self.currentFlow = KCSFlowType.Login
@ -213,7 +213,7 @@ QtObject:
if factoryReset:
payload[RequestParamFactoryReset] = %* factoryReset
self.currentFlow = KCSFlowType.RecoverAccount
self.startFlow(payload)
self.startFlow(payload)
proc startGetAppInfoFlow*(self: Service, factoryReset: bool) =
var payload = %* { }
@ -255,7 +255,7 @@ QtObject:
error "in order to export private address path must not be outside of eip1581 tree"
return
var payload = %* {
var payload = %* {
RequestParamBIP44Path: DefaultBIP44Path,
RequestParamExportMasterAddress: exportMasterAddr,
RequestParamExportPrivate: exportPrivateAddr
@ -277,7 +277,7 @@ QtObject:
error "one of paths in the list refers to a private address path which is not in eip1581 tree"
return
var payload = %* {
var payload = %* {
RequestParamBIP44Path: DefaultBIP44Path,
RequestParamExportMasterAddress: exportMasterAddr,
RequestParamExportPrivate: exportPrivateAddr
@ -293,7 +293,7 @@ QtObject:
var name = cardName
if cardName.len > CardNameLength:
name = cardName[0 .. CardNameLength - 1]
let payload = %* {
let payload = %* {
RequestParamPIN: pin,
RequestParamCardName: name,
RequestParamWalletPaths: walletPaths
@ -302,7 +302,7 @@ QtObject:
self.startFlow(payload)
proc startSignFlow*(self: Service, bip44Path: string, txHash: string) =
var payload = %* {
var payload = %* {
RequestParamTXHash: EmptyTxHash,
RequestParamBIP44Path: DefaultBIP44Path
}

View File

@ -86,7 +86,7 @@ type CurrentUserStatus* = object
type
SettingsFieldDto* = object
name*: string
value*: string
value*: JsonNode
type
SettingsDto* = object # There is no point to keep all these info as settings, but we must follow status-go response
@ -156,10 +156,8 @@ proc toCurrentUserStatus*(jsonObj: JsonNode): CurrentUserStatus =
discard jsonObj.getProp("text", result.text)
proc toSettingsFieldDto*(jsonObj: JsonNode): SettingsFieldDto =
var field = SettingsFieldDto()
field.name = jsonObj["name"].getStr()
field.value = jsonObj["value"].getStr()
result = field
discard jsonObj.getProp("name", result.name)
discard jsonObj.getProp("value", result.value)
proc toSettingsDto*(jsonObj: JsonNode): SettingsDto =
discard jsonObj.getProp(KEY_ADDRESS, result.address)

View File

@ -99,19 +99,19 @@ QtObject:
if receivedData.settings.len > 0:
for settingsField in receivedData.settings:
if settingsField.name == KEY_CURRENCY:
self.settings.currency = settingsField.value
self.events.emit(SIGNAL_CURRENCY_UPDATED, SettingsTextValueArgs(value: settingsField.value))
self.settings.currency = settingsField.value.getStr
self.events.emit(SIGNAL_CURRENCY_UPDATED, SettingsTextValueArgs(value: self.settings.currency))
if settingsField.name == KEY_DISPLAY_NAME:
self.settings.displayName = settingsField.value
self.events.emit(SIGNAL_DISPLAY_NAME_UPDATED, SettingsTextValueArgs(value: settingsField.value))
self.settings.displayName = settingsField.value.getStr
self.events.emit(SIGNAL_DISPLAY_NAME_UPDATED, SettingsTextValueArgs(value: self.settings.displayName))
if settingsField.name == KEY_BIO:
self.settings.bio = settingsField.value
self.events.emit(SIGNAL_BIO_UPDATED, SettingsTextValueArgs(value: settingsField.value))
self.settings.bio = settingsField.value.getStr
self.events.emit(SIGNAL_BIO_UPDATED, SettingsTextValueArgs(value: self.settings.bio))
if settingsField.name == KEY_MNEMONIC:
self.settings.mnemonic = ""
self.events.emit(SIGNAL_MNEMONIC_REMOVED, Args())
if settingsField.name == INCLUDE_WATCH_ONLY_ACCOUNT:
self.settings.includeWatchOnlyAccount = parseBool(settingsField.value)
self.settings.includeWatchOnlyAccount = settingsField.value.getBool
self.events.emit(SIGNAL_INCLUDE_WATCH_ONLY_ACCOUNTS_UPDATED, Args())
if receivedData.socialLinksInfo.links.len > 0 or

View File

@ -103,51 +103,55 @@ const prepareTokensTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
#################################################
type
AddKeycardOrAddAccountsIfKeycardIsAddedTaskArg* = ref object of QObjectTaskArg
SaveOrUpdateKeycardTaskArg* = ref object of QObjectTaskArg
keycard: KeycardDto
accountsComingFromKeycard: bool
const addKeycardOrAddAccountsIfKeycardIsAddedTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AddKeycardOrAddAccountsIfKeycardIsAddedTaskArg](argEncoded)
const saveOrUpdateKeycardTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[SaveOrUpdateKeycardTaskArg](argEncoded)
var responseJson = %*{
"success": false,
"keycard": arg.keycard.toJsonNode()
}
try:
let response = backend.addKeycardOrAddAccountsIfKeycardIsAdded(
arg.keycard.keycardUid,
arg.keycard.keycardName,
arg.keycard.keyUid,
arg.keycard.accountsAddresses,
let response = backend.saveOrUpdateKeycard(
%* {
"keycard-uid": arg.keycard.keycardUid,
"keycard-name": arg.keycard.keycardName,
# "keycard-locked" - no need to set it here, cause it will be set to false by the status-go
"key-uid": arg.keycard.keyUid,
"accounts-addresses": arg.keycard.accountsAddresses,
# "position": - no need to set it here, cause it is fully maintained by the status-go
},
arg.accountsComingFromKeycard
)
let success = responseHasNoErrors("addKeycardOrAddAccountsIfKeycardIsAdded", response)
let responseJson = %*{
"success": success,
"keycard": arg.keycard.toJsonNode()
}
arg.finish(responseJson)
let success = responseHasNoErrors("saveOrUpdateKeycard", response)
responseJson["success"] = %* success
except Exception as e:
error "error adding new keycard: ", message = e.msg
arg.finish("")
arg.finish(responseJson)
#################################################
# Async remove migrated accounts for keycard
#################################################
type
RemoveMigratedAccountsForKeycardTaskArg* = ref object of QObjectTaskArg
DeleteKeycardAccountsTaskArg* = ref object of QObjectTaskArg
keycard: KeycardDto
const removeMigratedAccountsForKeycardTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[RemoveMigratedAccountsForKeycardTaskArg](argEncoded)
const deleteKeycardAccountsTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[DeleteKeycardAccountsTaskArg](argEncoded)
var responseJson = %*{
"success": false,
"keycard": arg.keycard.toJsonNode()
}
try:
let response = backend.removeMigratedAccountsForKeycard(
let response = backend.deleteKeycardAccounts(
arg.keycard.keycardUid,
arg.keycard.accountsAddresses
)
let success = responseHasNoErrors("removeMigratedAccountsForKeycard", response)
let responseJson = %*{
"success": success,
"keycard": arg.keycard.toJsonNode()
}
arg.finish(responseJson)
let success = responseHasNoErrors("deleteKeycardAccounts", response)
responseJson["success"] = %* success
except Exception as e:
error "error remove accounts from keycard: ", message = e.msg
arg.finish("")
arg.finish(responseJson)

View File

@ -2,8 +2,7 @@ import tables, json, strformat, sequtils, sugar, strutils
include ../../common/json_utils
const WalletTypeDefaultStatusAccount* = ""
const WalletTypeGenerated* = "generated"
const WalletTypeGenerated* = "generated" # refers to accounts generated from the profile keypair
const WalletTypeSeed* = "seed"
const WalletTypeWatch* = "watch"
const WalletTypeKey* = "key"
@ -193,7 +192,7 @@ proc getBalance*(self: WalletTokenDto, chainIds: seq[int]): float64 =
for chainId in chainIds:
if self.balancesPerChain.hasKey(chainId):
sum += self.balancesPerChain[chainId].balance
return sum
proc getCurrencyBalance*(self: WalletTokenDto, chainIds: seq[int], currency: string): float64 =
@ -202,14 +201,14 @@ proc getCurrencyBalance*(self: WalletTokenDto, chainIds: seq[int], currency: str
for chainId in chainIds:
if self.balancesPerChain.hasKey(chainId):
sum += self.balancesPerChain[chainId].getCurrencyBalance(price)
return sum
proc getVisibleForNetwork*(self: WalletTokenDto, chainIds: seq[int]): bool =
for chainId in chainIds:
if self.balancesPerChain.hasKey(chainId):
return true
return false
proc getVisibleForNetworkWithPositiveBalance*(self: WalletTokenDto, chainIds: seq[int]): bool =
@ -219,7 +218,7 @@ proc getVisibleForNetworkWithPositiveBalance*(self: WalletTokenDto, chainIds: se
if self.balancesPerChain.hasKey(chainId) and self.balancesPerChain[chainId].balance > 0:
return true
return false
proc getCurrencyBalance*(self: WalletAccountDto, chainIds: seq[int], currency: string): float64 =

View File

@ -1,4 +1,5 @@
import NimQml, Tables, json, sequtils, sugar, chronicles, strformat, stint, httpclient, net, strutils, os, times, algorithm
import NimQml, Tables, json, sequtils, sugar, chronicles, strformat, stint, httpclient
import net, strutils, os, times, algorithm, options
import web3/ethtypes
import ../settings/service as settings_service
@ -34,11 +35,10 @@ const SIGNAL_WALLET_ACCOUNT_DERIVED_ADDRESSES_FETCHED* = "walletAccount/derivedA
const SIGNAL_WALLET_ACCOUNT_DERIVED_ADDRESSES_FROM_MNEMONIC_FETCHED* = "walletAccount/derivedAddressesFromMnemonicFetched"
const SIGNAL_WALLET_ACCOUNT_ADDRESS_DETAILS_FETCHED* = "walletAccount/addressDetailsFetched"
const SIGNAL_WALLET_ACCOUNT_POSITION_UPDATED* = "walletAccount/positionUpdated"
const SIGNAL_WALLET_ACCOUNT_OPERABILITY_UPDATED* = "walletAccount/operabilityUpdated"
const SIGNAL_WALLET_ACCOUNT_OPERABILITY_UPDATED* = "walletAccount/operabilityUpdated" # TODO: will be used later, when we deal with account operability
const SIGNAL_KEYPAIR_CHANGED* = "keypairChanged"
const SIGNAL_KEYPAIR_SYNCED* = "keypairSynced"
const SIGNAL_KEYPAIR_NAME_CHANGED* = "keypairNameChanged"
const SIGNAL_KEYPAIR_DELETED* = "keypairDeleted"
const SIGNAL_NEW_KEYCARD_SET* = "newKeycardSet"
const SIGNAL_KEYCARD_DELETED* = "keycardDeleted"
const SIGNAL_KEYCARD_ACCOUNTS_REMOVED* = "keycardAccountsRemoved"
@ -79,6 +79,11 @@ type AccountArgs* = ref object of Args
type KeypairArgs* = ref object of Args
keypair*: KeypairDto
type KeycardArgs* = ref object of Args
success*: bool
oldKeycardUid*: string
keycard*: KeycardDto
type DerivedAddressesArgs* = ref object of Args
uniqueId*: string
derivedAddresses*: seq[DerivedAddressDto]
@ -89,11 +94,6 @@ type TokensPerAccountArgs* = ref object of Args
hasBalanceCache*: bool
hasMarketValuesCache*: bool
type KeycardActivityArgs* = ref object of Args
success*: bool
oldKeycardUid*: string
keycard*: KeycardDto
proc responseHasNoErrors(procName: string, response: RpcResponse[JsonNode]): bool =
var errMsg = ""
if not response.error.isNil:
@ -123,8 +123,7 @@ QtObject:
proc buildAllTokens(self: Service, accounts: seq[string], store: bool)
proc checkRecentHistory*(self: Service)
proc startWallet(self: Service)
proc handleWalletAccount(self: Service, account: WalletAccountDto)
proc handleKeycardActions(self: Service, keycardActions: seq[KeycardActionDto])
proc handleWalletAccount(self: Service, account: WalletAccountDto, notify: bool = true)
proc handleKeypair(self: Service, keypair: KeypairDto)
proc getAllKnownKeycards*(self: Service): seq[KeycardDto]
proc removeMigratedAccountsForKeycard*(self: Service, keyUid: string, keycardUid: string, accountsToRemove: seq[string])
@ -338,8 +337,6 @@ QtObject:
if receivedData.keypairs.len > 0:
for kp in receivedData.keypairs:
self.handleKeypair(kp)
## TODO: will be removed in the second part of synchronization improvements
# self.handleKeycardActions(receivedData.keycardActions)
self.events.on(SignalType.Wallet.event) do(e:Args):
var data = WalletSignal(e)
@ -386,7 +383,7 @@ QtObject:
error "error: ", errDescription
return
proc addNewAccountToLocalStoreAndNotify(self: Service) =
proc addNewAccountToLocalStoreAndNotify(self: Service, notify: bool = true) =
let accounts = self.getAccounts()
var newAccount: WalletAccountDto
var found = false
@ -406,18 +403,21 @@ QtObject:
self.storeAccount(newAccount)
self.buildAllTokens(@[newAccount.address], store = true)
self.events.emit(SIGNAL_WALLET_ACCOUNT_SAVED, AccountArgs(account: newAccount))
if notify:
self.events.emit(SIGNAL_WALLET_ACCOUNT_SAVED, AccountArgs(account: newAccount))
proc removeAccountFromLocalStoreAndNotify(self: Service, address: string) =
proc removeAccountFromLocalStoreAndNotify(self: Service, address: string, notify: bool = true) =
if not self.walletAccountsContainsAddress(address):
return
let removedAcc = self.walletAccounts[address]
self.walletAccounts.del(address)
# updating related accounts for other accounts
self.setRelatedAccountsForAllAccounts(removedAcc.keyUid)
self.events.emit(SIGNAL_WALLET_ACCOUNT_DELETED, AccountArgs(account: removedAcc))
if notify:
self.events.emit(SIGNAL_WALLET_ACCOUNT_DELETED, AccountArgs(account: removedAcc))
proc updateAccountInLocalStoreAndNotify(self: Service, address, name, colorId, emoji: string, position: int = -1, accOperability: string = "") =
proc updateAccountInLocalStoreAndNotify(self: Service, address, name, colorId, emoji: string,
position: Option[int] = none(int), notify: bool = true) =
if not self.walletAccountsContainsAddress(address):
return
var account = self.getAccountByAddress(address)
@ -429,15 +429,13 @@ QtObject:
if emoji.len > 0 and emoji != account.emoji:
account.emoji = emoji
self.storeAccount(account, updateRelatedAccounts = false)
self.events.emit(SIGNAL_WALLET_ACCOUNT_UPDATED, AccountArgs(account: account))
if position > -1 and position != account.position:
account.position = position
if notify:
self.events.emit(SIGNAL_WALLET_ACCOUNT_UPDATED, AccountArgs(account: account))
if position.isSome and position.get != account.position:
account.position = position.get
self.storeAccount(account, updateRelatedAccounts = false)
self.events.emit(SIGNAL_WALLET_ACCOUNT_POSITION_UPDATED, AccountArgs(account: account))
if accOperability.len > 0 and account.operable != accOperability:
account.operable = accOperability
self.storeAccount(account, updateRelatedAccounts = false)
self.events.emit(SIGNAL_WALLET_ACCOUNT_OPERABILITY_UPDATED, AccountArgs(account: account))
if notify:
self.events.emit(SIGNAL_WALLET_ACCOUNT_POSITION_UPDATED, AccountArgs(account: account))
## if password is not provided local keystore file won't be created
proc addWalletAccount*(self: Service, password: string, doPasswordHashing: bool, name, address, path, publicKey,
@ -573,7 +571,7 @@ QtObject:
if not response.error.isNil:
error "status-go error", procName="updateAccountPosition", errCode=response.error.code, errDesription=response.error.message
return
self.updateAccountInLocalStoreAndNotify(address, name = "", colorId = "", emoji = "", position)
self.updateAccountInLocalStoreAndNotify(address, name = "", colorId = "", emoji = "", some(position))
except Exception as e:
error "error: ", procName="updateAccountPosition", errName=e.name, errDesription=e.msg
@ -749,8 +747,8 @@ QtObject:
return 0.0
proc addKeycardOrAccountsAsync*(self: Service, keycard: KeycardDto, accountsComingFromKeycard: bool = false) =
let arg = AddKeycardOrAddAccountsIfKeycardIsAddedTaskArg(
tptr: cast[ByteAddress](addKeycardOrAddAccountsIfKeycardIsAddedTask),
let arg = SaveOrUpdateKeycardTaskArg(
tptr: cast[ByteAddress](saveOrUpdateKeycardTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onKeycardAdded",
keycard: keycard,
@ -759,73 +757,67 @@ QtObject:
self.threadpool.start(arg)
proc emitAddKeycardAddAccountsChange(self: Service, success: bool, keycard: KeycardDto) =
let data = KeycardActivityArgs(
let data = KeycardArgs(
success: success,
keycard: keycard
)
self.events.emit(SIGNAL_NEW_KEYCARD_SET, data)
proc onKeycardAdded*(self: Service, response: string) {.slot.} =
var keycard = KeycardDto()
var success = false
try:
let responseObj = response.parseJson
var keycard: KeycardDto
var success = false
discard responseObj.getProp("success", success)
if success:
var kpJson: JsonNode
if responseObj.getProp("keycard", kpJson):
keycard = kpJson.toKeycardDto()
self.emitAddKeycardAddAccountsChange(success, keycard)
var kpJson: JsonNode
if responseObj.getProp("keycard", kpJson):
keycard = kpJson.toKeycardDto()
except Exception as e:
error "error handilng migrated keycard response", errDesription=e.msg
self.emitAddKeycardAddAccountsChange(success = false, KeycardDto())
self.emitAddKeycardAddAccountsChange(success, keycard)
proc addKeycardOrAccounts*(self: Service, keycard: KeycardDto, accountsComingFromKeycard: bool = false): bool =
var success = false
try:
let response = backend.addKeycardOrAddAccountsIfKeycardIsAdded(
keycard.keycardUid,
keycard.keycardName,
keycard.keyUid,
keycard.accountsAddresses,
let response = backend.saveOrUpdateKeycard(
%* {
"keycard-uid": keycard.keycardUid,
"keycard-name": keycard.keycardName,
# "keycard-locked" - no need to set it here, cause it will be set to false by the status-go
"key-uid": keycard.keyUid,
"accounts-addresses": keycard.accountsAddresses,
# "position": - no need to set it here, cause it is fully maintained by the status-go
},
accountsComingFromKeycard
)
result = responseHasNoErrors("addKeycardOrAccounts", response)
if result:
self.emitAddKeycardAddAccountsChange(success = true, keycard)
success = responseHasNoErrors("addKeycardOrAccounts", response)
except Exception as e:
error "error: ", procName="addKeycardOrAccounts", errName = e.name, errDesription = e.msg
self.emitAddKeycardAddAccountsChange(success = success, keycard)
return success
proc removeMigratedAccountsForKeycard*(self: Service, keyUid: string, keycardUid: string, accountsToRemove: seq[string]) =
let arg = RemoveMigratedAccountsForKeycardTaskArg(
tptr: cast[ByteAddress](removeMigratedAccountsForKeycardTask),
let arg = DeleteKeycardAccountsTaskArg(
tptr: cast[ByteAddress](deleteKeycardAccountsTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onMigratedAccountsForKeycardRemoved",
keycard: KeycardDto(keyUid: keyUid, keycardUid: keycardUid, accountsAddresses: accountsToRemove)
)
self.threadpool.start(arg)
proc emitKeycardRemovedAccountsChange(self: Service, success: bool, keyUid: string, keycardUid: string,
removedAccounts: seq[string]) =
let data = KeycardActivityArgs(
success: success,
keycard: KeycardDto(keyUid: keyUid, keycardUid: keycardUid, accountsAddresses: removedAccounts)
)
self.events.emit(SIGNAL_KEYCARD_ACCOUNTS_REMOVED, data)
proc onMigratedAccountsForKeycardRemoved*(self: Service, response: string) {.slot.} =
var data = KeycardArgs(
success: false,
)
try:
let responseObj = response.parseJson
var keycard: KeycardDto
var success = false
discard responseObj.getProp("success", success)
if success:
var kpJson: JsonNode
if responseObj.getProp("keycard", kpJson):
keycard = kpJson.toKeycardDto()
self.emitKeycardRemovedAccountsChange(success, keycard.keyUid, keycard.keycardUid, keycard.accountsAddresses)
discard responseObj.getProp("success", data.success)
var kpJson: JsonNode
if responseObj.getProp("keycard", kpJson):
data.keycard = kpJson.toKeycardDto()
except Exception as e:
error "error handilng migrated keycard response", errDesription=e.msg
self.emitKeycardRemovedAccountsChange(success = false, keyUid = "", keycardUid = "", removedAccounts = @[])
self.events.emit(SIGNAL_KEYCARD_ACCOUNTS_REMOVED, data)
proc getAllKnownKeycards*(self: Service): seq[KeycardDto] =
try:
@ -835,31 +827,21 @@ QtObject:
except Exception as e:
error "error: ", procName="getAllKnownKeycards", errName = e.name, errDesription = e.msg
proc getKeycardWithKeycardUid*(self: Service, keycardUid: string): KeycardDto =
let allKnownKeycards = self.getAllKnownKeycards()
let keycardsWithKeycardUid = allKnownKeycards.filter(kp => kp.keycardUid == keycardUid)
if keycardsWithKeycardUid.len == 0:
return
if keycardsWithKeycardUid.len > 1:
error "there are more than one keycard with the same uid", keycardUid=keycardUid
return
return keycardsWithKeycardUid[0]
proc getAllKnownKeycardsGroupedByKeyUid*(self: Service): seq[KeycardDto] =
proc getKeycardByKeycardUid*(self: Service, keycardUid: string): KeycardDto =
try:
let response = backend.getAllKnownKeycardsGroupedByKeyUid()
if responseHasNoErrors("getAllKnownKeycardsGroupedByKeyUid", response):
let response = backend.getKeycardByKeycardUID(keycardUid)
if responseHasNoErrors("getKeycardByKeycardUid", response):
return response.result.toKeycardDto()
except Exception as e:
error "error: ", procName="getKeycardByKeycardUid", errName = e.name, errDesription = e.msg
proc getKeycardsWithSameKeyUid*(self: Service, keyUid: string): seq[KeycardDto] =
try:
let response = backend.getKeycardsWithSameKeyUID(keyUid)
if responseHasNoErrors("getKeycardsWithSameKeyUid", response):
return map(response.result.getElems(), proc(x: JsonNode): KeycardDto = toKeycardDto(x))
except Exception as e:
error "error: ", procName="getAllKnownKeycardsGroupedByKeyUid", errName = e.name, errDesription = e.msg
proc getKeycardByKeyUid*(self: Service, keyUid: string): seq[KeycardDto] =
try:
let response = backend.getKeycardByKeyUid(keyUid)
if responseHasNoErrors("getKeycardByKeyUid", response):
return map(response.result.getElems(), proc(x: JsonNode): KeycardDto = toKeycardDto(x))
except Exception as e:
error "error: ", procName="getKeycardByKeyUid", errName = e.name, errDesription = e.msg
error "error: ", procName="getKeycardsWithSameKeyUid", errName = e.name, errDesription = e.msg
proc isKeycardAccount*(self: Service, account: WalletAccountDto): bool =
if account.isNil or
@ -867,108 +849,84 @@ QtObject:
account.path.len == 0 or
utils.isPathOutOfTheDefaultStatusDerivationTree(account.path):
return false
let keycards = self.getKeycardByKeyUid(account.keyUid)
let keycards = self.getKeycardsWithSameKeyUid(account.keyUid)
return keycards.len > 0
proc emitKeycardNameChange(self: Service, keycardUid: string, name: string) =
let data = KeycardActivityArgs(success: true, keycard: KeycardDto(keycardUid: keycardUid, keycardName: name))
self.events.emit(SIGNAL_KEYCARD_NAME_CHANGED, data)
proc updateKeycardName*(self: Service, keycardUid: string, name: string): bool =
var data = KeycardArgs(
success: false,
keycard: KeycardDto(keycardUid: keycardUid, keycardName: name)
)
try:
let response = backend.setKeycardName(keycardUid, name)
result = responseHasNoErrors("updateKeycardName", response)
if result:
self.emitKeycardNameChange(keycardUid, name)
data.success = responseHasNoErrors("updateKeycardName", response)
except Exception as e:
error "error: ", procName="updateKeycardName", errName = e.name, errDesription = e.msg
proc emitKeycardLockedChange(self: Service, keyUid: string, keycardUid: string) =
let data = KeycardActivityArgs(success: true, keycard: KeycardDto(keyUid: keyUid, keycardUid: keycardUid))
self.events.emit(SIGNAL_KEYCARD_LOCKED, data)
self.events.emit(SIGNAL_KEYCARD_NAME_CHANGED, data)
return data.success
proc setKeycardLocked*(self: Service, keyUid: string, keycardUid: string): bool =
var data = KeycardArgs(
success: false,
keycard: KeycardDto(keyUid: keyUid, keycardUid: keycardUid)
)
try:
let response = backend.keycardLocked(keycardUid)
result = responseHasNoErrors("setKeycardLocked", response)
if result:
self.emitKeycardLockedChange(keyUid, keycardUid)
data.success = responseHasNoErrors("setKeycardLocked", response)
except Exception as e:
error "error: ", procName="setKeycardLocked", errName = e.name, errDesription = e.msg
proc emitKeycardUnlockedChange(self: Service, keyUid: string, keycardUid: string) =
let data = KeycardActivityArgs(success: true, keycard: KeycardDto(keyUid: keyUid, keycardUid: keycardUid))
self.events.emit(SIGNAL_KEYCARD_UNLOCKED, data)
self.events.emit(SIGNAL_KEYCARD_LOCKED, data)
return data.success
proc setKeycardUnlocked*(self: Service, keyUid: string, keycardUid: string): bool =
var data = KeycardArgs(
success: false,
keycard: KeycardDto(keyUid: keyUid, keycardUid: keycardUid)
)
try:
let response = backend.keycardUnlocked(keycardUid)
result = responseHasNoErrors("setKeycardUnlocked", response)
if result:
self.emitKeycardUnlockedChange(keyUid, keycardUid)
data.success = responseHasNoErrors("setKeycardUnlocked", response)
except Exception as e:
error "error: ", procName="setKeycardUnlocked", errName = e.name, errDesription = e.msg
proc emitUpdateKeycardUidChange(self: Service, oldKeycardUid: string, newKeycardUid: string) =
let data = KeycardActivityArgs(success: true, oldKeycardUid: oldKeycardUid, keycard: KeycardDto(keycardUid: newKeycardUid))
self.events.emit(SIGNAL_KEYCARD_UID_UPDATED, data)
self.events.emit(SIGNAL_KEYCARD_UNLOCKED, data)
return data.success
proc updateKeycardUid*(self: Service, oldKeycardUid: string, newKeycardUid: string): bool =
var data = KeycardArgs(
success: false,
oldKeycardUid: oldKeycardUid,
keycard: KeycardDto(keycardUid: newKeycardUid)
)
try:
let response = backend.updateKeycardUID(oldKeycardUid, newKeycardUid)
result = responseHasNoErrors("updateKeycardUid", response)
if result:
self.emitUpdateKeycardUidChange(oldKeycardUid, newKeycardUid)
data.success = responseHasNoErrors("updateKeycardUid", response)
except Exception as e:
error "error: ", procName="updateKeycardUid", errName = e.name, errDesription = e.msg
proc emitDeleteKeycardChange(self: Service, keycardUid: string) =
let data = KeycardActivityArgs(success: true, keycard: KeycardDto(keycardUid: keycardUid))
self.events.emit(SIGNAL_KEYCARD_DELETED, data)
self.events.emit(SIGNAL_KEYCARD_UID_UPDATED, data)
return data.success
proc deleteKeycard*(self: Service, keycardUid: string): bool =
var data = KeycardArgs(
success: false,
keycard: KeycardDto(keycardUid: keycardUid)
)
try:
let response = backend.deleteKeycard(keycardUid)
result = responseHasNoErrors("deleteKeycard", response)
if result:
self.emitDeleteKeycardChange(keycardUid)
data.success = responseHasNoErrors("deleteKeycard", response)
except Exception as e:
error "error: ", procName="deleteKeycard", errName = e.name, errDesription = e.msg
return false
self.events.emit(SIGNAL_KEYCARD_DELETED, data)
return data.success
proc handleWalletAccount(self: Service, account: WalletAccountDto) =
proc handleWalletAccount(self: Service, account: WalletAccountDto, notify: bool = true) =
if account.removed:
self.removeAccountFromLocalStoreAndNotify(account.address)
self.removeAccountFromLocalStoreAndNotify(account.address, notify)
else:
if self.walletAccountsContainsAddress(account.address):
self.updateAccountInLocalStoreAndNotify(account.address, account.name, account.colorId, account.emoji, account.position)
self.updateAccountInLocalStoreAndNotify(account.address, account.name, account.colorId, account.emoji,
some(account.position), notify)
else:
self.addNewAccountToLocalStoreAndNotify()
proc handleKeycardActions(self: Service, keycardActions: seq[KeycardActionDto]) =
if keycardActions.len == 0:
return
for kcAction in keycardActions:
if kcAction.action == KeycardActionKeycardAdded or
kcAction.action == KeycardActionAccountsAdded:
self.emitAddKeycardAddAccountsChange(success = true, kcAction.keycard)
elif kcAction.action == KeycardActionKeycardDeleted:
self.emitDeleteKeycardChange(kcAction.keycard.keycardUid)
elif kcAction.action == KeycardActionAccountsRemoved:
let keycard = self.getKeycardWithKeycardUid(kcAction.keycard.keycardUid)
self.emitKeycardRemovedAccountsChange(success = true, keycard.keyUid, kcAction.keycard.keycardUid, kcAction.keycard.accountsAddresses)
elif kcAction.action == KeycardActionLocked:
let keycard = self.getKeycardWithKeycardUid(kcAction.keycard.keycardUid)
self.emitKeycardLockedChange(keycard.keyUid, kcAction.keycard.keycardUid)
elif kcAction.action == KeycardActionUnlocked:
let keycard = self.getKeycardWithKeycardUid(kcAction.keycard.keycardUid)
self.emitKeycardUnlockedChange(keycard.keyUid, kcAction.keycard.keycardUid)
elif kcAction.action == KeycardActionUidUpdated:
self.emitUpdateKeycardUidChange(kcAction.oldKeycardUid, kcAction.keycard.keycardUid)
elif kcAction.action == KeycardActionNameChanged:
self.emitKeycardNameChange(kcAction.keycard.keycardUid, kcAction.keycard.keycardName)
else:
error "unsupported action received", action=kcAction.action
self.addNewAccountToLocalStoreAndNotify(notify)
proc handleKeypair(self: Service, keypair: KeypairDto) =
## In some point in future instead `self.walletAccounts` table we should switch to maintaining local state in the
@ -984,16 +942,13 @@ QtObject:
for localAcc in localKeypairRelatedAccounts:
let accAddress = localAcc.address
if keypair.accounts.filter(a => cmpIgnoreCase(a.address, accAddress) == 0).len == 0:
self.handleWalletAccount(WalletAccountDto(address: accAddress, removed: true))
self.handleWalletAccount(WalletAccountDto(address: accAddress, removed: true), notify = false)
# - second add/update new/existing accounts
for acc in keypair.accounts:
self.handleWalletAccount(acc)
self.handleWalletAccount(acc, notify = false)
if keypair.removed:
self.events.emit(SIGNAL_KEYPAIR_DELETED, KeypairArgs(keypair: keypair))
else:
# notify all interested parts about the keypair change
self.events.emit(SIGNAL_KEYPAIR_CHANGED, KeypairArgs(keypair: keypair))
# notify all interested parts about the keypair change
self.events.emit(SIGNAL_KEYPAIR_SYNCED, KeypairArgs(keypair: keypair))
proc allAccountsTokenBalance*(self: Service, symbol: string): float64 =
var totalTokenBalance = 0.0

View File

@ -221,26 +221,23 @@ rpc(fetchMarketValues, "wallet"):
rpc(fetchTokenDetails, "wallet"):
symbols: seq[string]
rpc(addKeycardOrAddAccountsIfKeycardIsAdded, "accounts"):
keycardUid: string
keyPairName: string
keyUid: string
accountAddresses: seq[string]
rpc(saveOrUpdateKeycard, "accounts"):
keycard: JsonNode
accountsComingFromKeycard: bool
rpc(removeMigratedAccountsForKeycard, "accounts"):
rpc(deleteKeycardAccounts, "accounts"):
keycardUid: string
accountsToRemove: seq[string]
rpc(getAllKnownKeycards, "accounts"):
discard
rpc(getAllKnownKeycardsGroupedByKeyUID, "accounts"):
discard
rpc(getKeycardByKeyUID, "accounts"):
rpc(getKeycardsWithSameKeyUID, "accounts"):
keyUid: string
rpc(getKeycardByKeycardUID, "accounts"):
keycardUid: string
rpc(setKeycardName, "accounts"):
keycardUid: string
keyPairName: string

View File

@ -88,6 +88,11 @@ SettingsContentBase {
onChangeSectionTitle: {
root.sectionTitle = title
}
onDetailsModelIsEmpty: {
// if keypair is removed while user is in the details keycard view mode we need to go back to main keycard view
root.handleBackAction()
}
}
Connections {

View File

@ -19,12 +19,22 @@ ColumnLayout {
property string keyUid: ""
signal changeSectionTitle(string title)
signal detailsModelIsEmpty()
spacing: Constants.settingsSection.itemSpacing
QtObject {
id: d
property bool collapsed: true
readonly property int numOfKeycards: root.keycardStore.keycardModule.keycardDetailsModel?
root.keycardStore.keycardModule.keycardDetailsModel.count
: 0
onNumOfKeycardsChanged: {
if (!!root.keycardStore.keycardModule.keycardDetailsModel && numOfKeycards === 0) {
root.detailsModelIsEmpty()
}
}
function checkAndCheckTitleIfNeeded(newKeycardName) {
// We change title if there is only a single keycard for a keypair in keycard details view

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit 61527f8c7870331bc3c6b61f3adb1c68111e9188
Subproject commit 7063ad11aabf5f6ccb1db4b12e55b69292fd9707