feat(wallet): Recalculate specific entries in accounts model (#16344)

This commit is contained in:
Cuteivist 2024-10-03 14:49:10 +02:00 committed by GitHub
parent 277f408e0c
commit 932e6e2820
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 204 additions and 48 deletions

View File

@ -32,6 +32,9 @@ proc init*(self: Controller) =
proc getWalletAccounts*(self: Controller): seq[wallet_account_service.WalletAccountDto] =
return self.walletAccountService.getWalletAccounts()
proc getWalletAccountsByAddresses*(self: Controller, addresses: seq[string]): seq[wallet_account_service.WalletAccountDto] =
return self.walletAccountService.getAccountsByAddresses(addresses)
proc isKeycardAccount*(self: Controller, account: WalletAccountDto): bool =
return self.walletAccountService.isKeycardAccount(account)
@ -73,6 +76,3 @@ proc updateWatchAccountHiddenFromTotalBalance*(self: Controller, address: string
proc getTokensMarketValuesLoading*(self: Controller): bool =
return self.walletAccountService.getTokensMarketValuesLoading()
proc getChainIds*(self: Controller): seq[int] =
return self.networkService.getCurrentNetworksChainIds()

View File

@ -16,10 +16,10 @@ method isLoaded*(self: AccessInterface): bool {.base.} =
method deleteAccount*(self: AccessInterface, address: string) {.base.} =
raise newException(ValueError, "No implementation available")
method refreshWalletAccounts*(self: AccessInterface) {.base.} =
method loadAllWalletAccounts*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method filterChanged*(self: AccessInterface, addresses: seq[string], chainIds: seq[int]) {.base.} =
method filterChanged*(self: AccessInterface, chainIds: seq[int]) {.base.} =
raise newException(ValueError, "No implementation available")
method updateAccount*(self: AccessInterface, address: string, accountName: string, colorId: string, emoji: string) {.base.} =

View File

@ -125,3 +125,13 @@ QtObject:
proc canSend*(self: Item): bool =
return self.canSend
proc setAssetsLoading*(self: Item, value: bool) =
self.assetsLoading = value
proc setBalance*(self: Item, value: CurrencyAmount) =
self.currencyBalance = value
self.currencyBalanceChanged()
proc setHideFromTotalBalance*(self: Item, value: bool) =
self.hideFromTotalBalance = value

View File

@ -1,4 +1,4 @@
import NimQml, Tables, strutils, stew/shims/strformat, std/sequtils
import NimQml, Tables, strutils, stew/shims/strformat, std/sequtils, logging
import ./item
import ../../../shared_models/currency_amount
@ -93,12 +93,15 @@ QtObject:
self.items.insert(item, index)
self.endInsertRows()
proc findAccountIndex(self: Model, account: Item): int =
proc findAccountIndex(self: Model, address: string): int =
for i in 0 ..< self.items.len:
if self.items[i].address() == account.address():
if(cmpIgnoreCase(self.items[i].address(), address) == 0):
return i
return -1
proc findAccountIndex(self: Model, account: Item): int =
return self.findAccountIndex(account.address())
proc setItems*(self: Model, items: seq[Item]) =
var indexesToRemove: seq[int]
@ -129,6 +132,21 @@ QtObject:
for item in items:
self.itemChanged(item.address())
proc updateItems*(self: Model, items: seq[Item]) =
for account in items:
let i = self.findAccountIndex(account)
if i >= 0:
self.items[i] = account
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.dataChanged(index, index)
else:
self.insertItem(account, self.getCount())
self.countChanged()
for item in items:
self.itemChanged(item.address())
method data(self: Model, index: QModelIndex, role: int): QVariant =
if (not index.isValid):
return
@ -173,34 +191,73 @@ QtObject:
of ModelRole.CanSend:
result = newQVariant(item.canSend())
proc updateBalance*(self: Model, address: string, balance: CurrencyAmount, assetsLoading: bool) =
let i = self.findAccountIndex(address)
if i < 0:
error "Trying to update invalid account"
return
self.items[i].setBalance(balance)
self.items[i].setAssetsLoading(assetsLoading)
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.CurrencyBalance.int, ModelRole.AssetsLoading.int])
proc updateAccountHiddenFromTotalBalance*(self: Model, address: string, hideFromTotalBalance: bool) =
let i = self.findAccountIndex(address)
if i < 0:
return
self.items[i].setHideFromTotalBalance(hideFromTotalBalance)
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.HideFromTotalBalance.int])
proc updateAccountsPositions*(self: Model, values: Table[string, int]) =
for address, position in values:
let i = self.findAccountIndex(address)
if i < 0:
continue
self.items[i].setPosition(position)
let firstIndex = self.createIndex(0, 0, nil)
let lastIndex = self.createIndex(self.rowCount() - 1, 0, nil)
defer:
firstIndex.delete
lastIndex.delete
self.dataChanged(firstIndex, lastIndex, @[ModelRole.Position.int])
proc deleteAccount*(self: Model, address: string) =
let i = self.findAccountIndex(address)
if i < 0:
return
self.removeItemWithIndex(i)
proc getNameByAddress*(self: Model, address: string): string =
for item in self.items:
if(cmpIgnoreCase(item.address(), address) == 0):
return item.name()
let i = self.findAccountIndex(address)
if i < 0:
return ""
return self.items[i].name()
proc getEmojiByAddress*(self: Model, address: string): string =
for item in self.items:
if(cmpIgnoreCase(item.address(), address) == 0):
return item.emoji()
let i = self.findAccountIndex(address)
if i < 0:
return ""
return self.items[i].emoji()
proc getColorByAddress*(self: Model, address: string): string =
for item in self.items:
if(cmpIgnoreCase(item.address(), address) == 0):
return item.colorId()
let i = self.findAccountIndex(address)
if i < 0:
return ""
return self.items[i].colorId()
proc isOwnedAccount*(self: Model, address: string): bool =
for item in self.items:
if cmpIgnoreCase(item.address(), address) == 0 and item.walletType != "watch":
return true
let i = self.findAccountIndex(address)
if i < 0:
return false
return self.items[i].walletType != "watch"
proc onPreferredSharingChainsUpdated*(self: Model, address, prodPreferredChainIds, testPreferredChainIds: string) =
var i = 0
for item in self.items.mitems:
if address == item.address:
if(cmpIgnoreCase(item.address, address) == 0):
item.prodPreferredChainIds = prodPreferredChainIds
item.testPreferredChainIds = testPreferredChainIds
let index = self.createIndex(i, 0, nil)

View File

@ -1,12 +1,14 @@
import NimQml, json, sequtils, sugar
import NimQml, json, sequtils, sugar, tables
import ./io_interface, ./view, ./controller
import ./item as wallet_accounts_item
import ../io_interface as delegate_interface
import app/global/global_singleton
import app/core/eventemitter
import app_service/service/wallet_account/service as wallet_account_service
import app_service/service/network/service as network_service
import app_service/service/currency/service as currency_service
import app_service/service/token/service as token_service
import app/modules/shared/wallet_utils
export io_interface
@ -20,6 +22,7 @@ type
controller: Controller
moduleLoaded: bool
walletAccountService: wallet_account_service.Service
filterChainIds: seq[int]
proc newModule*(
delegate: delegate_interface.AccessInterface,
@ -42,28 +45,53 @@ method delete*(self: Module) =
self.view.delete
self.controller.delete
method filterChanged*(self: Module, addresses: seq[string], chainIds: seq[int]) =
let walletAccounts = self.controller.getWalletAccounts()
proc getWalletAccounts(self: Module, addresses: seq[string]): seq[wallet_account_service.WalletAccountDto] =
if addresses.len > 0:
return self.controller.getWalletAccountsByAddresses(addresses)
return self.controller.getWalletAccounts()
proc refreshWalletAccountsBalances(self: Module, addresses: seq[string]) =
let walletAccounts = self.getWalletAccounts(addresses)
let currency = self.controller.getCurrentCurrency()
let currencyFormat = self.controller.getCurrencyFormat(currency)
let marketValuesLoading = self.controller.getTokensMarketValuesLoading()
for walletAccount in walletAccounts:
let currencyBalance = self.controller.getTotalCurrencyBalance(walletAccount.address, self.filterChainIds)
self.view.updateBalance(walletAccount.address, currencyAmountToItem(currencyBalance, currencyFormat), walletAccount.assetsLoading or marketValuesLoading)
proc refreshAllWalletAccountsBalances(self: Module) =
self.refreshWalletAccountsBalances(@[])
proc getWalletItems(self: Module, addresses: seq[string]): seq[wallet_accounts_item.Item] =
let walletAccounts = self.getWalletAccounts(addresses)
let currency = self.controller.getCurrentCurrency()
let allChainIds = self.controller.getChainIds()
let currencyFormat = self.controller.getCurrencyFormat(currency)
let areTestNetworksEnabled = self.controller.areTestNetworksEnabled()
let items = walletAccounts.map(w => (block:
let currencyBalance = self.controller.getTotalCurrencyBalance(w.address, chainIds)
let keycardAccount = self.controller.isKeycardAccount(w)
return walletAccounts.map(w => (block:
let currencyBalance = self.controller.getTotalCurrencyBalance(w.address, self.filterChainIds)
let isKeycardAccount = self.controller.isKeycardAccount(w)
walletAccountToWalletAccountsItem(
w,
keycardAccount,
allChainIds,
chainIds,
isKeycardAccount,
currencyBalance,
currencyFormat,
areTestNetworksEnabled,
self.controller.getTokensMarketValuesLoading()
)
))
self.view.setItems(items)
proc updateWalletAccounts(self: Module, addresses: seq[string]) =
self.view.updateItems(self.getWalletItems(addresses))
method loadAllWalletAccounts*(self: Module) =
self.view.setItems(self.getWalletItems(@[]))
method filterChanged*(self: Module, chainIds: seq[int]) =
if self.filterChainIds == chainIds:
return
self.filterChainIds = chainIds
self.refreshAllWalletAccountsBalances()
method load*(self: Module) =
singletonInstance.engine.setRootContextProperty("walletSectionAccounts", self.viewVariant)
@ -73,6 +101,38 @@ method load*(self: Module) =
self.events.on(SIGNAL_WALLET_ACCOUNT_PREFERRED_SHARING_CHAINS_UPDATED) do(e: Args):
let args = AccountArgs(e)
self.view.onPreferredSharingChainsUpdated(args.account.keyUid, args.account.address, args.account.prodPreferredChainIds, args.account.testPreferredChainIds)
self.events.on(SIGNAL_TOKENS_MARKET_VALUES_UPDATED) do(e:Args):
self.refreshAllWalletAccountsBalances()
self.events.on(SIGNAL_CURRENCY_FORMATS_UPDATED) do(e:Args):
self.refreshAllWalletAccountsBalances()
self.events.on(SIGNAL_WALLET_ACCOUNT_TOKENS_REBUILT) do(e:Args):
self.refreshAllWalletAccountsBalances()
self.events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e:Args):
self.refreshAllWalletAccountsBalances()
self.events.on(SIGNAL_KEYPAIR_SYNCED) do(e: Args):
self.loadAllWalletAccounts()
self.events.on(SIGNAL_WALLET_ACCOUNT_UPDATED) do(e:Args):
let accountArgs = AccountArgs(e)
self.updateWalletAccounts(@[accountArgs.account.address])
self.events.on(SIGNAL_WALLET_ACCOUNT_SAVED) do(e:Args):
let accountArgs = AccountArgs(e)
self.updateWalletAccounts(@[accountArgs.account.address])
self.events.on(SIGNAL_WALLET_ACCOUNT_DELETED) do(e:Args):
let accountArgs = AccountArgs(e)
self.view.onAccountRemoved(accountArgs.account.address)
self.events.on(SIGNAL_NEW_KEYCARD_SET) do(e: Args):
self.loadAllWalletAccounts()
self.events.on(SIGNAL_ALL_KEYCARDS_DELETED) do(e: Args):
self.loadAllWalletAccounts()
self.events.on(SIGNAL_WALLET_ACCOUNT_POSITION_UPDATED) do(e: Args):
let walletAccounts = self.getWalletAccounts(@[])
var accountPositions = initTable[string, int]()
for walletAccount in walletAccounts.items:
accountPositions[walletAccount.address] = walletAccount.position
self.view.updateAccountsPositions(accountPositions)
self.events.on(SIGNAL_WALLET_ACCOUNT_HIDDEN_UPDATED) do(e: Args):
let accountArgs = AccountArgs(e)
self.view.updateAccountHiddenFromTotalBalance(accountArgs.account.address, accountArgs.account.hideFromTotalBalance)
method isLoaded*(self: Module): bool =
return self.moduleLoaded

View File

@ -1,6 +1,7 @@
import NimQml, json, sequtils, strutils
import NimQml, json, sequtils, strutils, tables
import app_service/service/wallet_account/service as wallet_account_service
import app/modules/shared_models/currency_amount
import ./model
import ./item
@ -40,6 +41,21 @@ QtObject:
proc setItems*(self: View, items: seq[Item]) =
self.accounts.setItems(items)
proc updateItems*(self: View, items: seq[Item]) =
self.accounts.updateItems(items)
proc updateBalance*(self: View, address: string, balance: CurrencyAmount, assetsLoading: bool) =
self.accounts.updateBalance(address, balance, assetsLoading)
proc onAccountRemoved*(self: View, address: string) =
self.accounts.deleteAccount(address)
proc updateAccountsPositions*(self: View, values: Table[string, int]) =
self.accounts.updateAccountsPositions(values)
proc updateAccountHiddenFromTotalBalance*(self: View, address: string, hideFromTotalBalance: bool) =
self.accounts.updateAccountHiddenFromTotalBalance(address, hideFromTotalBalance)
proc deleteAccount*(self: View, address: string) {.slot.} =
self.delegate.deleteAccount(address)

View File

@ -7,6 +7,7 @@ type Filter* = ref object
addresses*: seq[string]
chainIds*: seq[int]
allChainsEnabled*: bool
isDirty*: bool
proc initFilter*(
controller: controller.Controller
@ -16,6 +17,7 @@ proc initFilter*(
result.addresses = @[]
result.chainIds = @[]
result.allChainsEnabled = true
result.isDirty = true
proc `$`*(self: Filter): string =
result = fmt"""WalletFilter(
@ -25,14 +27,17 @@ proc `$`*(self: Filter): string =
proc setAddresses*(self: Filter, addresses: seq[string]) =
self.addresses = addresses
self.isDirty = true
proc setAddress*(self: Filter, address: string) =
self.setAddresses(@[address])
self.isDirty = true
proc removeAddress*(self: Filter, address: string) =
if len(self.addresses) == 1 and self.addresses[0] == address:
let accounts = self.controller.getWalletAccounts()
self.setAddresses(@[accounts[0].address])
self.isDirty = true
return
let ind = self.addresses.find(address)
@ -42,6 +47,7 @@ proc removeAddress*(self: Filter, address: string) =
proc updateNetworks*(self: Filter) =
self.chainIds = self.controller.getEnabledChainIds()
self.allChainsEnabled = (self.chainIds.len == self.controller.getCurrentNetworks().len)
self.isDirty = true
proc load*(self: Filter) =
self.updateNetworks()

View File

@ -221,16 +221,16 @@ method setTotalCurrencyBalance*(self: Module) =
proc notifyModulesOnFilterChanged(self: Module) =
self.overviewModule.filterChanged(self.filter.addresses, self.filter.chainIds)
self.accountsModule.filterChanged(self.filter.addresses, self.filter.chainIds)
self.sendModule.filterChanged(self.filter.addresses, self.filter.chainIds)
self.accountsModule.filterChanged(self.filter.chainIds)
self.sendModule.filterChanged(self.filter.addresses, self.filter.chainIds, self.filter.isDirty)
self.activityController.globalFilterChanged(self.filter.addresses, self.filter.chainIds, self.filter.allChainsEnabled)
self.allTokensModule.filterChanged(self.filter.addresses)
self.allCollectiblesModule.refreshWalletAccounts()
self.assetsModule.filterChanged(self.filter.addresses, self.filter.chainIds)
self.filter.isDirty = false
proc notifyModulesBalanceIsLoaded(self: Module) =
self.overviewModule.filterChanged(self.filter.addresses, self.filter.chainIds)
self.accountsModule.filterChanged(self.filter.addresses, self.filter.chainIds)
proc updateViewWithAddressFilterChanged(self: Module) =
if self.overviewModule.getIsAllAccounts():
@ -289,6 +289,9 @@ method load*(self: Module) =
self.setTotalCurrencyBalance()
self.filter.removeAddress(args.account.address)
self.view.emitWalletAccountRemoved(args.account.address)
if(cmpIgnoreCase(self.view.getAddressFilters(), args.account.address) == 0):
self.setFilterAllAddresses()
else:
self.notifyFilterChanged()
self.events.on(SIGNAL_WALLET_ACCOUNT_NETWORK_ENABLED_UPDATED) do(e:Args):
self.filter.updateNetworks()
@ -397,6 +400,7 @@ proc checkIfModuleDidLoad(self: Module) =
self.filter.setAddresses(self.getWalletAddressesNotHidden())
self.filter.load()
self.notifyFilterChanged()
self.accountsModule.loadAllWalletAccounts()
self.moduleLoaded = true
self.delegate.walletSectionDidLoad()
self.view.setWalletReady()

View File

@ -65,7 +65,7 @@ method onUserAuthenticated*(self: AccessInterface, pin: string, password: string
method setSelectedReceiveAccountIndex*(self: AccessInterface, index: int) {.base.} =
raise newException(ValueError, "No implementation available")
method filterChanged*(self: AccessInterface, addresses: seq[string], chainIds: seq[int]) {.base.} =
method filterChanged*(self: AccessInterface, addresses: seq[string], chainIds: seq[int], isDirty: bool) {.base.} =
raise newException(ValueError, "No implementation available")
method getCollectiblesModel*(self: AccessInterface): collectibles.Model {.base.} =

View File

@ -351,8 +351,8 @@ method suggestedRoutes*(self: Module,
method stopUpdatesForSuggestedRoute*(self: Module) =
self.controller.stopSuggestedRoutesAsyncCalculation()
method filterChanged*(self: Module, addresses: seq[string], chainIds: seq[int]) =
if addresses.len == 0:
method filterChanged*(self: Module, addresses: seq[string], chainIds: seq[int], isDirty: bool) =
if not isDirty or addresses.len == 0:
return
self.view.setSenderAccount(addresses[0])
self.view.setReceiverAccount(addresses[0])

View File

@ -33,8 +33,7 @@ proc walletAccountToWalletAccountItem*(w: WalletAccountDto, keycardAccount: bool
w.hideFromTotalBalance
)
proc walletAccountToWalletAccountsItem*(w: WalletAccountDto, keycardAccount: bool,
chainIds: seq[int], enabledChainIds: seq[int],
proc walletAccountToWalletAccountsItem*(w: WalletAccountDto, isKeycardAccount: bool,
currencyBalance: float64, currencyFormat: CurrencyFormatDto, areTestNetworksEnabled: bool,
marketValuesLoading: bool): wallet_accounts_item.Item =
return wallet_accounts_item.newItem(
@ -48,7 +47,7 @@ proc walletAccountToWalletAccountsItem*(w: WalletAccountDto, keycardAccount: boo
w.keyUid,
w.createdAt,
w.position,
keycardAccount,
isKeycardAccount,
w.assetsLoading or marketValuesLoading,
w.isWallet,
areTestNetworksEnabled,

View File

@ -219,3 +219,7 @@ QtObject:
QtProperty[bool] hideFromTotalBalance:
read = hideFromTotalBalance
notify = hideFromTotalBalanceChanged
proc `hideFromTotalBalance=`*(self: WalletAccountItem, value: bool) {.inline.} =
self.hideFromTotalBalance = value
self.hideFromTotalBalanceChanged()