From 86fb93ecb7ab65b05d820b03538f11e8e4496415 Mon Sep 17 00:00:00 2001 From: Sale Djenic Date: Mon, 13 Feb 2023 18:19:08 +0100 Subject: [PATCH] fix(@desktop/keycard): Keycard -> Factory reset: $NaN amount is shown in factory reset flow when account has no funds Fixes: #9418 --- src/app/modules/main/module.nim | 6 +- .../main/profile_section/keycard/module.nim | 6 +- .../modules/main/profile_section/module.nim | 4 +- .../main/wallet_section/accounts/module.nim | 2 +- .../keycard_popup/controller.nim | 28 ++++++++- .../keycard_popup/io_interface.nim | 6 +- .../models/key_pair_account_item.nim | 14 ++++- .../models/key_pair_account_model.nim | 5 ++ .../keycard_popup/models/key_pair_item.nim | 2 + .../shared_modules/keycard_popup/module.nim | 20 +++++-- src/app/modules/startup/module.nim | 2 +- .../service/wallet_account/async_tasks.nim | 14 ++++- .../service/wallet_account/service.nim | 57 ++++++++++++------- .../keycard/helpers/KeyPairUnknownItem.qml | 37 ++++++++---- 14 files changed, 151 insertions(+), 52 deletions(-) diff --git a/src/app/modules/main/module.nim b/src/app/modules/main/module.nim index c0f66b7cac..d0e2ff2cc0 100644 --- a/src/app/modules/main/module.nim +++ b/src/app/modules/main/module.nim @@ -80,6 +80,7 @@ type urlsManager: UrlsManager keycardService: keycard_service.Service settingsService: settings_service.Service + networkService: network_service.Service privacyService: privacy_service.Service accountsService: accounts_service.Service walletAccountService: wallet_account_service.Service @@ -163,6 +164,7 @@ proc newModule*[T]( result.urlsManager = urlsManager result.keycardService = keycardService result.settingsService = settingsService + result.networkService = networkService result.privacyService = privacyService result.accountsService = accountsService result.walletAccountService = walletAccountService @@ -981,7 +983,7 @@ method getKeycardSharedModule*[T](self: Module[T]): QVariant = proc createSharedKeycardModule[T](self: Module[T]) = self.keycardSharedModule = keycard_shared_module.newModule[Module[T]](self, UNIQUE_MAIN_MODULE_IDENTIFIER, - self.events, self.keycardService, self.settingsService, self.privacyService, self.accountsService, + self.events, self.keycardService, self.settingsService, self.networkService, self.privacyService, self.accountsService, self.walletAccountService, self.keychainService) method onSharedKeycarModuleFlowTerminated*[T](self: Module[T], lastStepInTheCurrentFlow: bool) = @@ -1003,7 +1005,7 @@ method onSharedKeycarModuleKeycardSyncPurposeTerminated*[T](self: Module[T], las method tryKeycardSync*[T](self: Module[T], keyUid: string, pin: string) = self.keycardSharedModuleKeycardSyncPurpose = keycard_shared_module.newModule[Module[T]](self, UNIQUE_MAIN_MODULE_KEYCARD_SYNC_IDENTIFIER, - self.events, self.keycardService, self.settingsService, self.privacyService, self.accountsService, + self.events, self.keycardService, self.settingsService, self.networkService, self.privacyService, self.accountsService, self.walletAccountService, self.keychainService) if self.keycardSharedModuleKeycardSyncPurpose.isNil: return diff --git a/src/app/modules/main/profile_section/keycard/module.nim b/src/app/modules/main/profile_section/keycard/module.nim index f3f335e6dd..9de17c5aa7 100644 --- a/src/app/modules/main/profile_section/keycard/module.nim +++ b/src/app/modules/main/profile_section/keycard/module.nim @@ -8,6 +8,7 @@ import ../../../../core/eventemitter import ../../../../../app_service/service/keycard/service as keycard_service import ../../../../../app_service/service/settings/service as settings_service +import ../../../../../app_service/service/network/service as network_service import ../../../../../app_service/service/privacy/service as privacy_service import ../../../../../app_service/service/accounts/service as accounts_service import ../../../../../app_service/service/wallet_account/service as wallet_account_service @@ -36,6 +37,7 @@ type events: EventEmitter keycardService: keycard_service.Service settingsService: settings_service.Service + networkService: network_service.Service privacyService: privacy_service.Service accountsService: accounts_service.Service walletAccountService: wallet_account_service.Service @@ -49,6 +51,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter, keycardService: keycard_service.Service, settingsService: settings_service.Service, + networkService: network_service.Service, privacyService: privacy_service.Service, accountsService: accounts_service.Service, walletAccountService: wallet_account_service.Service, @@ -58,6 +61,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface, result.events = events result.keycardService = keycardService result.settingsService = settingsService + result.networkService = networkService result.privacyService = privacyService result.accountsService = accountsService result.walletAccountService = walletAccountService @@ -102,7 +106,7 @@ proc createSharedKeycardModule(self: Module) = self.view.emitSharedModuleBusy() return self.keycardSharedModule = keycard_shared_module.newModule[Module](self, UNIQUE_SETTING_KEYCARD_MODULE_IDENTIFIER, - self.events, self.keycardService, self.settingsService, self.privacyService, self.accountsService, + self.events, self.keycardService, self.settingsService, self.networkService, self.privacyService, self.accountsService, self.walletAccountService, self.keychainService) method onSharedKeycarModuleFlowTerminated*(self: Module, lastStepInTheCurrentFlow: bool) = diff --git a/src/app/modules/main/profile_section/module.nim b/src/app/modules/main/profile_section/module.nim index 998c21ef66..0f592a8f44 100644 --- a/src/app/modules/main/profile_section/module.nim +++ b/src/app/modules/main/profile_section/module.nim @@ -106,8 +106,8 @@ proc newModule*(delegate: delegate_interface.AccessInterface, result, events, settingsService, ensService, walletAccountService, networkService, tokenService ) result.communitiesModule = communities_module.newModule(result, communityService) - result.keycardModule = keycard_module.newModule(result, events, keycardService, settingsService, privacyService, - accountsService, walletAccountService, keychainService) + result.keycardModule = keycard_module.newModule(result, events, keycardService, settingsService, networkService, + privacyService, accountsService, walletAccountService, keychainService) singletonInstance.engine.setRootContextProperty("profileSectionModule", result.viewVariant) diff --git a/src/app/modules/main/wallet_section/accounts/module.nim b/src/app/modules/main/wallet_section/accounts/module.nim index a6dc7a81a3..d7c370135c 100644 --- a/src/app/modules/main/wallet_section/accounts/module.nim +++ b/src/app/modules/main/wallet_section/accounts/module.nim @@ -237,7 +237,7 @@ method onUserAuthenticated*(self: Module, pin: string, password: string, keyUid: method createSharedKeycardModule*(self: Module) = if self.keycardSharedModule.isNil: self.keycardSharedModule = keycard_shared_module.newModule[Module](self, UNIQUE_WALLET_SECTION_ACCOUNTS_MODULE_IDENTIFIER, - self.events, self.keycardService, settingsService = nil, privacyService = nil, self.accountsService, + self.events, self.keycardService, settingsService = nil, networkService = nil, privacyService = nil, self.accountsService, self.walletAccountService, keychainService = nil) method destroySharedKeycarModule*(self: Module) = diff --git a/src/app/modules/shared_modules/keycard_popup/controller.nim b/src/app/modules/shared_modules/keycard_popup/controller.nim index 79b136bdfb..510390cbce 100644 --- a/src/app/modules/shared_modules/keycard_popup/controller.nim +++ b/src/app/modules/shared_modules/keycard_popup/controller.nim @@ -12,6 +12,7 @@ import ../../../../app_service/common/utils import ../../../../app_service/common/account_constants import ../../../../app_service/service/keycard/service as keycard_service import ../../../../app_service/service/settings/service as settings_service +import ../../../../app_service/service/network/service as network_service import ../../../../app_service/service/privacy/service as privacy_service import ../../../../app_service/service/accounts/service as accounts_service import ../../../../app_service/service/wallet_account/service as wallet_account_service @@ -29,6 +30,7 @@ type events: EventEmitter keycardService: keycard_service.Service settingsService: settings_service.Service + networkService: network_service.Service privacyService: privacy_service.Service accountsService: accounts_service.Service walletAccountService: wallet_account_service.Service @@ -71,6 +73,7 @@ proc newController*(delegate: io_interface.AccessInterface, events: EventEmitter, keycardService: keycard_service.Service, settingsService: settings_service.Service, + networkService: network_service.Service, privacyService: privacy_service.Service, accountsService: accounts_service.Service, walletAccountService: wallet_account_service.Service, @@ -82,6 +85,7 @@ proc newController*(delegate: io_interface.AccessInterface, result.events = events result.keycardService = keycardService result.settingsService = settingsService + result.networkService = networkService result.privacyService = privacyService result.accountsService = accountsService result.walletAccountService = walletAccountService @@ -112,6 +116,8 @@ proc serviceApplicable[T](service: T): bool = serviceName = "PrivacyService" when (service is settings_service.Service): serviceName = "SettingsService" + when (service is network_service.Service): + serviceName = "NetworkService" when (service is accounts_service.Service): serviceName = "AccountsService" when (service is keychain_service.Service): @@ -182,6 +188,11 @@ proc init*(self: Controller) = self.delegate.onSecondaryActionClicked() self.connectionIds.add(handlerId) + handlerId = self.events.onWithUUID(SIGNAL_WALLET_ACCOUNT_TOKENS_REBUILT) do(e:Args): + let arg = TokensPerAccountArgs(e) + self.delegate.onTokensRebuilt(arg.accountsTokens) + self.connectionIds.add(handlerId) + proc switchToWalletSection*(self: Controller) = let data = ActiveSectionChatArgs(sectionId: conf.WALLET_SECTION_ID) self.events.emit(SIGNAL_MAKE_SECTION_CHAT_ACTIVE, data) @@ -602,10 +613,11 @@ proc isKeyPairAlreadyAdded*(self: Controller, keyUid: string): bool = let accountsForKeyUid = walletAccounts.filter(a => a.keyUid == keyUid) return accountsForKeyUid.len > 0 -proc getCurrencyBalanceForAddress*(self: Controller, address: string): float64 = +proc getOrFetchBalanceForAddressInPreferredCurrency*(self: Controller, address: string): tuple[balance: float64, fetched: bool] = if not serviceApplicable(self.walletAccountService): - return - return self.walletAccountService.getCurrencyBalanceForAddress(address) + # Return 0, casuse JSON-RPC client is unavailable before user logs in. + return (0.0, true) + return self.walletAccountService.getOrFetchBalanceForAddressInPreferredCurrency(address) proc addMigratedKeyPair*(self: Controller, keyPair: KeyPairDto) = if not serviceApplicable(self.walletAccountService): @@ -682,6 +694,16 @@ proc getSigningPhrase*(self: Controller): string = return return self.settingsService.getSigningPhrase() +proc getCurrency*(self: Controller): string = + if not serviceApplicable(self.settingsService): + return + return self.settingsService.getCurrency() + +proc getChainIdsOfAllKnownNetworks*(self: Controller): seq[int] = + if not serviceApplicable(self.networkService): + return + return self.networkService.getNetworks().map(n => n.chainId) + proc enterKeycardPin*(self: Controller, pin: string) = if not serviceApplicable(self.keycardService): return diff --git a/src/app/modules/shared_modules/keycard_popup/io_interface.nim b/src/app/modules/shared_modules/keycard_popup/io_interface.nim index b33e0eb5b3..dd1c0dbc74 100644 --- a/src/app/modules/shared_modules/keycard_popup/io_interface.nim +++ b/src/app/modules/shared_modules/keycard_popup/io_interface.nim @@ -1,6 +1,7 @@ -import NimQml +import NimQml, tables import ../../../../app/core/eventemitter from ../../../../app_service/service/keycard/service import KeycardEvent, CardMetadata, KeyDetails +from ../../../../app_service/service/wallet_account/service as wallet_account_service import WalletTokenDto import models/key_pair_item const SIGNAL_SHARED_KEYCARD_MODULE_USER_AUTHENTICATED_AND_WALLET_ADDRESS_GENERATED* = "sharedKeycarModuleUserAuthenticatedAndWalletAddressGenerated" @@ -202,5 +203,8 @@ method syncKeycardBasedOnAppState*(self: AccessInterface, keyUid: string, pin: s method getPin*(self: AccessInterface): string {.base.} = raise newException(ValueError, "No implementation available") +method onTokensRebuilt*(self: AccessInterface, accountsTokens: OrderedTable[string, seq[WalletTokenDto]]) {.base.} = + raise newException(ValueError, "No implementation available") + type DelegateInterface* = concept c diff --git a/src/app/modules/shared_modules/keycard_popup/models/key_pair_account_item.nim b/src/app/modules/shared_modules/keycard_popup/models/key_pair_account_item.nim index f97d066795..84b7ada5d3 100644 --- a/src/app/modules/shared_modules/keycard_popup/models/key_pair_account_item.nim +++ b/src/app/modules/shared_modules/keycard_popup/models/key_pair_account_item.nim @@ -10,12 +10,13 @@ QtObject: color: string icon: string balance: float + balanceFetched: bool proc delete*(self: KeyPairAccountItem) = self.QObject.delete proc newKeyPairAccountItem*(name = "", path = "", address = "", pubKey = "", emoji = "", color = "", icon = "", - balance = 0.0): KeyPairAccountItem = + balance = 0.0, balanceFetched = true): KeyPairAccountItem = new(result, delete) result.QObject.setup result.name = name @@ -26,6 +27,7 @@ QtObject: result.color = color result.icon = icon result.balance = balance + result.balanceFetched = balanceFetched proc `$`*(self: KeyPairAccountItem): string = result = fmt"""KeyPairAccountItem[ @@ -37,7 +39,8 @@ QtObject: color: {self.color}, icon: {self.icon}, icon: {$self.icon}, - balance: {self.balance} + balance: {self.balance}, + balanceFetched: {self.balanceFetched} ]""" proc nameChanged*(self: KeyPairAccountItem) {.signal.} @@ -122,8 +125,15 @@ QtObject: return self.balance proc setBalance*(self: KeyPairAccountItem, value: float) {.slot.} = self.balance = value + self.balanceFetched = true self.balanceChanged() QtProperty[float] balance: read = getBalance write = setBalance + notify = balanceChanged + + proc getBalanceFetched*(self: KeyPairAccountItem): bool {.slot.} = + return self.balanceFetched + QtProperty[bool] balanceFetched: + read = getBalanceFetched notify = balanceChanged \ No newline at end of file diff --git a/src/app/modules/shared_modules/keycard_popup/models/key_pair_account_model.nim b/src/app/modules/shared_modules/keycard_popup/models/key_pair_account_model.nim index 5f9fe8f43c..743d99df31 100644 --- a/src/app/modules/shared_modules/keycard_popup/models/key_pair_account_model.nim +++ b/src/app/modules/shared_modules/keycard_popup/models/key_pair_account_model.nim @@ -119,4 +119,9 @@ QtObject: if emoji.len > 0: self.items[i].setEmoji(emoji) return + + proc setBalanceForAddress*(self: KeyPairAccountModel, address: string, balance: float) = + for i in 0 ..< self.items.len: + if cmpIgnoreCase(self.items[i].getAddress(), address) == 0: + self.items[i].setBalance(balance) \ No newline at end of file diff --git a/src/app/modules/shared_modules/keycard_popup/models/key_pair_item.nim b/src/app/modules/shared_modules/keycard_popup/models/key_pair_item.nim index 841de1930e..4cf09a3575 100644 --- a/src/app/modules/shared_modules/keycard_popup/models/key_pair_item.nim +++ b/src/app/modules/shared_modules/keycard_popup/models/key_pair_item.nim @@ -196,6 +196,8 @@ QtObject: return self.accounts.containsPathOutOfTheDefaultStatusDerivationTree() proc updateDetailsForAccountWithAddressIfTheyAreSet*(self: KeyPairItem, address, name, color, emoji: string) = self.accounts.updateDetailsForAddressIfTheyAreSet(address, name, color, emoji) + proc setBalanceForAddress*(self: KeyPairItem, address: string, balance: float) = + self.accounts.setBalanceForAddress(address, balance) proc setItem*(self: KeyPairItem, item: KeyPairItem) = self.setKeyUid(item.getKeyUid()) diff --git a/src/app/modules/shared_modules/keycard_popup/module.nim b/src/app/modules/shared_modules/keycard_popup/module.nim index f4382bc786..21155efd10 100644 --- a/src/app/modules/shared_modules/keycard_popup/module.nim +++ b/src/app/modules/shared_modules/keycard_popup/module.nim @@ -1,4 +1,4 @@ -import NimQml, random, strutils, marshal, sequtils, sugar, chronicles +import NimQml, tables, random, strutils, marshal, sequtils, sugar, chronicles import io_interface import view, controller @@ -11,6 +11,7 @@ import ../../../../app_service/common/utils import ../../../../app_service/service/keycard/constants import ../../../../app_service/service/keycard/service as keycard_service import ../../../../app_service/service/settings/service as settings_service +import ../../../../app_service/service/network/service as network_service import ../../../../app_service/service/privacy/service as privacy_service import ../../../../app_service/service/accounts/service as accounts_service import ../../../../app_service/service/wallet_account/service as wallet_account_service @@ -43,6 +44,7 @@ proc newModule*[T](delegate: T, events: EventEmitter, keycardService: keycard_service.Service, settingsService: settings_service.Service, + networkService: network_service.Service, privacyService: privacy_service.Service, accountsService: accounts_service.Service, walletAccountService: wallet_account_service.Service, @@ -53,7 +55,7 @@ proc newModule*[T](delegate: T, result.view = view.newView(result) result.viewVariant = newQVariant(result.view) result.controller = controller.newController(result, uniqueIdentifier, events, keycardService, settingsService, - privacyService, accountsService, walletAccountService, keychainService) + networkService, privacyService, accountsService, walletAccountService, keychainService) result.initialized = false result.authenticationPopupIsAlreadyRunning = false result.derivingAccountDetails.deriveAddressAfterAuthentication = false @@ -624,10 +626,17 @@ proc updateKeyPairItemIfDataAreKnown[T](self: Module[T], address: string, item: if a.walletType == WalletTypeDefaultStatusAccount: icon = "wallet" item.setKeyUid(a.keyUid) - item.addAccount(newKeyPairAccountItem(a.name, a.path, a.address, a.publicKey, a.emoji, a.color, icon, balance = 0.0)) + item.addAccount(newKeyPairAccountItem(a.name, a.path, a.address, a.publicKey, a.emoji, a.color, icon, balance = 0.0, balanceFetched = true)) return true return false +method onTokensRebuilt*[T](self: Module[T], accountsTokens: OrderedTable[string, seq[WalletTokenDto]]) = + let chainIds = self.controller.getChainIdsOfAllKnownNetworks() + let currency = self.controller.getCurrency() + for address, tokens in accountsTokens.pairs: + let balance = tokens.map(t => t.getCurrencyBalance(chainIds, currency)).foldl(a + b, 0.0) + self.getKeyPairForProcessing().setBalanceForAddress(address, balance) + proc buildKeyPairItemBasedOnCardMetadata[T](self: Module[T], cardMetadata: CardMetadata): tuple[item: KeyPairItem, knownKeyPair: bool] = result.item = newKeyPairItem(keyUid = "", @@ -646,9 +655,10 @@ proc buildKeyPairItemBasedOnCardMetadata[T](self: Module[T], cardMetadata: CardM for wa in cardMetadata.walletAccounts: if self.updateKeyPairItemIfDataAreKnown(wa.address, result.item): continue - let balance = self.controller.getCurrencyBalanceForAddress(wa.address) + let (balance, balanceFetched) = self.controller.getOrFetchBalanceForAddressInPreferredCurrency(wa.address) result.knownKeyPair = false - result.item.addAccount(newKeyPairAccountItem(name = "", wa.path, wa.address, pubKey = wa.publicKey, emoji = "", color = self.generateRandomColor(), icon = "wallet", balance)) + result.item.addAccount(newKeyPairAccountItem(name = "", wa.path, wa.address, pubKey = wa.publicKey, emoji = "", + color = self.generateRandomColor(), icon = "wallet", balance, balanceFetched)) method updateKeyPairForProcessing*[T](self: Module[T], cardMetadata: CardMetadata) = let(item, knownKeyPair) = self.buildKeyPairItemBasedOnCardMetadata(cardMetadata) diff --git a/src/app/modules/startup/module.nim b/src/app/modules/startup/module.nim index 99cac1d1df..28bcdef7e5 100644 --- a/src/app/modules/startup/module.nim +++ b/src/app/modules/startup/module.nim @@ -129,7 +129,7 @@ method getKeycardSharedModule*[T](self: Module[T]): QVariant = proc createSharedKeycardModule[T](self: Module[T]) = self.keycardSharedModule = keycard_shared_module.newModule[Module[T]](self, UNIQUE_STARTUP_MODULE_IDENTIFIER, - self.events, self.keycardService, settingsService = nil, privacyService = nil, self.accountsService, + self.events, self.keycardService, settingsService = nil, networkService = nil, privacyService = nil, self.accountsService, walletAccountService = nil, self.keychainService) method moveToLoadingAppState*[T](self: Module[T]) = diff --git a/src/app_service/service/wallet_account/async_tasks.nim b/src/app_service/service/wallet_account/async_tasks.nim index 6d81597f59..3b9e6d9b62 100644 --- a/src/app_service/service/wallet_account/async_tasks.nim +++ b/src/app_service/service/wallet_account/async_tasks.nim @@ -112,11 +112,21 @@ const fetchDerivedAddressDetailsTask*: Task = proc(argEncoded: string) {.gcsafe, type BuildTokensTaskArg = ref object of QObjectTaskArg accounts: seq[string] + storeResult: bool const prepareTokensTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = let arg = decode[BuildTokensTaskArg](argEncoded) - let response = backend.getWalletToken(arg.accounts) - arg.finish(response.result) + var output = %*{ + "result": "", + "storeResult": false + } + try: + let response = backend.getWalletToken(arg.accounts) + output["result"] = response.result + output["storeResult"] = %* arg.storeResult + except Exception as e: + let err = fmt"Error getting wallet tokens" + arg.finish(output) ################################################# # Async add migrated keypair diff --git a/src/app_service/service/wallet_account/service.nim b/src/app_service/service/wallet_account/service.nim index 108d20b76a..5701b7995c 100644 --- a/src/app_service/service/wallet_account/service.nim +++ b/src/app_service/service/wallet_account/service.nim @@ -120,7 +120,7 @@ QtObject: walletAccounts {.guard: walletAccountsLock.}: OrderedTable[string, WalletAccountDto] # Forward declaration - proc buildAllTokens(self: Service, accounts: seq[string]) + proc buildAllTokens(self: Service, accounts: seq[string], store: bool) proc checkRecentHistory*(self: Service) proc checkConnected(self: Service) proc startWallet(self: Service) @@ -212,7 +212,7 @@ QtObject: account.relatedAccounts = accounts.filter(x => not account.derivedFrom.isEmptyOrWhitespace and (cmpIgnoreCase(x.derivedFrom, account.derivedFrom) == 0)) self.storeAccount(account) - self.buildAllTokens(self.getAddresses()) + self.buildAllTokens(self.getAddresses(), store = true) self.checkRecentHistory() self.startWallet() except Exception as e: @@ -231,7 +231,7 @@ QtObject: var data = WalletSignal(e) case data.eventType: of "wallet-tick-reload": - self.buildAllTokens(self.getAddresses()) + self.buildAllTokens(self.getAddresses(), store = true) self.checkRecentHistory() of "wallet-tick-check-connected": self.checkConnected() @@ -290,7 +290,7 @@ QtObject: newAccount.relatedAccounts = accounts.filter(x => cmpIgnoreCase(x.derivedFrom, account.derivedFrom) == 0) break self.storeAccount(newAccount) - self.buildAllTokens(@[newAccount.address]) + self.buildAllTokens(@[newAccount.address], store = true) self.events.emit(SIGNAL_WALLET_ACCOUNT_SAVED, AccountSaved(account: newAccount)) proc addOrReplaceWalletAccount(self: Service, name, address, path, addressAccountIsDerivedFrom, publicKey, keyUid, accountType, @@ -405,7 +405,7 @@ QtObject: proc updateCurrency*(self: Service, newCurrency: string) = discard self.settingsService.saveCurrency(newCurrency) - self.buildAllTokens(self.getAddresses()) + self.buildAllTokens(self.getAddresses(), store = true) self.events.emit(SIGNAL_WALLET_ACCOUNT_CURRENCY_UPDATED, CurrencyUpdated()) proc toggleNetworkEnabled*(self: Service, chainId: int) = @@ -525,27 +525,33 @@ QtObject: let chainIds = self.networkService.getNetworks().map(n => n.chainId) let responseObj = response.parseJson + var storeResult: bool + var resultObj: JsonNode + discard responseObj.getProp("storeResult", storeResult) + discard responseObj.getProp("result", resultObj) + var data = TokensPerAccountArgs() - if responseObj.kind == JObject: - for wAddress, tokensDetailsObj in responseObj: + if resultObj.kind == JObject: + for wAddress, tokensDetailsObj in resultObj: if tokensDetailsObj.kind == JArray: var tokens: seq[WalletTokenDto] tokens = map(tokensDetailsObj.getElems(), proc(x: JsonNode): WalletTokenDto = x.toWalletTokenDto()) tokens.sort(priorityTokenCmp) data.accountsTokens[wAddress] = tokens - self.storeTokensForAccount(wAddress, tokens) - self.tokenService.updateTokenPrices(tokens) # For efficiency. Will be removed when token info fetching gets moved to the tokenService - # Gather symbol for visible tokens - for token in tokens: - if token.getVisibleForNetworkWithPositiveBalance(chainIds) and find(visibleSymbols, token.symbol) == -1: - visibleSymbols.add(token.symbol) + if storeResult: + self.storeTokensForAccount(wAddress, tokens) + self.tokenService.updateTokenPrices(tokens) # For efficiency. Will be removed when token info fetching gets moved to the tokenService + # Gather symbol for visible tokens + for token in tokens: + if token.getVisibleForNetworkWithPositiveBalance(chainIds) and find(visibleSymbols, token.symbol) == -1: + visibleSymbols.add(token.symbol) self.events.emit(SIGNAL_WALLET_ACCOUNT_TOKENS_REBUILT, data) - - discard backend.updateVisibleTokens(visibleSymbols) + if visibleSymbols.len > 0: + discard backend.updateVisibleTokens(visibleSymbols) except Exception as e: error "error: ", procName="onAllTokensBuilt", errName = e.name, errDesription = e.msg - proc buildAllTokens(self: Service, accounts: seq[string]) = + proc buildAllTokens(self: Service, accounts: seq[string], store: bool) = if not singletonInstance.localAccountSensitiveSettings.getIsWalletEnabled() or accounts.len == 0: return @@ -554,16 +560,17 @@ QtObject: tptr: cast[ByteAddress](prepareTokensTask), vptr: cast[ByteAddress](self.vptr), slot: "onAllTokensBuilt", - accounts: accounts + accounts: accounts, + storeResult: store ) self.threadpool.start(arg) proc onIsWalletEnabledChanged*(self: Service) {.slot.} = - self.buildAllTokens(self.getAddresses()) + self.buildAllTokens(self.getAddresses(), store = true) self.checkRecentHistory() self.startWallet() - proc getCurrentCurrencyIfEmpty(self: Service, currency: string): string = + proc getCurrentCurrencyIfEmpty(self: Service, currency = ""): string = if currency != "": return currency else: @@ -577,9 +584,15 @@ QtObject: proc findTokenSymbolByAddress*(self: Service, address: string): string = return self.tokenService.findTokenSymbolByAddress(address) - proc getCurrencyBalanceForAddress*(self: Service, address: string, currency: string = ""): float64 = - let chainIds = self.networkService.getNetworks().map(n => n.chainId) - return self.getAccountByAddress(address).getCurrencyBalance(chainIds, self.getCurrentCurrencyIfEmpty(currency)) + proc getOrFetchBalanceForAddressInPreferredCurrency*(self: Service, address: string): tuple[balance: float64, fetched: bool] = + if self.walletAccountsContainsAddress(address): + let chainIds = self.networkService.getNetworks().map(n => n.chainId) + result.balance = self.getAccountByAddress(address).getCurrencyBalance(chainIds, self.getCurrentCurrencyIfEmpty()) + result.fetched = true + else: + self.buildAllTokens(@[address], store = false) + result.balance = 0.0 + result.fetched = false proc getTotalCurrencyBalance*(self: Service, currency: string = ""): float64 = let chainIds = self.networkService.getNetworks().filter(a => a.enabled).map(a => a.chainId) diff --git a/ui/imports/shared/popups/keycard/helpers/KeyPairUnknownItem.qml b/ui/imports/shared/popups/keycard/helpers/KeyPairUnknownItem.qml index 04326fb59b..f04652319f 100644 --- a/ui/imports/shared/popups/keycard/helpers/KeyPairUnknownItem.qml +++ b/ui/imports/shared/popups/keycard/helpers/KeyPairUnknownItem.qml @@ -126,17 +126,34 @@ Rectangle { Layout.preferredHeight: parent.height } - StatusBaseText { - Layout.alignment: Qt.AlignVCenter - text: { - return LocaleUtils.currencyAmountToLocaleString({ - amount: parseFloat(model.account.balance.amount), - symbol: SharedStore.RootStore.currencyStore.currentCurrencySymbol, - displayDecimals: 2}) + Component { + id: balance + StatusBaseText { + + text: { + return LocaleUtils.currencyAmountToLocaleString({ + amount: parseFloat(model.account.balance), + symbol: SharedStore.RootStore.currencyStore.currentCurrencySymbol, + displayDecimals: 2}) + } + wrapMode: Text.WordWrap + font.pixelSize: Constants.keycard.general.fontSize2 + color: Theme.palette.baseColor1 } - wrapMode: Text.WordWrap - font.pixelSize: Constants.keycard.general.fontSize2 - color: Theme.palette.baseColor1 + } + + Component { + id: fetchingBalance + StatusLoadingIndicator { + width: 12 + height: 12 + } + } + + Loader { + id: fetchLoaderIndicator + Layout.alignment: Qt.AlignVCenter + sourceComponent: model.account.balanceFetched? balance : fetchingBalance } } }