Do initial balance fetch async

This commit is contained in:
Richard Ramos 2021-01-20 16:04:23 -04:00 committed by Iuri Matias
parent 17477b0c45
commit 81c33fe2af
10 changed files with 124 additions and 56 deletions

View File

@ -30,8 +30,8 @@ proc init*(self: WalletController) =
var accounts = self.status.wallet.accounts
for account in accounts:
self.view.addAccountToList(account)
self.view.setTotalFiatBalance(self.status.wallet.getTotalFiatBalance())
self.view.initBalances()
self.view.setDappBrowserAddress()
self.status.events.on("accountsUpdated") do(e: Args):
@ -40,6 +40,7 @@ proc init*(self: WalletController) =
self.status.events.on("newAccountAdded") do(e: Args):
var account = WalletTypes.AccountArgs(e)
self.view.accounts.addAccountToList(account.account)
self.view.updateView()
self.status.events.on("assetChanged") do(e: Args):
self.view.updateView()
@ -54,6 +55,8 @@ proc init*(self: WalletController) =
for acc in data.accounts:
self.status.wallet.updateAccount(acc)
self.status.wallet.checkPendingTransactions(acc, data.blockNumber)
self.view.updateView()
# TODO: show notification
of "recent-history-fetching":
self.view.setHistoryFetchState(data.accounts, true)

View File

@ -1,4 +1,4 @@
import NimQml, Tables, strformat, strutils, chronicles, json, std/wrapnils, parseUtils, stint, tables, json_serialization
import NimQml, Tables, strformat, strutils, chronicles, sequtils, json, std/wrapnils, parseUtils, stint, tables, json_serialization
import ../../status/[status, wallet, threads]
import ../../status/wallet/collectibles as status_collectibles
import ../../status/libstatus/accounts/constants
@ -348,7 +348,11 @@ QtObject:
self.accountListChanged()
self.currentAccountChanged()
proc addCustomToken*(self: WalletView, address: string, name: string, symbol: string, decimals: string) {.slot.} =
self.status.wallet.addCustomToken(symbol, true, address, name, parseInt(decimals), "")
proc updateView*(self: WalletView) =
self.setTotalFiatBalance(self.status.wallet.getTotalFiatBalance())
self.totalFiatBalanceChanged()
self.currentAccount.assetList.setNewData(self.currentAccount.account.assetList)
self.currentAccountChanged()
@ -356,8 +360,27 @@ QtObject:
self.accounts.forceUpdate()
self.setCurrentAssetList(self.currentAccount.account.assetList)
proc addCustomToken*(self: WalletView, address: string, name: string, symbol: string, decimals: string) {.slot.} =
self.status.wallet.addCustomToken(symbol, true, address, name, parseInt(decimals), "")
proc initBalances*(self: WalletView) =
for acc in self.status.wallet.accounts:
let accountAddress = acc.address
let tokenList = acc.assetList.filter(proc(x:Asset): bool = x.address != "").map(proc(x: Asset): string = x.address)
spawnAndSend(self, "getAccountBalanceSuccess") do:
var tokenBalances = initTable[string, string]()
for token in tokenList:
tokenBalances[token] = getTokenBalance(token, accountAddress)
$ %* {
"address": accountAddress,
"eth": getEthBalance(accountAddress),
"tokens": tokenBalances
}
proc getAccountBalanceSuccess*(self: WalletView, jsonResponse: string) {.slot.} =
let jsonObj = jsonResponse.parseJson()
self.status.wallet.update(jsonObj["address"].getStr(), jsonObj["eth"].getStr(), jsonObj["tokens"])
self.setTotalFiatBalance(self.status.wallet.getTotalFiatBalance())
self.accounts.forceUpdate()
self.currentAccountChanged()
proc loadCollectiblesForAccount*(self: WalletView, address: string, currentCollectiblesList: seq[CollectibleList]) =
if (currentCollectiblesList.len > 0):
@ -523,17 +546,8 @@ QtObject:
QtProperty[QVariant] customTokenList:
read = getCustomTokenList
proc historyWasFetched*(self: WalletView) {.signal.}
proc setHistoryFetchState*(self: WalletView, accounts: seq[string], isFetching: bool) =
for acc in accounts:
self.fetchingHistoryState[acc] = isFetching
if not isFetching: self.historyWasFetched()
proc isFetchingHistory*(self: WalletView, address: string): bool {.slot.} =
if self.fetchingHistoryState.hasKey(address):
return self.fetchingHistoryState[address]
return true
proc isKnownTokenContract*(self: WalletView, address: string): bool {.slot.} =
return self.status.wallet.getKnownTokenContract(parseAddress(address)) != nil
@ -548,6 +562,19 @@ QtObject:
return """{"error":"Unknown token address"}""";
proc historyWasFetched*(self: WalletView) {.signal.}
proc setHistoryFetchState*(self: WalletView, accounts: seq[string], isFetching: bool) =
for acc in accounts:
self.fetchingHistoryState[acc] = isFetching
if not isFetching: self.historyWasFetched()
proc isFetchingHistory*(self: WalletView, address: string): bool {.slot.} =
if self.fetchingHistoryState.hasKey(address):
return self.fetchingHistoryState[address]
return true
proc isHistoryFetched*(self: WalletView, address: string): bool {.slot.} =
return self.currentTransactions.rowCount() > 0

View File

@ -1,4 +1,4 @@
import NimQml, std/wrapnils, strformat
import NimQml, std/wrapnils, strformat, options
from ../../../status/wallet import WalletAccount
import ./asset_list
@ -36,11 +36,21 @@ QtObject:
QtProperty[string] iconColor:
read = iconColor
proc balance*(self: AccountItemView): string {.slot.} = result = ?.self.account.balance
proc balance*(self: AccountItemView): string {.slot.} =
if ?.self.account.balance.isSome:
result = ?.self.account.balance.get()
else:
result = ""
QtProperty[string] balance:
read = balance
proc fiatBalance*(self: AccountItemView): string {.slot.} = result = fmt"{?.self.account.realFiatBalance:>.2f}"
proc fiatBalance*(self: AccountItemView): string {.slot.} =
if ?.self.account.realFiatBalance.isSome:
result = fmt"{?.self.account.realFiatBalance.get():>.2f}"
else:
result = ""
QtProperty[string] fiatBalance:
read = fiatBalance

View File

@ -17,6 +17,7 @@ type
Assets = UserRole + 6
WalletType = UserRole + 7
Wallet = UserRole + 8
Loading = UserRole + 9
QtObject:
type AccountList* = ref object of QAbstractListModel
@ -45,10 +46,10 @@ QtObject:
of "name": result = account.name
of "address": result = account.address
of "iconColor": result = account.iconColor
of "balance": result = account.balance
of "balance": result = if account.balance.isSome(): account.balance.get() else: "..."
of "path": result = account.path
of "walletType": result = account.walletType
of "fiatBalance": result = fmt"{account.realFiatBalance:>.2f}"
of "fiatBalance": result = if account.realFiatBalance.isSome(): fmt"{account.realFiatBalance.get():>.2f}" else: "..."
proc getAccountindexByAddress*(self: AccountList, address: string): int =
var i = 0
@ -91,11 +92,12 @@ QtObject:
of AccountRoles.Name: result = newQVariant(account.name)
of AccountRoles.Address: result = newQVariant(account.address)
of AccountRoles.Color: result = newQVariant(account.iconColor)
of AccountRoles.Balance: result = newQVariant(account.balance)
of AccountRoles.FiatBalance: result = newQVariant(fmt"{account.realFiatBalance:>.2f}")
of AccountRoles.Balance: result = newQVariant(if account.balance.isSome(): account.balance.get() else: "...")
of AccountRoles.FiatBalance: result = newQVariant(if account.realFiatBalance.isSome(): fmt"{account.realFiatBalance.get():>.2f}" else: "...")
of AccountRoles.Assets: result = newQVariant(accountView.assets)
of AccountRoles.WalletType: result = newQVariant(account.walletType)
of AccountRoles.Wallet: result = newQVariant(account.wallet)
of AccountRoles.Loading: result = newQVariant(if account.balance.isSome() and account.realFiatBalance.isSome(): false else: true)
method roleNames(self: AccountList): Table[int, string] =
{ AccountRoles.Name.int:"name",
@ -105,7 +107,8 @@ QtObject:
AccountRoles.FiatBalance.int:"fiatBalance",
AccountRoles.Assets.int:"assets",
AccountRoles.Wallet.int:"isWallet",
AccountRoles.WalletType.int:"walletType" }.toTable
AccountRoles.WalletType.int:"walletType",
AccountRoles.Loading.int:"isLoading" }.toTable
proc addAccountToList*(self: AccountList, account: WalletAccount) =
if account.iconColor == "":

View File

@ -84,7 +84,7 @@ proc validateMnemonic*(mnemonic: string): string =
result = $nim_status.validateMnemonic(mnemonic)
proc startWallet*() =
discard nim_status.startWallet()
discard nim_status.startWallet(true)
proc hex2Token*(input: string, decimals: int): string =
var value = fromHex(Stuint[256], input)

View File

@ -15,6 +15,7 @@ from libstatus/utils as libstatus_utils import eth2Wei, gwei2Wei, first, toUInt6
import wallet/[balance_manager, account, collectibles]
import transactions
import ../eventemitter
import options
export account, collectibles
export Transaction
@ -188,14 +189,23 @@ proc generateAccountConfiguredAssets*(self: WalletModel, accountAddress: string)
proc populateAccount*(self: WalletModel, walletAccount: var WalletAccount, balance: string, refreshCache: bool = false) =
var assets: seq[Asset] = self.generateAccountConfiguredAssets(walletAccount.address)
walletAccount.balance = fmt"{balance} {self.defaultCurrency}"
walletAccount.balance = none[string]()
walletAccount.assetList = assets
walletAccount.realFiatBalance = 0.0
updateBalance(walletAccount, self.getDefaultCurrency(), refreshCache)
walletAccount.realFiatBalance = none[float]()
proc update*(self: WalletModel, address: string, ethBalance: string, tokens: JsonNode) =
for account in self.accounts:
if account.address != address: continue
storeBalances(account, ethBalance, tokens)
updateBalance(account, self.getDefaultCurrency(), false)
proc getEthBalance*(address: string): string =
var balance = getBalance(address)
result = hex2token(balance, 18)
proc newAccount*(self: WalletModel, walletType: string, derivationPath: string, name: string, address: string, iconColor: string, balance: string, publicKey: string): WalletAccount =
var assets: seq[Asset] = self.generateAccountConfiguredAssets(address)
var account = WalletAccount(name: name, path: derivationPath, walletType: walletType, address: address, iconColor: iconColor, balance: fmt"{balance} {self.defaultCurrency}", assetList: assets, realFiatBalance: 0.0, publicKey: publicKey)
var account = WalletAccount(name: name, path: derivationPath, walletType: walletType, address: address, iconColor: iconColor, balance: none[string](), assetList: assets, realFiatBalance: none[float](), publicKey: publicKey)
updateBalance(account, self.getDefaultCurrency())
account
@ -204,19 +214,18 @@ proc initAccounts*(self: WalletModel) =
let accounts = status_wallet.getWalletAccounts()
for account in accounts:
var acc = WalletAccount(account)
self.populateAccount(acc, "")
self.populateAccount(acc, "")
self.accounts.add(acc)
proc updateAccount*(self: WalletModel, address: string) =
for acc in self.accounts.mitems:
if acc.address == address:
self.populateAccount(acc, "", true)
updateBalance(acc, self.getDefaultCurrency(), true)
self.events.emit("accountsUpdated", Args())
proc getTotalFiatBalance*(self: WalletModel): string =
if self.totalBalance == 0.0:
self.calculateTotalFiatBalance()
self.calculateTotalFiatBalance()
fmt"{self.totalBalance:.2f}"
proc convertValue*(self: WalletModel, balance: string, fromCurrency: string, toCurrency: string): float =
@ -225,7 +234,8 @@ proc convertValue*(self: WalletModel, balance: string, fromCurrency: string, toC
proc calculateTotalFiatBalance*(self: WalletModel) =
self.totalBalance = 0.0
for account in self.accounts:
self.totalBalance += account.realFiatBalance
if account.realFiatBalance.isSome:
self.totalBalance += account.realFiatBalance.get()
proc addNewGeneratedAccount(self: WalletModel, generatedAccount: GeneratedAccount, password: string, accountName: string, color: string, accountType: string, isADerivedAccount = true, walletIndex: int = 0): string =
try:

View File

@ -1,5 +1,6 @@
from ../../eventemitter import Args
import ../libstatus/types
import options
type CollectibleList* = ref object
collectibleType*, collectiblesJSON*, error*: string
@ -15,8 +16,9 @@ type Asset* = ref object
name*, symbol*, value*, fiatBalanceDisplay*, fiatBalance*, accountAddress*, address*: string
type WalletAccount* = ref object
name*, address*, iconColor*, balance*, path*, walletType*, publicKey*: string
realFiatBalance*: float
name*, address*, iconColor*, path*, walletType*, publicKey*: string
balance*: Option[string]
realFiatBalance*: Option[float]
assetList*: seq[Asset]
wallet*, chat*: bool
collectiblesLists*: seq[CollectibleList]

View File

@ -4,6 +4,7 @@ import ../libstatus/tokens as status_tokens
import ../libstatus/types as status_types
import ../utils/cache
import account
import options
logScope:
topics = "balance-manager"
@ -69,9 +70,17 @@ proc updateBalance*(account: WalletAccount, currency: string, refreshCache: bool
let eth_balance = getBalance("ETH", account.address, "", refreshCache)
let usd_balance = convertValue(eth_balance, "ETH", currency)
var totalAccountBalance = usd_balance
account.realFiatBalance = totalAccountBalance
account.balance = fmt"{totalAccountBalance:.2f} {currency}"
account.realFiatBalance = some(totalAccountBalance)
account.balance = some(fmt"{totalAccountBalance:.2f} {currency}")
for asset in account.assetList:
updateBalance(asset, currency, refreshCache)
except RpcException:
error "Error in updateBalance", message = getCurrentExceptionMsg()
proc storeBalances*(account: WalletAccount, ethBalance = "0", tokenBalance: JsonNode) =
let ethCacheKey = fmt"ETH-{account.address}-"
balanceManager.tokenBalances.cacheValue(ethCacheKey, ethBalance)
for asset in account.assetList:
if tokenBalance.hasKey(asset.address):
let cacheKey = fmt"{asset.symbol}-{account.address}-{asset.address}"
balanceManager.tokenBalances.cacheValue(cacheKey, tokenBalance{asset.address}.getStr())

View File

@ -134,7 +134,7 @@ Item {
}
StyledText {
id: walletBalance
text: Utils.toLocaleString(fiatBalance, appSettings.locale) + " " + walletModel.defaultCurrency.toUpperCase()
text: isLoading ? "..." : Utils.toLocaleString(fiatBalance, appSettings.locale) + " " + walletModel.defaultCurrency.toUpperCase()
anchors.top: parent.top
anchors.topMargin: Style.current.smallPadding
anchors.right: parent.right

View File

@ -63,25 +63,33 @@ Item {
anchors.topMargin: 0
}
ReceiveModal{
id: receiveModal
selectedAccount: currentAccount
Component {
id: receiveModalComponent
ReceiveModal{
selectedAccount: currentAccount
}
}
SetCurrencyModal{
id: setCurrencyModal
Component {
id: setCurrencyModalComponent
SetCurrencyModal{
}
}
TokenSettingsModal{
id: tokenSettingsModal
Component {
id: tokenSettingsModalComponent
TokenSettingsModal{
}
}
AccountSettingsModal {
id: accountSettingsModal
changeSelectedAccount: walletHeader.changeSelectedAccount
Component {
id: accountSettingsModalComponent
AccountSettingsModal{
changeSelectedAccount: walletHeader.changeSelectedAccount
}
}
AddCustomTokenModal {
AddCustomTokenModal{
id: addCustomTokenModal
}
@ -101,7 +109,7 @@ Item {
imageSource: "../../img/send.svg"
//% "Send"
text: qsTrId("command-button-send")
onClicked: function () {
onClicked: function() {
sendModal.open()
}
}
@ -113,7 +121,7 @@ Item {
//% "Receive"
text: qsTrId("receive")
onClicked: function () {
receiveModal.open()
openPopup(receiveModalComponent);
}
anchors.left: sendBtn.right
anchors.leftMargin: walletMenu.btnOuterMargin
@ -141,9 +149,7 @@ Item {
icon.source: "../../img/manage-wallet.svg"
icon.width: 16
icon.height: 16
onTriggered: {
accountSettingsModal.open()
}
onTriggered: openPopup(accountSettingsModalComponent)
}
Action {
text: qsTr("Manage Assets")
@ -151,7 +157,7 @@ Item {
icon.width: 16
icon.height: 16
onTriggered: {
tokenSettingsModal.open()
openPopup(tokenSettingsModalComponent)
walletModel.loadCustomTokens()
}
}
@ -161,9 +167,7 @@ Item {
icon.source: "../../img/currency.svg"
icon.width: 16
icon.height: 16
onTriggered: {
setCurrencyModal.open()
}
onTriggered: openPopup(setCurrencyModalComponent)
}
}
}