feat(@desktop/wallet): implement unified currency formatting

Fixes #8640
This commit is contained in:
Dario Gabriel Lipicar 2022-12-29 13:44:51 -03:00 committed by dlipicar
parent 00817aedf9
commit 7c4022e4ac
79 changed files with 1121 additions and 455 deletions

View File

@ -10,6 +10,7 @@ import ../../app_service/service/chat/service as chat_service
import ../../app_service/service/community/service as community_service
import ../../app_service/service/message/service as message_service
import ../../app_service/service/token/service as token_service
import ../../app_service/service/currency/service as currency_service
import ../../app_service/service/transaction/service as transaction_service
import ../../app_service/service/collectible/service as collectible_service
import ../../app_service/service/wallet_account/service as wallet_account_service
@ -67,6 +68,7 @@ type
communityService: community_service.Service
messageService: message_service.Service
tokenService: token_service.Service
currencyService: currency_service.Service
transactionService: transaction_service.Service
collectibleService: collectible_service.Service
walletAccountService: wallet_account_service.Service
@ -160,6 +162,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
result.tokenService = token_service.newService(
statusFoundation.events, statusFoundation.threadpool, result.networkService
)
result.currencyService = currency_service.newService(result.tokenService, result.settingsService)
result.collectibleService = collectible_service.newService(statusFoundation.events, statusFoundation.threadpool, result.networkService)
result.walletAccountService = wallet_account_service.newService(
statusFoundation.events, statusFoundation.threadpool, result.settingsService, result.accountsService,
@ -221,6 +224,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
result.communityService,
result.messageService,
result.tokenService,
result.currencyService,
result.transactionService,
result.collectibleService,
result.walletAccountService,
@ -273,6 +277,7 @@ proc delete*(self: AppController) =
self.accountsService.delete
self.chatService.delete
self.communityService.delete
self.currencyService.delete
self.tokenService.delete
self.transactionService.delete
self.collectibleService.delete
@ -352,6 +357,7 @@ proc load(self: AppController) =
self.networkService.init()
self.tokenService.init()
self.currencyService.init()
self.walletAccountService.init()
# Apply runtime log level settings

View File

@ -1,23 +1,31 @@
import sugar, sequtils
import sugar, sequtils, Tables
import io_interface
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../../app_service/service/network/service as network_service
import ../../../../../app_service/service/token/service as token_service
import ../../../../../app_service/service/currency/service as currency_service
type
Controller* = ref object of RootObj
delegate: io_interface.AccessInterface
walletAccountService: wallet_account_service.Service
networkService: network_service.Service
tokenService: token_service.Service
currencyService: currency_service.Service
proc newController*(
delegate: io_interface.AccessInterface,
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
tokenService: token_service.Service,
currencyService: currency_service.Service,
): Controller =
result = Controller()
result.delegate = delegate
result.walletAccountService = walletAccountService
result.networkService = networkService
result.tokenService = tokenService
result.currencyService = currencyService
proc delete*(self: Controller) =
discard
@ -38,4 +46,13 @@ proc getChainIds*(self: Controller): seq[int] =
return self.networkService.getNetworks().map(n => n.chainId)
proc getEnabledChainIds*(self: Controller): seq[int] =
return self.networkService.getNetworks().filter(n => n.enabled).map(n => n.chainId)
return self.networkService.getNetworks().filter(n => n.enabled).map(n => n.chainId)
proc getCurrentCurrency*(self: Controller): string =
return self.walletAccountService.getCurrency()
proc getCurrencyFormat*(self: Controller, symbol: string): CurrencyFormatDto =
return self.currencyService.getCurrencyFormat(symbol)
proc getAllMigratedKeyPairs*(self: Controller): seq[KeyPairDto] =
return self.walletAccountService.getAllMigratedKeyPairs()

View File

@ -1,11 +1,16 @@
import NimQml, Tables, sequtils
import NimQml, Tables, sequtils, sugar
import ../../../../global/global_singleton
import ../../../../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/token/service as token_service
import ../../../../../app_service/service/currency/service as currency_service
import ../../../shared_models/token_model as token_model
import ../../../shared_models/token_item as token_item
import ../../../shared_models/token_utils
import ../../wallet_section/accounts/utils
import ./io_interface, ./view, ./controller
import ../io_interface as delegate_interface
@ -28,57 +33,64 @@ proc newModule*(
events: EventEmitter,
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
tokenService: token_service.Service,
currencyService: currency_service.Service,
): Module =
result = Module()
result.delegate = delegate
result.events = events
result.currentAccountIndex = 0
result.view = newView(result)
result.controller = newController(result, walletAccountService, networkService)
result.controller = newController(result, walletAccountService, networkService, tokenService, currencyService)
result.moduleLoaded = false
method delete*(self: Module) =
self.view.delete
proc setAssets(self: Module, tokens: seq[WalletTokenDto]) =
var items: seq[Item]
let chainIds = self.controller.getChainIds()
let enabledChainIds = self.controller.getEnabledChainIds()
for t in tokens:
let item = token_item.initItem(
t.name,
t.symbol,
t.getBalance(chainIds),
t.getCurrencyBalance(chainIds),
t.getBalance(enabledChainIds),
t.getCurrencyBalance(enabledChainIds),
t.getVisibleForNetwork(enabledChainIds),
t.getVisibleForNetworkWithPositiveBalance(enabledChainIds),
t.getBalances(enabledChainIds),
t.description,
t.assetWebsiteUrl,
t.builtOn,
t.getAddress(),
t.marketCap,
t.highDay,
t.lowDay,
t.changePctHour,
t.changePctDay,
t.changePct24hour,
t.change24hour,
t.currencyPrice,
t.decimals,
)
items.add(item)
let currency = self.controller.getCurrentCurrency()
let currencyFormat = self.controller.getCurrencyFormat(currency)
let items = tokens.map(t => walletTokenToItem(t, chainIds, enabledChainIds, currency, currencyFormat, self.controller.getCurrencyFormat(t.symbol)))
self.view.getAssetsModel().setItems(items)
method switchAccount*(self: Module, accountIndex: int) =
self.currentAccountIndex = accountIndex
let keyPairMigrated = proc(migratedKeyPairs: seq[KeyPairDto], keyUid: string): bool =
for kp in migratedKeyPairs:
if kp.keyUid == keyUid:
return true
return false
let walletAccount = self.controller.getWalletAccount(accountIndex)
let migratedKeyPairs = self.controller.getAllMigratedKeyPairs()
let currency = self.controller.getCurrentCurrency()
let chainIds = self.controller.getChainIds()
let enabledChainIds = self.controller.getEnabledChainIds()
self.view.setData(walletAccount, enabledChainIds)
let tokenFormats = collect(initTable()):
for t in walletAccount.tokens: {t.symbol: self.controller.getCurrencyFormat(t.symbol)}
let currencyFormat = self.controller.getCurrencyFormat(currency)
let accountItem = walletAccountToItem(
walletAccount,
chainIds,
enabledChainIds,
currency,
keyPairMigrated(migratedKeyPairs, walletAccount.keyUid),
currencyFormat,
tokenFormats
)
self.view.setData(accountItem)
self.setAssets(walletAccount.tokens)
method load*(self: Module) =

View File

@ -1,10 +1,11 @@
import NimQml, sequtils, sugar
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ./io_interface
import ../../../shared_models/token_model as token_model
import ../../../shared_models/token_item as token_item
import ../../../shared_models/currency_amount
import ../../wallet_section/accounts/item as account_item
QtObject:
type
@ -17,7 +18,7 @@ QtObject:
publicKey: string
walletType: string
isChat: bool
currencyBalance: float64
currencyBalance: CurrencyAmount
assets: token_model.Model
emoji: string
@ -140,27 +141,27 @@ QtObject:
proc hasGas*(self: View, chainId: int, nativeGasSymbol: string, requiredGas: float): bool {.slot.} =
return self.assets.hasGas(chainId, nativeGasSymbol, requiredGas)
proc getTokenBalanceOnChain*(self: View, chainId: int, tokenSymbol: string): string {.slot.} =
return self.assets.getTokenBalanceOnChain(chainId, tokenSymbol)
# proc getTokenBalanceOnChain*(self: View, chainId: int, tokenSymbol: string): QVariant {.slot.} =
# return newQVariant(self.assets.getTokenBalanceOnChain(chainId, tokenSymbol))
proc setData*(self: View, dto: wallet_account_service.WalletAccountDto, chainIds: seq[int]) =
self.name = dto.name
proc setData*(self: View, item: account_item.Item) =
self.name = item.getName()
self.nameChanged()
self.address = dto.address
self.address = item.getAddress()
self.addressChanged()
self.path = dto.path
self.path = item.getPath()
self.pathChanged()
self.color = dto.color
self.color = item.getColor()
self.colorChanged()
self.publicKey = dto.publicKey
self.publicKey = item.getPublicKey()
self.publicKeyChanged()
self.walletType = dto.walletType
self.walletType = item.getWalletType()
self.walletTypeChanged()
self.isChat = dto.isChat
self.isChat = item.getIsChat()
self.isChatChanged()
self.currencyBalance = dto.getCurrencyBalance(chainIds)
self.currencyBalance = item.getCurrencyBalance()
self.currencyBalanceChanged()
self.emoji = dto.emoji
self.emoji = item.getEmoji()
self.emojiChanged()
proc isAddressCurrentAccount*(self: View, address: string): bool =

View File

@ -14,6 +14,8 @@ import ../../../../app_service/service/network/service as network_service
import ../../../../app_service/service/dapp_permissions/service as dapp_permissions_service
import ../../../../app_service/service/provider/service as provider_service
import ../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../app_service/service/token/service as token_service
import ../../../../app_service/service/currency/service as currency_service
export io_interface
@ -36,7 +38,10 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
networkService: network_service.Service,
dappPermissionsService: dapp_permissions_service.Service,
providerService: provider_service.Service,
walletAccountService: wallet_account_service.Service): Module =
walletAccountService: wallet_account_service.Service,
tokenService: token_service.Service,
currencyService: currency_service.Service
): Module =
result = Module()
result.delegate = delegate
result.events = events
@ -46,7 +51,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
result.providerModule = provider_module.newModule(result, events, settingsService, networkService, providerService)
result.bookmarkModule = bookmark_module.newModule(result, events, bookmarkService)
result.dappsModule = dapps_module.newModule(result, dappPermissionsService, walletAccountService)
result.currentAccountModule = current_account_module.newModule(result, events, walletAccountService, networkService)
result.currentAccountModule = current_account_module.newModule(result, events, walletAccountService, networkService, tokenService, currencyService)
method delete*(self: Module) =
self.view.delete

View File

@ -29,6 +29,7 @@ import ../../../app_service/service/chat/service as chat_service
import ../../../app_service/service/community/service as community_service
import ../../../app_service/service/message/service as message_service
import ../../../app_service/service/token/service as token_service
import ../../../app_service/service/currency/service as currency_service
import ../../../app_service/service/transaction/service as transaction_service
import ../../../app_service/service/collectible/service as collectible_service
import ../../../app_service/service/wallet_account/service as wallet_account_service
@ -109,6 +110,7 @@ proc newModule*[T](
communityService: community_service.Service,
messageService: message_service.Service,
tokenService: token_service.Service,
currencyService: currency_service.Service,
transactionService: transaction_service.Service,
collectibleService: collectible_service.Service,
walletAccountService: wallet_account_service.Service,
@ -168,21 +170,22 @@ proc newModule*[T](
# Submodules
result.channelGroupModules = initOrderedTable[string, chat_section_module.AccessInterface]()
result.walletSectionModule = wallet_section_module.newModule(
result, events, tokenService,
result, events, tokenService, currencyService,
transactionService, collectible_service, walletAccountService,
settingsService, savedAddressService, networkService, accountsService, keycardService
)
result.browserSectionModule = browser_section_module.newModule(
result, events, bookmarkService, settingsService, networkService,
dappPermissionsService, providerService, walletAccountService
dappPermissionsService, providerService, walletAccountService,
tokenService, currencyService
)
result.profileSectionModule = profile_section_module.newModule(
result, events, accountsService, settingsService, stickersService,
profileService, contactsService, aboutService, languageService, privacyService, nodeConfigurationService,
devicesService, mailserversService, chatService, ensService, walletAccountService, generalService, communityService,
networkService, keycardService, keychainService
networkService, keycardService, keychainService, tokenService
)
result.stickersModule = stickers_module.newModule(result, events, stickersService, settingsService, walletAccountService, networkService)
result.stickersModule = stickers_module.newModule(result, events, stickersService, settingsService, walletAccountService, networkService, tokenService)
result.activityCenterModule = activity_center_module.newModule(result, events, activityCenterService, contactsService,
messageService, chatService)
result.communitiesModule = communities_module.newModule(result, events, communityService, contactsService)

View File

@ -7,7 +7,7 @@ import ../../../../../app_service/service/settings/service as settings_service
import ../../../../../app_service/service/ens/service as ens_service
import ../../../../../app_service/service/network/service as network_service
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../../app_service/service/token/dto
import ../../../../../app_service/service/token/service as token_service
import ../../../shared_modules/keycard_popup/io_interface as keycard_shared_module
logScope:
@ -23,11 +23,13 @@ type
ensService: ens_service.Service
networkService: network_service.Service
walletAccountService: wallet_account_service.Service
tokenService: token_service.Service
proc newController*(
delegate: io_interface.AccessInterface, events: EventEmitter,
settingsService: settings_service.Service, ensService: ens_service.Service,
walletAccountService: wallet_account_service.Service, networkService: network_service.Service,
tokenService: token_service.Service
): Controller =
result = Controller()
result.delegate = delegate
@ -36,6 +38,7 @@ proc newController*(
result.ensService = ensService
result.walletAccountService = walletAccountService
result.networkService = networkService
result.tokenService = tokenService
proc delete*(self: Controller) =
discard
@ -135,7 +138,7 @@ proc getCurrentCurrency*(self: Controller): string =
return self.settingsService.getCurrency()
proc getPrice*(self: Controller, crypto: string, fiat: string): float64 =
return self.walletAccountService.getPrice(crypto, fiat)
return self.tokenService.getTokenPrice(crypto, fiat)
proc getStatusToken*(self: Controller): string =
let token = self.ensService.getStatusToken()

View File

@ -12,6 +12,7 @@ import ../../../../../app_service/service/ens/service as ens_service
import ../../../../../app_service/service/network/service as network_service
import ../../../../../app_service/service/ens/utils as ens_utils
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../../app_service/service/token/service as token_service
export io_interface
@ -49,12 +50,13 @@ proc newModule*(
settingsService: settings_service.Service, ensService: ens_service.Service,
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
tokenService: token_service.Service,
): Module =
result = Module()
result.delegate = delegate
result.view = view.newView(result)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events, settingsService, ensService, walletAccountService, networkService)
result.controller = controller.newController(result, events, settingsService, ensService, walletAccountService, networkService, tokenService)
result.moduleLoaded = false
method delete*(self: Module) =

View File

@ -22,6 +22,7 @@ import ../../../../app_service/service/general/service as general_service
import ../../../../app_service/service/community/service as community_service
import ../../../../app_service/service/keycard/service as keycard_service
import ../../../../app_service/service/keychain/service as keychain_service
import ../../../../app_service/service/token/service as token_service
import ./profile/module as profile_module
import ./contacts/module as contacts_module
@ -79,7 +80,8 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
communityService: community_service.Service,
networkService: network_service.Service,
keycardService: keycard_service.Service,
keychainService: keychain_service.Service
keychainService: keychain_service.Service,
tokenService: token_service.Service
): Module =
result = Module()
result.delegate = delegate
@ -98,7 +100,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
result.syncModule = sync_module.newModule(result, events, settingsService, nodeConfigurationService, mailserversService)
result.notificationsModule = notifications_module.newModule(result, events, settingsService, chatService, contactsService)
result.ensUsernamesModule = ens_usernames_module.newModule(
result, events, settingsService, ensService, walletAccountService, networkService
result, events, settingsService, ensService, walletAccountService, networkService, tokenService
)
result.communitiesModule = communities_module.newModule(result, communityService)
result.keycardModule = keycard_module.newModule(result, events, keycardService, settingsService, privacyService,

View File

@ -10,6 +10,7 @@ import ../../../../app_service/service/settings/service as settings_service
import ../../../../app_service/service/network/service as network_service
import ../../../../app_service/service/eth/utils as eth_utils
import ../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../app_service/service/token/service as token_service
import ../../shared_modules/keycard_popup/io_interface as keycard_shared_module
const UNIQUE_BUY_STICKER_TRANSACTION_MODULE_IDENTIFIER* = "StickersSection-TransactionModule"
@ -22,6 +23,7 @@ type
settingsService: settings_service.Service
networkService: network_service.Service
walletAccountService: wallet_account_service.Service
tokenService: token_service.Service
disconnected: bool
# Forward declaration
@ -35,6 +37,7 @@ proc newController*(
settingsService: settings_service.Service,
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
tokenService: token_service.Service,
): Controller =
result = Controller()
result.delegate = delegate
@ -43,6 +46,7 @@ proc newController*(
result.settingsService = settingsService
result.networkService = networkService
result.walletAccountService = walletAccountService
result.tokenService = tokenService
result.disconnected = false
proc delete*(self: Controller) =
@ -154,7 +158,7 @@ proc getCurrentCurrency*(self: Controller): string =
return self.settingsService.getCurrency()
proc getPrice*(self: Controller, crypto: string, fiat: string): float64 =
return self.walletAccountService.getPrice(crypto, fiat)
return self.tokenService.getTokenPrice(crypto, fiat)
proc getChainIdForStickers*(self: Controller): int =
return self.networkService.getNetworkForStickers().chainId

View File

@ -8,6 +8,7 @@ import ../../../../app_service/service/settings/service as settings_service
import ../../../../app_service/service/network/service as network_service
import ../../../../app_service/common/conversion as service_conversion
import ../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../app_service/service/token/service as token_service
export io_interface
@ -40,12 +41,13 @@ proc newModule*(
settingsService: settings_Service.Service,
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
tokenService: token_service.Service,
): Module =
result = Module()
result.delegate = delegate
result.view = newView(result)
result.viewVariant = newQVariant(result.view)
result.controller = controller.newController(result, events, stickersService, settingsService, walletAccountService, networkService)
result.controller = controller.newController(result, events, stickersService, settingsService, walletAccountService, networkService, tokenService)
result.moduleLoaded = false
singletonInstance.engine.setRootContextProperty("stickersModule", result.viewVariant)

View File

@ -1,5 +1,7 @@
import strformat
import ../../../shared_models/currency_amount
type
Item* = object
name: string
@ -10,7 +12,7 @@ type
walletType: string
isWallet: bool
isChat: bool
currencyBalance: float64
currencyBalance: CurrencyAmount
emoji: string
derivedfrom: string
@ -23,7 +25,7 @@ proc initItem*(
walletType: string,
isWallet: bool,
isChat: bool,
currencyBalance: float64,
currencyBalance: CurrencyAmount,
emoji: string,
derivedfrom: string
): Item =
@ -81,7 +83,7 @@ proc getIsWallet*(self: Item): bool =
proc getIsChat*(self: Item): bool =
return self.isChat
proc getCurrencyBalance*(self: Item): float64 =
proc getCurrencyBalance*(self: Item): CurrencyAmount =
return self.currencyBalance
proc getDerivedFrom*(self: Item): string =

View File

@ -1,8 +1,11 @@
import sugar, sequtils
import sugar, sequtils, tables
import io_interface
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../../app_service/service/accounts/service as accounts_service
import ../../../../../app_service/service/network/service as network_service
import ../../../../../app_service/service/token/service as token_service
import ../../../../../app_service/service/currency/service as currency_service
import ../../../../../app_service/service/currency/dto as currency_dto
import ../../../../global/global_singleton
import ../../../shared_modules/keycard_popup/io_interface as keycard_shared_module
@ -19,6 +22,8 @@ type
walletAccountService: wallet_account_service.Service
accountsService: accounts_service.Service
networkService: network_service.Service
tokenService: token_service.Service
currencyService: currency_service.Service
proc newController*(
delegate: io_interface.AccessInterface,
@ -26,6 +31,8 @@ proc newController*(
walletAccountService: wallet_account_service.Service,
accountsService: accounts_service.Service,
networkService: network_service.Service,
tokenService: token_service.Service,
currencyService: currency_service.Service,
): Controller =
result = Controller()
result.delegate = delegate
@ -33,6 +40,8 @@ proc newController*(
result.walletAccountService = walletAccountService
result.accountsService = accountsService
result.networkService = networkService
result.tokenService = tokenService
result.currencyService = currencyService
proc delete*(self: Controller) =
discard
@ -112,3 +121,9 @@ proc getChainIds*(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 =
return self.walletAccountService.getCurrency()
proc getCurrencyFormat*(self: Controller, symbol: string): CurrencyFormatDto =
return self.currencyService.getCurrencyFormat(symbol)

View File

@ -1,44 +1,50 @@
import strformat
import ../../../shared_models/token_model as token_model
import ../../../shared_models/currency_amount
import ./compact_model as compact_model
type
Item* = object
name: string
address: string
mixedCaseAddress: string
path: string
color: string
publicKey: string
walletType: string
isWallet: bool
isChat: bool
currencyBalance: float64
currencyBalance: CurrencyAmount
assets: token_model.Model
emoji: string
derivedfrom: string
relatedAccounts: compact_model.Model
keyUid: string
migratedToKeycard: bool
ens: string
proc initItem*(
name: string,
address: string,
mixedCaseAddress: string,
path: string,
color: string,
publicKey: string,
walletType: string,
isWallet: bool,
isChat: bool,
currencyBalance: float64,
currencyBalance: CurrencyAmount,
assets: token_model.Model,
emoji: string,
derivedfrom: string,
relatedAccounts: compact_model.Model,
keyUid: string,
migratedToKeycard: bool
migratedToKeycard: bool,
ens: string
): Item =
result.name = name
result.address = address
result.mixedCaseAddress = mixedCaseAddress
result.path = path
result.color = color
result.publicKey = publicKey
@ -52,11 +58,13 @@ proc initItem*(
result.relatedAccounts = relatedAccounts
result.keyUid = keyUid
result.migratedToKeycard = migratedToKeycard
result.ens = ens
proc `$`*(self: Item): string =
result = fmt"""WalletAccountItem(
name: {self.name},
address: {self.address},
mixedCaseAddress: {self.mixedCaseAddress},
path: {self.path},
color: {self.color},
publicKey: {self.publicKey},
@ -69,7 +77,8 @@ proc `$`*(self: Item): string =
derivedfrom: {self.derivedfrom},
relatedAccounts: {self.relatedAccounts}
keyUid: {self.keyUid},
migratedToKeycard: {self.migratedToKeycard}
migratedToKeycard: {self.migratedToKeycard},
ens: {self.ens}
]"""
proc getName*(self: Item): string =
@ -78,6 +87,9 @@ proc getName*(self: Item): string =
proc getAddress*(self: Item): string =
return self.address
proc getMixedCaseAddress*(self: Item): string =
return self.mixedCaseAddress
proc getPath*(self: Item): string =
return self.path
@ -99,7 +111,7 @@ proc getIsWallet*(self: Item): bool =
proc getIsChat*(self: Item): bool =
return self.isChat
proc getCurrencyBalance*(self: Item): float64 =
proc getCurrencyBalance*(self: Item): CurrencyAmount =
return self.currencyBalance
proc getAssets*(self: Item): token_model.Model =
@ -116,3 +128,6 @@ proc getKeyUid*(self: Item): string =
proc getMigratedToKeycard*(self: Item): bool =
return self.migratedToKeycard
proc getEns*(self: Item): string =
return self.ens

View File

@ -1,6 +1,6 @@
import tables, NimQml, sequtils, sugar, chronicles
import ./io_interface, ./view, ./item, ./controller
import ./io_interface, ./view, ./item, ./controller, ./utils
import ../io_interface as delegate_interface
import ../../../../global/global_singleton
import ../../../../core/eventemitter
@ -9,6 +9,8 @@ import ../../../../../app_service/service/keycard/service as keycard_service
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../../app_service/service/accounts/service as accounts_service
import ../../../../../app_service/service/network/service as network_service
import ../../../../../app_service/service/token/service as token_service
import ../../../../../app_service/service/currency/service as currency_service
import ../../../shared_models/token_model as token_model
import ../../../shared_models/token_item as token_item
import ../../../shared_modules/keycard_popup/module as keycard_shared_module
@ -43,7 +45,9 @@ proc newModule*(
keycardService: keycard_service.Service,
walletAccountService: wallet_account_service.Service,
accountsService: accounts_service.Service,
networkService: network_service.Service
networkService: network_service.Service,
tokenService: token_service.Service,
currencyService: currency_service.Service
): Module =
result = Module()
result.delegate = delegate
@ -52,7 +56,7 @@ proc newModule*(
result.accountsService = accountsService
result.walletAccountService = walletAccountService
result.view = newView(result)
result.controller = controller.newController(result, events, walletAccountService, accountsService, networkService)
result.controller = controller.newController(result, events, walletAccountService, accountsService, networkService, tokenService, currencyService)
result.moduleLoaded = false
method delete*(self: Module) =
@ -70,73 +74,27 @@ method refreshWalletAccounts*(self: Module) =
let walletAccounts = self.controller.getWalletAccounts()
let migratedKeyPairs = self.controller.getAllMigratedKeyPairs()
let currency = self.controller.getCurrentCurrency()
let chainIds = self.controller.getChainIds()
let enabledChainIds = self.controller.getEnabledChainIds()
let currencyFormat = self.controller.getCurrencyFormat(currency)
let items = walletAccounts.map(proc (w: WalletAccountDto): item.Item =
let assets = token_model.newModel()
assets.setItems(
w.tokens.map(t => token_item.initItem(
t.name,
t.symbol,
t.getBalance(chainIds),
t.getCurrencyBalance(chainIds),
t.getBalance(enabledChainIds),
t.getCurrencyBalance(enabledChainIds),
t.getVisibleForNetwork(enabledChainIds),
t.getVisibleForNetworkWithPositiveBalance(enabledChainIds),
t.getBalances(enabledChainIds),
t.description,
t.assetWebsiteUrl,
t.builtOn,
t.getAddress(),
t.marketCap,
t.highDay,
t.lowDay,
t.changePctHour,
t.changePctDay,
t.changePct24hour,
t.change24hour,
t.currencyPrice,
t.decimals,
))
let items = walletAccounts.map(w => (block:
let tokenFormats = collect(initTable()):
for t in w.tokens: {t.symbol: self.controller.getCurrencyFormat(t.symbol)}
walletAccountToItem(
w,
chainIds,
enabledChainIds,
currency,
keyPairMigrated(migratedKeyPairs, w.keyUid),
currencyFormat,
tokenFormats
)
let relatedAccounts = compact_model.newModel()
relatedAccounts.setItems(
w.relatedAccounts.map(x => compact_item.initItem(
x.name,
x.address,
x.path,
x.color,
x.publicKey,
x.walletType,
x.isWallet,
x.isChat,
x.getCurrencyBalance(enabledChainIds),
x.emoji,
x.derivedfrom,
))
)
result = initItem(
w.name,
w.address,
w.path,
w.color,
w.publicKey,
w.walletType,
w.isWallet,
w.isChat,
w.getCurrencyBalance(enabledChainIds),
assets,
w.emoji,
w.derivedfrom,
relatedAccounts,
w.keyUid,
keyPairMigrated(migratedKeyPairs, w.keyUid)
))
))
self.view.setItems(items)

View File

@ -0,0 +1,68 @@
import tables, sequtils, sugar
import ./item
import ../../../../../app_service/service/wallet_account/dto
import ../../../../../app_service/service/token/dto as token_dto
import ../../../../../app_service/service/currency/dto as currency_dto
import ../../../shared_models/token_model as token_model
import ../../../shared_models/token_item as token_item
import ../../../shared_models/token_utils
import ../../../shared_models/currency_amount
import ../../../shared_models/currency_amount_utils
import ./compact_item as compact_item
import ./compact_model as compact_model
proc walletAccountToCompactItem*(w: WalletAccountDto, enabledChainIds: seq[int], currency: string, currencyFormat: CurrencyFormatDto) : compact_item.Item =
return compact_item.initItem(
w.name,
w.address,
w.path,
w.color,
w.publicKey,
w.walletType,
w.isWallet,
w.isChat,
currencyAmountToItem(w.getCurrencyBalance(enabledChainIds, currency), currencyFormat),
w.emoji,
w.derivedfrom)
proc walletAccountToItem*(
w: WalletAccountDto,
chainIds: seq[int],
enabledChainIds: seq[int],
currency: string,
keyPairMigrated: bool,
currencyFormat: CurrencyFormatDto,
tokenFormats: Table[string, CurrencyFormatDto],
) : item.Item =
let assets = token_model.newModel()
assets.setItems(
w.tokens.map(t => walletTokenToItem(t, chainIds, enabledChainIds, currency, currencyFormat, tokenFormats[t.symbol]))
)
let relatedAccounts = compact_model.newModel()
relatedAccounts.setItems(
w.relatedAccounts.map(x => walletAccountToCompactItem(x, enabledChainIds, currency, currencyFormat))
)
result = initItem(
w.name,
w.address,
w.mixedCaseAddress,
w.path,
w.color,
w.publicKey,
w.walletType,
w.isWallet,
w.isChat,
currencyAmountToItem(w.getCurrencyBalance(enabledChainIds, currency), currencyFormat),
assets,
w.emoji,
w.derivedfrom,
relatedAccounts,
w.keyUid,
keyPairMigrated,
w.ens
)

View File

@ -1,22 +1,29 @@
import io_interface
import ../../../../app_service/service/settings/service as settings_service
import ../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../app_service/service/currency/service as currency_service
import ../../shared_models/currency_amount
import ../../shared_models/currency_amount_utils
type
Controller* = ref object of RootObj
delegate: io_interface.AccessInterface
settingsService: settings_service.Service
walletAccountService: wallet_account_service.Service
currencyService: currency_service.Service
proc newController*(
delegate: io_interface.AccessInterface,
settingsService: settings_service.Service,
walletAccountService: wallet_account_service.Service,
currencyService: currency_service.Service,
): Controller =
result = Controller()
result.delegate = delegate
result.settingsService = settingsService
result.walletAccountService = walletAccountService
result.currencyService = currencyService
proc delete*(self: Controller) =
discard
@ -33,8 +40,8 @@ proc getSigningPhrase*(self: Controller): string =
proc isMnemonicBackedUp*(self: Controller): bool =
return self.settingsService.getMnemonic().len > 0
proc getCurrencyBalance*(self: Controller): float64 =
return self.walletAccountService.getTotalCurrencyBalance()
proc getCurrencyBalance*(self: Controller): CurrencyAmount =
return currencyAmountToItem(self.walletAccountService.getTotalCurrencyBalance(), self.currencyService.getCurrencyFormat(self.getCurrency()))
proc updateCurrency*(self: Controller, currency: string) =
self.walletAccountService.updateCurrency(currency)

View File

@ -1,24 +1,31 @@
import sugar, sequtils
import sugar, sequtils, Tables
import io_interface
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../../app_service/service/network/service as network_service
import ../../../../../app_service/service/token/service as token_service
import ../../../../../app_service/service/currency/service as currency_service
type
Controller* = ref object of RootObj
delegate: io_interface.AccessInterface
walletAccountService: wallet_account_service.Service
networkService: network_service.Service
tokenService: token_service.Service
currencyService: currency_service.Service
proc newController*(
delegate: io_interface.AccessInterface,
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
tokenService: token_service.Service,
currencyService: currency_service.Service,
): Controller =
result = Controller()
result.delegate = delegate
result.walletAccountService = walletAccountService
result.networkService = networkService
result.tokenService = tokenService
result.currencyService = currencyService
proc delete*(self: Controller) =
discard
@ -39,4 +46,13 @@ proc getChainIds*(self: Controller): seq[int] =
return self.networkService.getNetworks().map(n => n.chainId)
proc getEnabledChainIds*(self: Controller): seq[int] =
return self.networkService.getNetworks().filter(n => n.enabled).map(n => n.chainId)
return self.networkService.getNetworks().filter(n => n.enabled).map(n => n.chainId)
proc getCurrentCurrency*(self: Controller): string =
return self.walletAccountService.getCurrency()
proc getCurrencyFormat*(self: Controller, symbol: string): CurrencyFormatDto =
return self.currencyService.getCurrencyFormat(symbol)
proc getAllMigratedKeyPairs*(self: Controller): seq[KeyPairDto] =
return self.walletAccountService.getAllMigratedKeyPairs()

View File

@ -1,11 +1,18 @@
import NimQml, Tables, sequtils
import NimQml, Tables, sequtils, sugar
import ../../../../global/global_singleton
import ../../../../core/eventemitter
import ../../../../../app_service/service/token/service as token_service
import ../../../../../app_service/service/currency/service as currency_service
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../../app_service/service/network/service as network_service
import ../../../shared_models/currency_amount_utils
import ../../../shared_models/token_model as token_model
import ../../../shared_models/token_item as token_item
import ../../../shared_models/token_utils
import ../accounts/compact_item as account_compact_item
import ../accounts/item as account_item
import ../accounts/utils
import ./io_interface, ./view, ./controller
import ../io_interface as delegate_interface
@ -28,13 +35,15 @@ proc newModule*(
events: EventEmitter,
walletAccountService: wallet_account_service.Service,
networkService: network_service.Service,
tokenService: token_service.Service,
currencyService: currency_service.Service,
): Module =
result = Module()
result.delegate = delegate
result.events = events
result.currentAccountIndex = 0
result.view = newView(result)
result.controller = newController(result, walletAccountService, networkService)
result.controller = newController(result, walletAccountService, networkService, tokenService, currencyService)
result.moduleLoaded = false
method delete*(self: Module) =
@ -71,49 +80,68 @@ method viewDidLoad*(self: Module) =
self.delegate.currentAccountModuleDidLoad()
proc setAssetsAndBalance(self: Module, tokens: seq[WalletTokenDto]) =
var totalCurrencyBalanceForAllAssets = 0.0
let chainIds = self.controller.getChainIds()
let enabledChainIds = self.controller.getEnabledChainIds()
var items: seq[Item]
for t in tokens:
let item = token_item.initItem(
t.name,
t.symbol,
t.getBalance(chainIds),
t.getCurrencyBalance(chainIds),
t.getBalance(enabledChainIds),
t.getCurrencyBalance(enabledChainIds),
t.getVisibleForNetwork(enabledChainIds),
t.getVisibleForNetworkWithPositiveBalance(enabledChainIds),
t.getBalances(enabledChainIds),
t.description,
t.assetWebsiteUrl,
t.builtOn,
t.getAddress(),
t.marketCap,
t.highDay,
t.lowDay,
t.changePctHour,
t.changePctDay,
t.changePct24hour,
t.change24hour,
t.currencyPrice,
t.decimals,
)
items.add(item)
totalCurrencyBalanceForAllAssets += t.getCurrencyBalance(enabledChainIds)
let currency = self.controller.getCurrentCurrency()
let currencyFormat = self.controller.getCurrencyFormat(currency)
let items = tokens.map(t => walletTokenToItem(t, chainIds, enabledChainIds, currency, currencyFormat, self.controller.getCurrencyFormat(t.symbol)))
let totalCurrencyBalanceForAllAssets = tokens.map(t => t.getCurrencyBalance(enabledChainIds, currency)).foldl(a + b, 0.0)
self.view.getAssetsModel().setItems(items)
self.view.setCurrencyBalance(totalCurrencyBalanceForAllAssets)
self.view.setCurrencyBalance(currencyAmountToItem(totalCurrencyBalanceForAllAssets, currencyFormat))
method switchAccount*(self: Module, accountIndex: int) =
self.currentAccountIndex = accountIndex
let enabledChainIds = self.controller.getEnabledChainIds()
let keyPairMigrated = proc(migratedKeyPairs: seq[KeyPairDto], keyUid: string): bool =
for kp in migratedKeyPairs:
if kp.keyUid == keyUid:
return true
return false
let defaultAccount = self.controller.getWalletAccount(0) # can safely do this as the account will always contain atleast one account
let walletAccount = self.controller.getWalletAccount(accountIndex)
# can safely do this as the account will always contain atleast one account
self.view.setDefaultWalletAccount(self.controller.getWalletAccount(0))
self.view.setData(walletAccount, enabledChainIds)
let migratedKeyPairs = self.controller.getAllMigratedKeyPairs()
let currency = self.controller.getCurrentCurrency()
let chainIds = self.controller.getChainIds()
let enabledChainIds = self.controller.getEnabledChainIds()
let defaultAccountTokenFormats = collect(initTable()):
for t in defaultAccount.tokens: {t.symbol: self.controller.getCurrencyFormat(t.symbol)}
let accountTokenFormats = collect(initTable()):
for t in walletAccount.tokens: {t.symbol: self.controller.getCurrencyFormat(t.symbol)}
let currencyFormat = self.controller.getCurrencyFormat(currency)
let defaultAccountItem = walletAccountToItem(
defaultAccount,
chainIds,
enabledChainIds,
currency,
keyPairMigrated(migratedKeyPairs, defaultAccount.keyUid),
currencyFormat,
defaultAccountTokenFormats
)
let accountItem = walletAccountToItem(
walletAccount,
chainIds,
enabledChainIds,
currency,
keyPairMigrated(migratedKeyPairs, walletAccount.keyUid),
currencyFormat,
accountTokenFormats
)
self.view.setDefaultWalletAccount(defaultAccountItem)
self.view.setData(accountItem)
self.setAssetsAndBalance(walletAccount.tokens)
method update*(self: Module, address: string, accountName: string, color: string, emoji: string) =

View File

@ -1,12 +1,14 @@
import NimQml, sequtils, sugar
import NimQml, sequtils, sugar, json
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ./io_interface
import ../../../shared_models/token_model as token_model
import ../../../shared_models/token_item as token_item
import ../../../shared_models/currency_amount
import ../accounts/compact_model
import ../accounts/compact_item
import ../accounts/item as account_item
const GENERATED = "generated"
const GENERATED_FROM_IMPORTED = "generated from imported accounts"
@ -14,7 +16,7 @@ QtObject:
type
View* = ref object of QObject
delegate: io_interface.AccessInterface
defaultAccount: wallet_account_service.WalletAccountDto
defaultAccount: account_item.Item
name: string
address: string
mixedcaseAddress: string
@ -23,7 +25,7 @@ QtObject:
publicKey: string
walletType: string
isChat: bool
currencyBalance: float64
currencyBalance: CurrencyAmount
assets: token_model.Model
emoji: string
derivedfrom: string
@ -117,7 +119,7 @@ QtObject:
proc currencyBalanceChanged(self: View) {.signal.}
proc getCurrencyBalance*(self: View): QVariant {.slot.} =
return newQVariant(self.currencyBalance)
proc setCurrencyBalance*(self: View, value: float) =
proc setCurrencyBalance*(self: View, value: CurrencyAmount) =
self.currencyBalance = value
self.currencyBalanceChanged()
QtProperty[QVariant] currencyBalance:
@ -173,66 +175,50 @@ QtObject:
proc update(self: View, address: string, accountName: string, color: string, emoji: string) {.slot.} =
self.delegate.update(address, accountName, color, emoji)
proc setDefaultWalletAccount*(self: View, default: wallet_account_service.WalletAccountDto) =
proc setDefaultWalletAccount*(self: View, default: account_item.Item) =
self.defaultAccount = default
proc setData*(self: View, dto: wallet_account_service.WalletAccountDto, chainIds: seq[int]) =
if(self.name != dto.name):
self.name = dto.name
proc setData*(self: View, item: account_item.Item) =
if(self.name != item.getName()):
self.name = item.getName()
self.nameChanged()
if(self.address != dto.address):
self.address = dto.address
if(self.address != item.getAddress()):
self.address = item.getAddress()
self.addressChanged()
if(self.mixedcaseAddress != dto.mixedcaseAddress):
self.mixedcaseAddress = dto.mixedcaseAddress
if(self.mixedcaseAddress != item.getMixedCaseAddress()):
self.mixedcaseAddress = item.getMixedCaseAddress()
self.mixedcaseAddressChanged()
if(self.path != dto.path):
self.path = dto.path
if(self.path != item.getPath()):
self.path = item.getPath()
self.pathChanged()
if(self.color != dto.color):
self.color = dto.color
if(self.color != item.getColor()):
self.color = item.getColor()
self.colorChanged()
if(self.publicKey != dto.publicKey):
self.publicKey = dto.publicKey
if(self.publicKey != item.getPublicKey()):
self.publicKey = item.getPublicKey()
self.publicKeyChanged()
# Check if the account is generated from default wallet account else change wallettype
if dto.walletType == GENERATED and dto.derivedfrom != self.defaultAccount.derivedfrom:
if item.getWalletType() == GENERATED and item.getDerivedfrom() != self.defaultAccount.getDerivedfrom():
self.walletType = GENERATED_FROM_IMPORTED
self.walletTypeChanged()
else:
if(self.walletType != dto.walletType):
self.walletType = dto.walletType
if(self.walletType != item.getWalletType()):
self.walletType = item.getWalletType()
self.walletTypeChanged()
if(self.isChat != dto.isChat):
self.isChat = dto.isChat
if(self.isChat != item.getIsChat()):
self.isChat = item.getIsChat()
self.isChatChanged()
if(self.emoji != dto.emoji):
self.emoji = dto.emoji
if(self.emoji != item.getEmoji()):
self.emoji = item.getEmoji()
self.emojiChanged()
if(self.derivedfrom != dto.derivedfrom):
self.derivedfrom = dto.derivedfrom
if(self.derivedfrom != item.getDerivedFrom()):
self.derivedfrom = item.getDerivedFrom()
self.derivedfromChanged()
if(self.ens != dto.ens):
self.ens = dto.ens
if(self.ens != item.getEns()):
self.ens = item.getEns()
self.ensChanged()
# Set related accounts
let relatedAccounts = compact_model.newModel()
relatedAccounts.setItems(
dto.relatedAccounts.map(x => compact_item.initItem(
x.name,
x.address,
x.path,
x.color,
x.publicKey,
x.walletType,
x.isWallet,
x.isChat,
x.getCurrencyBalance(chainIds),
x.emoji,
x.derivedfrom
))
)
self.relatedAccounts = relatedAccounts
self.relatedAccounts = item.getRelatedAccounts()
self.relatedAccountsChanged()
proc findTokenSymbolByAddress*(self: View, address: string): string {.slot.} =
@ -241,5 +227,9 @@ QtObject:
proc hasGas*(self: View, chainId: int, nativeGasSymbol: string, requiredGas: float): bool {.slot.} =
return self.assets.hasGas(chainId, nativeGasSymbol, requiredGas)
proc getTokenBalanceOnChain*(self: View, chainId: int, tokenSymbol: string): string {.slot.} =
return self.assets.getTokenBalanceOnChain(chainId, tokenSymbol)
# Returning a QVariant from a slot with parameters other than "self" won't compile
#proc getTokenBalanceOnChain*(self: View, chainId: int, tokenSymbol: string): QVariant {.slot.} =
# return newQVariant(self.assets.getTokenBalanceOnChain(chainId, tokenSymbol))
proc getTokenBalanceOnChainAsJson*(self: View, chainId: int, tokenSymbol: string): string {.slot.} =
return $self.assets.getTokenBalanceOnChain(chainId, tokenSymbol).toJsonNode()

View File

@ -16,6 +16,7 @@ import ../../../global/global_singleton
import ../../../core/eventemitter
import ../../../../app_service/service/keycard/service as keycard_service
import ../../../../app_service/service/token/service as token_service
import ../../../../app_service/service/currency/service as currency_service
import ../../../../app_service/service/transaction/service as transaction_service
import ../../../../app_service/service/collectible/service as collectible_service
import ../../../../app_service/service/wallet_account/service as wallet_account_service
@ -48,6 +49,7 @@ proc newModule*(
delegate: delegate_interface.AccessInterface,
events: EventEmitter,
tokenService: token_service.Service,
currencyService: currency_service.Service,
transactionService: transaction_service.Service,
collectibleService: collectible_service.Service,
walletAccountService: wallet_account_service.Service,
@ -61,13 +63,13 @@ proc newModule*(
result.delegate = delegate
result.events = events
result.moduleLoaded = false
result.controller = newController(result, settingsService, walletAccountService)
result.controller = newController(result, settingsService, walletAccountService, currencyService)
result.view = newView(result)
result.accountsModule = accounts_module.newModule(result, events, keycardService, walletAccountService, accountsService, networkService)
result.accountsModule = accounts_module.newModule(result, events, keycardService, walletAccountService, accountsService, networkService, tokenService, currencyService)
result.allTokensModule = all_tokens_module.newModule(result, events, tokenService, walletAccountService)
result.collectiblesModule = collectibles_module.newModule(result, events, collectibleService, walletAccountService, networkService)
result.currentAccountModule = current_account_module.newModule(result, events, walletAccountService, networkService)
result.currentAccountModule = current_account_module.newModule(result, events, walletAccountService, networkService, tokenService, currencyService)
result.transactionsModule = transactions_module.newModule(result, events, transactionService, walletAccountService, networkService)
result.savedAddressesModule = saved_addresses_module.newModule(result, events, savedAddressService)
result.buySellCryptoModule = buy_sell_crypto_module.newModule(result, events, transactionService)

View File

@ -1,13 +1,14 @@
import NimQml
import ./io_interface
import ../../shared_models/currency_amount
QtObject:
type
View* = ref object of QObject
delegate: io_interface.AccessInterface
currentCurrency: string
totalCurrencyBalance: float64
totalCurrencyBalance: CurrencyAmount
signingPhrase: string
isMnemonicBackedUp: bool
@ -66,7 +67,7 @@ QtObject:
proc switchAccountByAddress(self: View, address: string) {.slot.} =
self.delegate.switchAccountByAddress(address)
proc setTotalCurrencyBalance*(self: View, totalCurrencyBalance: float64) =
proc setTotalCurrencyBalance*(self: View, totalCurrencyBalance: CurrencyAmount) =
self.totalCurrencyBalance = totalCurrencyBalance
self.totalCurrencyBalanceChanged()

View File

@ -0,0 +1,42 @@
import strformat
import ./currency_amount
type
Item* = object
balance*: CurrencyAmount
address*: string
chainId*: int
proc initItem*(
balance: CurrencyAmount,
address: string,
chainId: int,
): Item =
result.balance = balance
result.address = address
result.chainId = chainId
proc `$`*(self: Item): string =
result = fmt"""BalanceItem(
name: {self.balance},
address: {self.address},
chainId: {self.chainId},
]"""
proc getBalance*(self: Item): CurrencyAmount =
return self.balance
proc getAddress*(self: Item): string =
return self.address
proc getChainId*(self: Item): int =
return self.chainId
proc getCurrencyBalance*(self: Item, currencyPrice: CurrencyAmount): CurrencyAmount =
return newCurrencyAmount(
self.balance.getAmount() * currencyPrice.getAmount(),
currencyPrice.getSymbol(),
currencyPrice.getDisplayDecimals(),
currencyPrice.isStripTrailingZeroesActive()
)

View File

@ -1,6 +1,7 @@
import NimQml, Tables, strutils, strformat
import ../../../app_service/service/wallet_account/dto
import balance_item
import ./currency_amount
type
ModelRole {.pure.} = enum
@ -11,7 +12,7 @@ type
QtObject:
type
BalanceModel* = ref object of QAbstractListModel
items*: seq[BalanceDto]
items*: seq[Item]
proc delete(self: BalanceModel) =
self.items = @[]
@ -63,7 +64,7 @@ QtObject:
of ModelRole.Address:
result = newQVariant(item.address)
of ModelRole.Balance:
result = newQVariant($item.balance)
result = newQVariant(item.balance)
proc rowData(self: BalanceModel, index: int, column: string): string {.slot.} =
if (index >= self.items.len):
@ -74,7 +75,7 @@ QtObject:
of "address": result = $item.address
of "balance": result = $item.balance
proc setItems*(self: BalanceModel, items: seq[BalanceDto]) =
proc setItems*(self: BalanceModel, items: seq[Item]) =
self.beginResetModel()
self.items = items
self.endResetModel()

View File

@ -0,0 +1,11 @@
import ../../../app_service/service/wallet_account/dto
import ../../../app_service/service/currency/dto as currency_dto
import ./currency_amount_utils
import ./balance_item
proc balanceToItem*(b: BalanceDto, format: CurrencyFormatDto) : Item =
return initItem(
currencyAmountToItem(b.balance, format),
b.address,
b.chainId
)

View File

@ -0,0 +1,67 @@
import NimQml, strformat, json
QtObject:
type CurrencyAmount* = ref object of QObject
amount: float64
symbol: string
displayDecimals: int
stripTrailingZeroes: bool
proc setup(self: CurrencyAmount) =
self.QObject.setup
proc delete*(self: CurrencyAmount) =
self.QObject.delete
proc newCurrencyAmount*(
amount: float64,
symbol: string,
displayDecimals: int,
stripTrailingZeroes: bool,
): CurrencyAmount =
new(result, delete)
result.setup
result.amount = amount
result.symbol = symbol
result.displayDecimals = displayDecimals
result.stripTrailingZeroes = stripTrailingZeroes
proc `$`*(self: CurrencyAmount): string =
result = fmt"""CurrencyAmount(
amount: {self.amount},
symbol: {self.symbol},
displayDecimals: {self.displayDecimals},
stripTrailingZeroes: {self.stripTrailingZeroes}
)"""
proc getAmount*(self: CurrencyAmount): float64 =
return self.amount
proc getAmountFloat*(self: CurrencyAmount): float {.slot.} =
return self.amount
QtProperty[float] amount:
read = getAmountFloat
proc getSymbol*(self: CurrencyAmount): string {.slot.} =
return self.symbol
QtProperty[string] symbol:
read = getSymbol
proc getDisplayDecimals*(self: CurrencyAmount): int {.slot.} =
return self.displayDecimals
QtProperty[int] displayDecimals:
read = getDisplayDecimals
proc isStripTrailingZeroesActive*(self: CurrencyAmount): bool {.slot.} =
return self.stripTrailingZeroes
QtProperty[bool] stripTrailingZeroes:
read = isStripTrailingZeroesActive
# Needed to expose object to QML, see issue #8913
proc toJsonNode*(self: CurrencyAmount): JsonNode =
result = %* {
"amount": self.amount,
"symbol": self.symbol,
"displayDecimals": self.displayDecimals,
"stripTrailingZeroes": self.stripTrailingZeroes
}

View File

@ -0,0 +1,10 @@
import ../../../app_service/service/currency/dto
import ./currency_amount
proc currencyAmountToItem*(amount: float64, format: CurrencyFormatDto) : CurrencyAmount =
return newCurrencyAmount(
amount,
format.symbol,
format.displayDecimals,
format.stripTrailingZeroes
)

View File

@ -1,16 +1,18 @@
import strformat
import ../../../app_service/service/wallet_account/dto
import ./balance_item as balance_item
import ./balance_model as balance_model
import ./currency_amount
type
Item* = object
name: string
symbol: string
totalBalance: float
totalCurrencyBalance: float
enabledNetworkCurrencyBalance: float
enabledNetworkBalance: float
totalBalance: CurrencyAmount
totalCurrencyBalance: CurrencyAmount
enabledNetworkCurrencyBalance: CurrencyAmount
enabledNetworkBalance: CurrencyAmount
visibleForNetwork: bool
visibleForNetworkWithPositiveBalance: bool
balances: balance_model.BalanceModel
@ -18,38 +20,40 @@ type
assetWebsiteUrl: string
builtOn: string
address: string
marketCap: string
highDay: string
lowDay: string
changePctHour: string
changePctDay: string
changePct24hour: string
change24hour: string
currencyPrice: float
marketCap: CurrencyAmount
highDay: CurrencyAmount
lowDay: CurrencyAmount
changePctHour: float64
changePctDay: float64
changePct24hour: float64
change24hour: float64
currencyPrice: CurrencyAmount
decimals: int
pegSymbol: string
proc initItem*(
name, symbol: string,
totalBalance: float,
totalCurrencyBalance: float,
enabledNetworkBalance: float,
enabledNetworkCurrencyBalance: float,
totalBalance: CurrencyAmount,
totalCurrencyBalance: CurrencyAmount,
enabledNetworkBalance: CurrencyAmount,
enabledNetworkCurrencyBalance: CurrencyAmount,
visibleForNetwork: bool,
visibleForNetworkWithPositiveBalance: bool,
balances: seq[BalanceDto],
balances: seq[balance_item.Item],
description: string,
assetWebsiteUrl: string,
builtOn: string,
address: string,
marketCap: string,
highDay: string,
lowDay: string,
changePctHour: string,
changePctDay: string,
changePct24hour: string,
change24hour: string,
currencyPrice: float,
marketCap: CurrencyAmount,
highDay: CurrencyAmount,
lowDay: CurrencyAmount,
changePctHour: float64,
changePctDay: float64,
changePct24hour: float64,
change24hour: float64,
currencyPrice: CurrencyAmount,
decimals: int,
pegSymbol: string,
): Item =
result.name = name
result.symbol = symbol
@ -74,6 +78,7 @@ proc initItem*(
result.change24hour = change24hour
result.currencyPrice = currencyPrice
result.decimals = decimals
result.pegSymbol = pegSymbol
proc `$`*(self: Item): string =
result = fmt"""AllTokensItem(
@ -98,6 +103,7 @@ proc `$`*(self: Item): string =
change24hour: {self.change24hour},
currencyPrice: {self.currencyPrice},
decimals: {self.decimals},
pegSymbol: {self.pegSymbol},
]"""
proc getName*(self: Item): string =
@ -106,16 +112,16 @@ proc getName*(self: Item): string =
proc getSymbol*(self: Item): string =
return self.symbol
proc getTotalBalance*(self: Item): float =
proc getTotalBalance*(self: Item): CurrencyAmount =
return self.totalBalance
proc getTotalCurrencyBalance*(self: Item): float =
proc getTotalCurrencyBalance*(self: Item): CurrencyAmount =
return self.totalCurrencyBalance
proc getEnabledNetworkBalance*(self: Item): float =
proc getEnabledNetworkBalance*(self: Item): CurrencyAmount =
return self.enabledNetworkBalance
proc getEnabledNetworkCurrencyBalance*(self: Item): float =
proc getEnabledNetworkCurrencyBalance*(self: Item): CurrencyAmount =
return self.enabledNetworkCurrencyBalance
proc getVisibleForNetwork*(self: Item): bool =
@ -139,29 +145,32 @@ proc getBuiltOn*(self: Item): string =
proc getAddress*(self: Item): string =
return self.address
proc getMarketCap*(self: Item): string =
proc getMarketCap*(self: Item): CurrencyAmount =
return self.marketCap
proc getHighDay*(self: Item): string =
proc getHighDay*(self: Item): CurrencyAmount =
return self.highDay
proc getLowDay*(self: Item): string =
proc getLowDay*(self: Item): CurrencyAmount =
return self.lowDay
proc getChangePctHour*(self: Item): string =
proc getChangePctHour*(self: Item): float64 =
return self.changePctHour
proc getChangePctDay*(self: Item): string =
proc getChangePctDay*(self: Item): float64 =
return self.changePctDay
proc getChangePct24hour*(self: Item): string =
proc getChangePct24hour*(self: Item): float64 =
return self.changePct24hour
proc getChange24hour*(self: Item): string =
proc getChange24hour*(self: Item): float64 =
return self.change24hour
proc getCurrencyPrice*(self: Item): float =
proc getCurrencyPrice*(self: Item): CurrencyAmount =
return self.currencyPrice
proc getDecimals*(self: Item): int =
return self.decimals
proc getPegSymbol*(self: Item): string =
return self.pegSymbol

View File

@ -1,6 +1,7 @@
import NimQml, Tables, strutils, strformat
import ./token_item
import ./currency_amount
type
ModelRole {.pure.} = enum
@ -26,6 +27,7 @@ type
Change24hour
CurrencyPrice
Decimals
PegSymbol
QtObject:
type
@ -83,6 +85,7 @@ QtObject:
ModelRole.Change24hour.int:"change24hour",
ModelRole.CurrencyPrice.int:"currencyPrice",
ModelRole.Decimals.int:"decimals",
ModelRole.PegSymbol.int:"pegSymbol",
}.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -140,6 +143,8 @@ QtObject:
result = newQVariant(item.getCurrencyPrice())
of ModelRole.Decimals:
result = newQVariant(item.getDecimals())
of ModelRole.PegSymbol:
result = newQVariant(item.getPegSymbol())
proc rowData(self: Model, index: int, column: string): string {.slot.} =
if (index >= self.items.len):
@ -167,6 +172,7 @@ QtObject:
of "change24hour": result = $item.getChange24hour()
of "currencyPrice": result = $item.getCurrencyPrice()
of "decimals": result = $item.getDecimals()
of "pegSymbol": result = $item.getPegSymbol()
proc setItems*(self: Model, items: seq[Item]) =
self.beginResetModel()
@ -191,13 +197,12 @@ QtObject:
if (balance.chainId != chainId):
continue
if(balance.balance >= requiredGas):
if(balance.balance.getAmount() >= requiredGas):
return true
return false
proc getTokenBalanceOnChain*(self: Model, chainId: int, tokenSymbol: string): string =
var tokenBalance: float64 = 0.0
proc getTokenBalanceOnChain*(self: Model, chainId: int, tokenSymbol: string): CurrencyAmount =
for item in self.items:
if(item.getSymbol() != tokenSymbol):
continue
@ -206,6 +211,11 @@ QtObject:
if (balance.chainId != chainId):
continue
tokenBalance = balance.balance
return balance.balance
return $tokenBalance
return newCurrencyAmount(
0.0,
tokenSymbol,
0,
false
)

View File

@ -0,0 +1,42 @@
import tables, sequtils, sugar
import ../../../app_service/service/wallet_account/dto
import ../../../app_service/service/currency/dto as currency_dto
import ./currency_amount_utils
import ./balance_utils
import ./token_item
proc walletTokenToItem*(
t: WalletTokenDto,
chainIds: seq[int],
enabledChainIds: seq[int],
currency: string,
currencyFormat: CurrencyFormatDto,
tokenFormat: CurrencyFormatDto,
) : token_item.Item =
let marketValues = t.marketValuesPerCurrency.getOrDefault(currency)
return token_item.initItem(
t.name,
t.symbol,
currencyAmountToItem(t.getBalance(chainIds), tokenFormat),
currencyAmountToItem(t.getCurrencyBalance(chainIds, currency), currencyFormat),
currencyAmountToItem(t.getBalance(enabledChainIds), tokenFormat),
currencyAmountToItem(t.getCurrencyBalance(enabledChainIds, currency), currencyFormat),
t.getVisibleForNetwork(enabledChainIds),
t.getVisibleForNetworkWithPositiveBalance(enabledChainIds),
t.getBalances(enabledChainIds).map(b => balanceToItem(b, tokenFormat)),
t.description,
t.assetWebsiteUrl,
t.builtOn,
t.getAddress(),
currencyAmountToItem(marketValues.marketCap, currencyFormat),
currencyAmountToItem(marketValues.highDay, currencyFormat),
currencyAmountToItem(marketValues.lowDay, currencyFormat),
marketValues.changePctHour,
marketValues.changePctDay,
marketValues.changePct24hour,
marketValues.change24hour,
currencyAmountToItem(marketValues.price, currencyFormat),
t.decimals,
t.pegSymbol
)

View File

@ -0,0 +1,6 @@
type
CurrencyFormatDto* = ref object
symbol*: string
displayDecimals*: int
stripTrailingZeroes*: bool

View File

@ -0,0 +1,55 @@
import NimQml, strformat, strutils
import ../settings/service as settings_service
import ../token/service as token_service
import ./dto, ./utils
export dto
const DECIMALS_CALCULATION_CURRENCY = "USD"
QtObject:
type Service* = ref object of QObject
tokenService: token_service.Service
settingsService: settings_service.Service
proc delete*(self: Service) =
self.QObject.delete
proc newService*(
tokenService: token_service.Service,
settingsService: settings_service.Service,
): Service =
new(result, delete)
result.QObject.setup
result.tokenService = tokenService
result.settingsService = settingsService
proc init*(self: Service) =
discard
proc getFiatCurrencyFormat(self: Service, symbol: string): CurrencyFormatDto =
return CurrencyFormatDto(
symbol: toUpperAscii(symbol),
displayDecimals: getFiatDisplayDecimals(symbol),
stripTrailingZeroes: false
)
proc getTokenCurrencyFormat(self: Service, symbol: string): CurrencyFormatDto =
let pegSymbol = self.tokenService.getTokenPegSymbol(symbol)
if pegSymbol != "":
var currencyFormat = self.getFiatCurrencyFormat(pegSymbol)
currencyFormat.symbol = symbol
return currencyFormat
else:
let price = self.tokenService.getTokenPrice(symbol, DECIMALS_CALCULATION_CURRENCY, false)
return CurrencyFormatDto(
symbol: symbol,
displayDecimals: getTokenDisplayDecimals(price),
stripTrailingZeroes: true
)
proc getCurrencyFormat*(self: Service, symbol: string): CurrencyFormatDto =
if isCurrencyFiat(symbol):
return self.getFiatCurrencyFormat(symbol)
else:
return self.getTokenCurrencyFormat(symbol)

View File

@ -0,0 +1,33 @@
import math, chronicles, json, strutils
import ../../../backend/backend as backend
logScope:
topics = "currency-utils"
proc isCurrencyFiat*(symbol: string): bool =
let response = backend.isCurrencyFiat(symbol)
return response.result.getBool
proc getFiatDisplayDecimals*(symbol: string): int =
result = 0
try:
let response = backend.getFiatCurrencyMinorUnit(symbol)
result = response.result.getInt
except Exception as e:
let errDesription = e.msg
error "error getFiatDisplayDecimals: ", errDesription
proc getTokenDisplayDecimals*(currencyPrice: float): int =
var decimals = 0.0
if currencyPrice > 0:
const lowerCurrencyResolution = 0.1
const higherCurrencyResolution = 0.01
let lowerDecimalsBound = max(0.0, log10(currencyPrice) - log10(lowerCurrencyResolution))
let upperDecimalsBound = max(0.0, log10(currencyPrice) - log10(higherCurrencyResolution))
# Use as few decimals as needed to ensure lower precision
decimals = ceil(lowerDecimalsBound)
if (decimals + 1 < upperDecimalsBound):
# If allowed by upper bound, ensure resolution changes as soon as currency hits multiple of 10
decimals += 1
return decimals.int

View File

@ -318,7 +318,7 @@ QtObject:
proc getTransactionDetails*(self: Service, message: MessageDto): (string, string) =
let networksDto = self.networkService.getNetworks()
var token = newTokenDto(networksDto[0].nativeCurrencyName, networksDto[0].chainId, parseAddress(ZERO_ADDRESS), networksDto[0].nativeCurrencySymbol, networksDto[0].nativeCurrencyDecimals, true)
var token = newTokenDto(networksDto[0].nativeCurrencyName, networksDto[0].chainId, parseAddress(ZERO_ADDRESS), networksDto[0].nativeCurrencySymbol, networksDto[0].nativeCurrencyDecimals, true, "")
if message.transactionParameters.contract != "":
for networkDto in networksDto:

View File

@ -23,17 +23,7 @@ type
color*: string
isCustom* {.dontSerialize.}: bool
isVisible* {.dontSerialize.}: bool
description* :string
assetWebsiteUrl*: string
builtOn*: string
smartContractAddress*: string
marketCap*: string
highDay*: string
lowDay*: string
changePctHour*: string
changePctDay*: string
changePct24hour*: string
change24hour*: string
pegSymbol*: string
proc newTokenDto*(
name: string,
@ -42,18 +32,8 @@ proc newTokenDto*(
symbol: string,
decimals: int,
hasIcon: bool,
pegSymbol: string,
isCustom: bool = false,
description: string = "",
assetWebsiteUrl: string = "",
builtOn: string = "",
smartContractAddress: string = "",
marketCap: string = "",
highDay: string = "",
lowDay: string = "",
changePctHour: string = "",
changePctDay: string = "",
changePct24hour: string = "",
change24hour: string = "",
): TokenDto =
return TokenDto(
name: name,
@ -62,6 +42,7 @@ proc newTokenDto*(
symbol: symbol,
decimals: decimals,
hasIcon: hasIcon,
pegSymbol: pegSymbol,
isCustom: isCustom
)
@ -76,6 +57,7 @@ proc toTokenDto*(jsonObj: JsonNode, isVisible: bool, hasIcon: bool = false, isCu
discard jsonObj.getProp("symbol", result.symbol)
discard jsonObj.getProp("decimals", result.decimals)
discard jsonObj.getProp("color", result.color)
discard jsonObj.getProp("pegSymbol", result.pegSymbol)
result.isVisible = isVisible
proc addressAsString*(self: TokenDto): string =

View File

@ -6,9 +6,12 @@ from web3/conversions import `$`
import ../../../backend/backend as backend
import ../network/service as network_service
import ../wallet_account/dto as wallet_account_dto
import ../../../app/global/global_singleton
import ../../../app/core/eventemitter
import ../../../app/core/tasks/[qt, threadpool]
import ../../../backend/cache
import ./dto
export dto
@ -36,6 +39,9 @@ QtObject:
threadpool: ThreadPool
networkService: network_service.Service
tokens: Table[int, seq[TokenDto]]
priceCache: TimedCache
proc updateCachedTokenPrice(self: Service, crypto: string, fiat: string, price: float64)
proc delete*(self: Service) =
self.QObject.delete
@ -51,6 +57,7 @@ QtObject:
result.threadpool = threadpool
result.networkService = networkService
result.tokens = initTable[int, seq[TokenDto]]()
result.priceCache = newTimedCache()
proc init*(self: Service) =
try:
@ -63,7 +70,6 @@ QtObject:
found = true
break
if found:
continue
@ -82,6 +88,12 @@ QtObject:
error "error: ", errDesription
return
proc updateTokenPrices*(self: Service, tokens: seq[WalletTokenDto]) =
# Use data fetched by walletAccountService to update local price cache
for token in tokens:
for currency, marketValues in token.marketValuesPerCurrency:
self.updateCachedTokenPrice(token.symbol, currency, marketValues.price)
proc findTokenBySymbol*(self: Service, network: NetworkDto, symbol: string): TokenDto =
try:
for token in self.tokens[network.chainId]:
@ -111,6 +123,49 @@ QtObject:
return token.symbol
return ""
# Token
proc renameSymbol(symbol: string) : string =
return toUpperAscii(symbol)
proc getTokenPriceCacheKey(crypto: string, fiat: string) : string =
return renameSymbol(crypto) & renameSymbol(fiat)
proc getTokenPrice*(self: Service, crypto: string, fiat: string, fetchIfNotAvailable: bool = true): float64 =
let cacheKey = getTokenPriceCacheKey(crypto, fiat)
if self.priceCache.isCached(cacheKey) or (self.priceCache.hasKey(cacheKey) and not fetchIfNotAvailable):
return parseFloat(self.priceCache.get(cacheKey))
elif not fetchIfNotAvailable:
return 0.0
var prices = initTable[string, Table[string, float]]()
try:
let cryptoKey = renameSymbol(crypto)
let fiatKey = renameSymbol(fiat)
let response = backend.fetchPrices(@[cryptoKey], @[fiatKey])
for (symbol, pricePerCurrency) in response.result.pairs:
for (currency, price) in pricePerCurrency.pairs:
prices[symbol][currency] = price.getFloat
self.updateCachedTokenPrice(cryptoKey, fiatKey, prices[cryptoKey][fiatKey])
return prices[cryptoKey][fiatKey]
except Exception as e:
let errDesription = e.msg
error "error: ", errDesription
return 0.0
proc updateCachedTokenPrice(self: Service, crypto: string, fiat: string, price: float64) =
let cacheKey = getTokenPriceCacheKey(crypto, fiat)
self.priceCache.set(cacheKey, $price)
proc getTokenPegSymbol*(self: Service, symbol: string): string =
for _, tokens in self.tokens:
for token in tokens:
if token.symbol == symbol:
return token.pegSymbol
return ""
# History Data
proc tokenHistoricalDataResolved*(self: Service, response: string) {.slot.} =
let responseObj = response.parseJson
if (responseObj.kind != JObject):
@ -121,17 +176,6 @@ QtObject:
result: response
))
proc tokenBalanceHistoryDataResolved*(self: Service, response: string) {.slot.} =
# TODO
let responseObj = response.parseJson
if (responseObj.kind != JObject):
info "blance history response is not a json object"
return
self.events.emit(SIGNAL_BALANCE_HISTORY_DATA_READY, TokenBalanceHistoryDataArgs(
result: response
))
proc getHistoricalDataForToken*(self: Service, symbol: string, currency: string, range: int) =
let arg = GetTokenHistoricalDataTaskArg(
tptr: cast[ByteAddress](getTokenHistoricalDataTask),
@ -143,6 +187,18 @@ QtObject:
)
self.threadpool.start(arg)
# Historical Balance
proc tokenBalanceHistoryDataResolved*(self: Service, response: string) {.slot.} =
# TODO
let responseObj = response.parseJson
if (responseObj.kind != JObject):
info "blance history response is not a json object"
return
self.events.emit(SIGNAL_BALANCE_HISTORY_DATA_READY, TokenBalanceHistoryDataArgs(
result: response
))
proc fetchHistoricalBalanceForTokenAsJson*(self: Service, address: string, symbol: string, timeInterval: BalanceHistoryTimeInterval) =
let networks = self.networkService.getNetworks()
for network in networks:

View File

@ -22,6 +22,49 @@ type BalanceDto* = object
address*: string
chainId*: int
type
TokenMarketValuesDto* = object
marketCap*: float64
highDay*: float64
lowDay*: float64
changePctHour*: float64
changePctDay*: float64
changePct24hour*: float64
change24hour*: float64
price*: float64
proc newTokenMarketValuesDto*(
marketCap: float64,
highDay: float64,
lowDay: float64,
changePctHour: float64,
changePctDay: float64,
changePct24hour: float64,
change24hour: float64,
price: float64
): TokenMarketValuesDto =
return TokenMarketValuesDto(
marketCap: marketCap,
highDay: highDay,
lowDay: lowDay,
changePctHour: changePctHour,
changePctDay: changePctDay,
changePct24hour: changePct24hour,
change24hour: change24hour,
price: price,
)
proc toTokenMarketValuesDto*(jsonObj: JsonNode): TokenMarketValuesDto =
result = TokenMarketValuesDto()
discard jsonObj.getProp("marketCap", result.marketCap)
discard jsonObj.getProp("highDay", result.highDay)
discard jsonObj.getProp("lowDay", result.lowDay)
discard jsonObj.getProp("changePctHour", result.changePctHour)
discard jsonObj.getProp("changePctDay", result.changePctDay)
discard jsonObj.getProp("changePct24hour", result.changePct24hour)
discard jsonObj.getProp("change24hour", result.change24hour)
discard jsonObj.getProp("price", result.price)
type
WalletTokenDto* = object
name*: string
@ -32,14 +75,8 @@ type
description*: string
assetWebsiteUrl*: string
builtOn*: string
marketCap*: string
highDay*: string
lowDay*: string
changePctHour*: string
changePctDay*: string
changePct24hour*: string
change24hour*: string
currencyPrice*: float64
pegSymbol*: string
marketValuesPerCurrency*: Table[string, TokenMarketValuesDto]
type
WalletAccountDto* = ref object of RootObj
@ -123,11 +160,12 @@ proc getBalance*(self: WalletTokenDto, chainIds: seq[int]): float64 =
return sum
proc getCurrencyBalance*(self: WalletTokenDto, chainIds: seq[int]): float64 =
proc getCurrencyBalance*(self: WalletTokenDto, chainIds: seq[int], currency: string): float64 =
var sum = 0.0
let price = if self.marketValuesPerCurrency.hasKey(currency): self.marketValuesPerCurrency[currency].price else: 0.0
for chainId in chainIds:
if self.balancesPerChain.hasKey(chainId):
sum += self.balancesPerChain[chainId].getCurrencyBalance(self.currencyPrice)
sum += self.balancesPerChain[chainId].getCurrencyBalance(price)
return sum
@ -148,8 +186,8 @@ proc getVisibleForNetworkWithPositiveBalance*(self: WalletTokenDto, chainIds: se
return false
proc getCurrencyBalance*(self: WalletAccountDto, chainIds: seq[int]): float64 =
return self.tokens.map(t => t.getCurrencyBalance(chainIds)).foldl(a + b, 0.0)
proc getCurrencyBalance*(self: WalletAccountDto, chainIds: seq[int], currency: string): float64 =
return self.tokens.map(t => t.getCurrencyBalance(chainIds, currency)).foldl(a + b, 0.0)
proc toBalanceDto*(jsonObj: JsonNode): BalanceDto =
result = BalanceDto()
@ -166,14 +204,12 @@ proc toWalletTokenDto*(jsonObj: JsonNode): WalletTokenDto =
discard jsonObj.getProp("description", result.description)
discard jsonObj.getProp("assetWebsiteUrl", result.assetWebsiteUrl)
discard jsonObj.getProp("builtOn", result.builtOn)
discard jsonObj.getProp("marketCap", result.marketCap)
discard jsonObj.getProp("highDay", result.highDay)
discard jsonObj.getProp("lowDay", result.lowDay)
discard jsonObj.getProp("changePctHour", result.changePctHour)
discard jsonObj.getProp("changePctDay", result.changePctDay)
discard jsonObj.getProp("changePct24hour", result.changePct24hour)
discard jsonObj.getProp("change24hour", result.change24hour)
discard jsonObj.getProp("currencyPrice", result.currencyPrice)
discard jsonObj.getProp("pegSymbol", result.pegSymbol)
var marketValuesPerCurrencyObj: JsonNode
if(jsonObj.getProp("marketValuesPerCurrency", marketValuesPerCurrencyObj)):
for currency, marketValuesObj in marketValuesPerCurrencyObj:
result.marketValuesPerCurrency[currency] = marketValuesObj.toTokenMarketValuesDto()
var balancesPerChainObj: JsonNode
if(jsonObj.getProp("balancesPerChain", balancesPerChainObj)):

View File

@ -17,7 +17,6 @@ import ../../../backend/accounts as status_go_accounts
import ../../../backend/backend as backend
import ../../../backend/eth as status_go_eth
import ../../../backend/transactions as status_go_transactions
import ../../../backend/cache
export dto, derived_address, key_pair_dto
@ -101,7 +100,6 @@ include ../../common/json_utils
QtObject:
type Service* = ref object of QObject
closingApp: bool
ignoreTimeInitiatedTokensBuild: bool
events: EventEmitter
threadpool: ThreadPool
settingsService: settings_service.Service
@ -109,11 +107,7 @@ QtObject:
tokenService: token_service.Service
networkService: network_service.Service
walletAccounts: OrderedTable[string, WalletAccountDto]
timerStartTimeInSeconds: int64
priceCache: TimedCache
processedKeyPair: KeyPairDto
ignoreTimeInitiatedHistoryFetchBuild: bool
isHistoryFetchTimerAlreadyRunning: bool
# Forward declaration
proc buildAllTokens(self: Service, accounts: seq[string])
@ -135,7 +129,6 @@ QtObject:
new(result, delete)
result.QObject.setup
result.closingApp = false
result.ignoreTimeInitiatedTokensBuild = false
result.events = events
result.threadpool = threadpool
result.settingsService = settingsService
@ -143,27 +136,6 @@ QtObject:
result.tokenService = tokenService
result.networkService = networkService
result.walletAccounts = initOrderedTable[string, WalletAccountDto]()
result.priceCache = newTimedCache()
result.ignoreTimeInitiatedHistoryFetchBuild = false
result.isHistoryFetchTimerAlreadyRunning = false
proc getPrice*(self: Service, crypto: string, fiat: string): float64 =
let cacheKey = crypto & fiat
if self.priceCache.isCached(cacheKey):
return parseFloat(self.priceCache.get(cacheKey))
var prices = initTable[string, float]()
try:
let response = backend.fetchPrices(@[crypto], fiat)
for (symbol, value) in response.result.pairs:
prices[symbol] = value.getFloat
self.priceCache.set(cacheKey, $value.getFloat)
return prices[crypto]
except Exception as e:
let errDesription = e.msg
error "error: ", errDesription
return 0.0
proc fetchAccounts*(self: Service): seq[WalletAccountDto] =
let response = status_go_accounts.getAccounts()
@ -360,6 +332,9 @@ QtObject:
self.events.emit(SIGNAL_WALLET_ACCOUNT_DELETED, AccountDeleted(account: accountDeleted))
proc getCurrency*(self: Service): string =
return self.settingsService.getCurrency()
proc updateCurrency*(self: Service, newCurrency: string) =
discard self.settingsService.saveCurrency(newCurrency)
self.buildAllTokens(self.getAddresses())
@ -472,7 +447,7 @@ QtObject:
tokens.sort(priorityTokenCmp)
self.walletAccounts[wAddress].tokens = tokens
data.accountsTokens[wAddress] = tokens
self.tokenService.updateTokenPrices(tokens) # For efficiency. Will be removed when token info fetching gets moved to the tokenService
self.events.emit(SIGNAL_WALLET_ACCOUNT_TOKENS_REBUILT, data)
except Exception as e:
error "error: ", procName="onAllTokensBuilt", errName = e.name, errDesription = e.msg
@ -494,22 +469,28 @@ QtObject:
self.checkRecentHistory()
self.startWallet()
proc getNetworkCurrencyBalance*(self: Service, network: NetworkDto): float64 =
proc getCurrentCurrencyIfEmpty(self: Service, currency: string): string =
if currency != "":
return currency
else:
return self.getCurrency()
proc getNetworkCurrencyBalance*(self: Service, network: NetworkDto, currency: string = ""): float64 =
for walletAccount in toSeq(self.walletAccounts.values):
result += walletAccount.getCurrencyBalance(@[network.chainId])
result += walletAccount.getCurrencyBalance(@[network.chainId], self.getCurrentCurrencyIfEmpty(currency))
proc findTokenSymbolByAddress*(self: Service, address: string): string =
return self.tokenService.findTokenSymbolByAddress(address)
proc getCurrencyBalanceForAddress*(self: Service, address: string): float64 =
proc getCurrencyBalanceForAddress*(self: Service, address: string, currency: string = ""): float64 =
let chainIds = self.networkService.getNetworks().map(n => n.chainId)
if not self.walletAccounts.hasKey(address):
return
return self.walletAccounts[address].getCurrencyBalance(chainIds)
return self.walletAccounts[address].getCurrencyBalance(chainIds, self.getCurrentCurrencyIfEmpty(currency))
proc getTotalCurrencyBalance*(self: Service): float64 =
proc getTotalCurrencyBalance*(self: Service, currency: string = ""): float64 =
let chainIds = self.networkService.getNetworks().filter(a => a.enabled).map(a => a.chainId)
return self.getWalletAccounts().map(a => a.getCurrencyBalance(chainIds)).foldl(a + b, 0.0)
return self.getWalletAccounts().map(a => a.getCurrencyBalance(chainIds, self.getCurrentCurrencyIfEmpty(currency))).foldl(a + b, 0.0)
proc responseHasNoErrors(self: Service, procName: string, response: RpcResponse[JsonNode]): bool =
var errMsg = ""

View File

@ -100,7 +100,7 @@ rpc(getTransactionEstimatedTime, "wallet"):
rpc(fetchPrices, "wallet"):
symbols: seq[string]
currency: string
currencies: seq[string]
rpc(generateAccountWithDerivedPath, "accounts"):
password: string
@ -219,7 +219,7 @@ rpc(deleteDappPermissionsByNameAndAddress, "permissions"):
rpc(fetchMarketValues, "wallet"):
symbols: seq[string]
currency: string
currencies: seq[string]
rpc(fetchTokenDetails, "wallet"):
symbols: seq[string]
@ -277,4 +277,10 @@ rpc(getName, "ens"):
rpc(getBalanceHistory, "wallet"):
chainId: int
address: string
timeInterval: int
timeInterval: int
rpc(isCurrencyFiat, "wallet"):
code: string
rpc(getFiatCurrencyMinorUnit, "wallet"):
code: string

View File

@ -23,7 +23,6 @@ SplitView {
SplitView.fillHeight: true
communitiesStore: CommunitiesStore {
readonly property string locale: ""
readonly property int unreadNotificationsCount: 42
readonly property string communityTags: ModelsData.communityTags
readonly property var curatedCommunitiesModel: SortFilterProxyModel {

View File

@ -94,11 +94,11 @@ Rectangle {
*/
property ListModel categories: ListModel {}
/*!
\qmlproperty string StatusCommunityCard::locale
\qmlproperty var StatusCommunityCard::locale
This property holds the application locale used to give format to members number representation.
If not provided, default value is "en".
*/
property string locale: "en"
property var locale: Qt.locale("en")
/*!
\qmlproperty url StatusCommunityCard::banner
This property holds the community banner image url.
@ -148,14 +148,14 @@ Rectangle {
const ks = 1000
if(number > million) {
res = number / million
res = Number(number / million).toLocaleString(Qt.locale(root.locale), 'f', 1) + 'M'
res = Number(number / million).toLocaleString(root.locale, 'f', 1) + 'M'
}
else if(number > ks) {
res = number / ks
res = Number(number / ks).toLocaleString(Qt.locale(root.locale), 'f', 1) + 'K'
res = Number(number / ks).toLocaleString(root.locale, 'f', 1) + 'K'
}
else
res = Number(number).toLocaleString(Qt.locale(root.locale), 'f', 0)
res = Number(number).toLocaleString(root.locale, 'f', 0)
return res
}
}

View File

@ -47,7 +47,7 @@ Item {
if (showBalanceForAssetSymbol == "" || minRequiredAssetBalance == 0 || !assetFound) {
return root.isValid
}
root.isValid = assetFound.totalBalance >= minRequiredAssetBalance
root.isValid = assetFound.totalBalance.amount >= minRequiredAssetBalance
return root.isValid
}
@ -88,7 +88,7 @@ Item {
if (!assetFound) {
return
}
txtAssetBalance.text = root.assetBalanceTextFn(assetFound.totalBalance)
txtAssetBalance.text = root.assetBalanceTextFn(assetFound.totalBalance.amount)
txtAssetSymbol.text = " " + assetFound.symbol
}

View File

@ -33,10 +33,10 @@ StatusValidator {
property real bottom: qmlDoubleValidator.bottom
/*!
\qmlproperty string StatusFloatValidator::locale
This property holds the name of the locale used to interpret the number.
\qmlproperty var StatusFloatValidator::locale
This property holds the locale used to interpret the number.
*/
property string locale
property var locale: Qt.locale()
/*!
\qmlproperty real StatusFloatValidator::top

View File

@ -35,10 +35,10 @@ StatusValidator {
property int bottom
/*!
\qmlproperty string StatusIntValidator::locale
This property holds the name of the locale used to interpret the number.
\qmlproperty var StatusIntValidator::locale
This property holds the locale used to interpret the number.
*/
property string locale
property var locale: Qt.locale()
/*!
\qmlproperty string StatusIntValidator::top
@ -48,7 +48,7 @@ StatusValidator {
name: "intValidator"
errorMessage: qsTr("Please enter a valid numeric value.")
validatorObj: IntValidator { bottom: root.bottom; locale: root.locale; top: root.top }
validatorObj: IntValidator { bottom: root.bottom; locale: root.locale.name; top: root.top }
validate: function (t) {
// Basic validation management

View File

@ -17,6 +17,7 @@ ColumnLayout {
property alias amountText: amountInput.text
property alias amount: amountInput.amount
readonly property bool amountValid: amountInput.valid && amountInput.text.length > 0
property var locale
signal pickerClicked
@ -66,5 +67,7 @@ ColumnLayout {
Layout.topMargin: 8
allowDecimals: false
locale: root.locale
}
}

View File

@ -291,6 +291,7 @@ StatusDropdown {
tokenName: d.defaultTokenNameText
amountText: d.tokenAmountText
onAmountTextChanged: d.tokenAmountText = amountText
locale: root.store.locale
readonly property real effectiveAmount: amountValid ? amount : 0
onEffectiveAmountChanged: root.tokenAmount = effectiveAmount
@ -343,6 +344,7 @@ StatusDropdown {
collectibleName: d.defaultCollectibleNameText
amountText: d.collectibleAmountText
onAmountTextChanged: d.collectibleAmountText = amountText
locale: root.store.locale
readonly property real effectiveAmount: amountValid ? amount : 0
onEffectiveAmountChanged: root.collectibleAmount = effectiveAmount

View File

@ -15,6 +15,7 @@ ColumnLayout {
property alias amountText: amountInput.text
property alias amount: amountInput.amount
readonly property bool amountValid: amountInput.valid && amountInput.text.length > 0
property var locale
signal pickerClicked
@ -43,5 +44,7 @@ ColumnLayout {
Layout.fillWidth: true
Layout.topMargin: 8
locale: root.locale
}
}

View File

@ -7,7 +7,7 @@ import shared.stores 1.0
QtObject {
id: root
property string locale: localAppSettings.language
property var locale: Qt.locale(localAppSettings.language)
property var contactsStore
@ -464,7 +464,7 @@ QtObject {
property var accounts: walletSectionAccounts.model
property var currentAccount: walletSectionCurrent
property string currentCurrency: walletSection.currentCurrency
property CurrenciesStore currencyStore: CurrenciesStore { }
property CurrenciesStore currencyStore: CurrenciesStore {}
property var allNetworks: networksModule.all
property var savedAddressesModel: walletSectionSavedAddresses.model

View File

@ -28,7 +28,7 @@ QtObject {
property bool discordImportHasCommunityImage: root.communitiesModuleInst.discordImportHasCommunityImage
property var discordImportTasks: root.communitiesModuleInst.discordImportTasks
property bool downloadingCommunityHistoryArchives: root.communitiesModuleInst.downloadingCommunityHistoryArchives
property string locale: localAppSettings.language
property var locale: Qt.locale(localAppSettings.language)
property var advancedModule: profileSectionModule.advancedModule
// TODO: Could the backend provide directly 2 filtered models??

View File

@ -18,7 +18,7 @@ import "../stores"
Item {
id: root
property string locale: ""
property var locale
property string currency: ""
property var currentAccount
property var store
@ -46,7 +46,7 @@ Item {
font.pixelSize: 28
font.bold: true
color: Theme.palette.baseColor1
text: "%1 %2".arg(Utils.toLocaleString(root.currentAccount.currencyBalance.toFixed(2), root.locale, {"currency": true})).arg(root.currency.toUpperCase())
text: LocaleUtils.currencyAmountToLocaleString(root.currentAccount.currencyBalance, root.locale)
}
}

View File

@ -59,6 +59,7 @@ StatusModal {
root.selectedAccount = newAccount
}
showAllWalletTypes: true
locale: RootStore.locale
}
contentItem: Column {

View File

@ -22,12 +22,12 @@ QtObject {
property var generatedAccounts: walletSectionAccounts.generated
property var appSettings: localAppSettings
property var accountSensitiveSettings: localAccountSensitiveSettings
property string locale: Qt.locale().name
property var locale: Qt.locale(appSettings.language)
property bool hideSignPhraseModal: accountSensitiveSettings.hideSignPhraseModal
property var currencyStore: SharedStore.RootStore.currencyStore
property string currentCurrency: currencyStore.currentCurrency
property string totalCurrencyBalance: walletSection.totalCurrencyBalance
property var totalCurrencyBalance: walletSection.totalCurrencyBalance
property string signingPhrase: walletSection.signingPhrase
property string mnemonicBackedUp: walletSection.isMnemonicBackedUp

View File

@ -82,7 +82,7 @@ Rectangle {
objectName: "walletLeftListAmountValue"
color: Style.current.textColor
text: {
Utils.toLocaleString(parseFloat(RootStore.totalCurrencyBalance).toFixed(2), localAppSettings.language, {"currency": true}) + " " + RootStore.currentCurrency.toUpperCase()
LocaleUtils.currencyAmountToLocaleString(RootStore.totalCurrencyBalance, RootStore.currencyStore.locale)
}
selectByMouse: true
cursorVisible: true
@ -117,7 +117,7 @@ Rectangle {
width: ListView.view.width
highlighted: RootStore.currentAccount.name === model.name
title: model.name
subTitle: Utils.toLocaleString(model.currencyBalance.toFixed(2), RootStore.locale, {"model.currency": true}) + " " + RootStore.currentCurrency.toUpperCase()
subTitle: LocaleUtils.currencyAmountToLocaleString(model.currencyBalance, RootStore.currencyStore.locale)
asset.emoji: !!model.emoji ? model.emoji: ""
asset.color: model.color
asset.name: !model.emoji ? "filled-account": ""

View File

@ -92,6 +92,7 @@ Item {
AssetsView {
account: RootStore.currentAccount
assetDetailsLaunched: stack.currentIndex === 2
locale: RootStore.locale
onAssetClicked: {
assetDetailView.token = token
stack.currentIndex = 2

View File

@ -7,7 +7,7 @@ import "../Profile/stores"
QtObject {
id: root
property string locale: localAppSettings.language
property var locale: Qt.locale(localAppSettings.language)
property var mainModuleInst: mainModule
property var aboutModuleInst: aboutModule

View File

@ -10,7 +10,7 @@ Input {
id: root
property int maximumLength: 10
property var locale: Qt.locale()
property var locale
readonly property alias amount: d.amount
readonly property bool valid: validationError.length === 0
@ -40,7 +40,7 @@ Input {
decimals: root.allowDecimals ? 100 : 0
bottom: 0
notation: DoubleValidator.StandardNotation
locale: root.locale.name
locale: root.locale
}
onTextChanged: {

View File

@ -181,7 +181,7 @@ Item {
if (!selectAsset.selectedAsset) {
return
}
txtBalance.text = Utils.stripTrailingZeros(parseFloat(selectAsset.selectedAsset.balance).toFixed(4))
txtBalance.text = Utils.stripTrailingZeros(selectAsset.selectedAsset.balance.amount.toFixed(4))
if (inputAmount.text === "" || isNaN(inputAmount.text)) {
return
}

View File

@ -10,7 +10,7 @@ Item {
id: assetDelegate
objectName: symbol
property string locale: ""
property var locale
property string currency: ""
property string currencySymbol: ""
@ -52,7 +52,7 @@ Item {
anchors.leftMargin: Style.current.smallPadding
font.pixelSize: 15
color: Style.current.secondaryText
text: qsTr("%1 %2").arg(enabledNetworkBalance.toString()).arg(symbol)
text: LocaleUtils.currencyAmountToLocaleString(enabledNetworkBalance, root.locale)
}
StyledText {
@ -63,6 +63,6 @@ Item {
anchors.rightMargin: 0
font.pixelSize: 15
font.strikeout: false
text: enabledNetworkCurrencyBalance.toLocaleCurrencyString(Qt.locale(), assetDelegate.currencySymbol)
text: LocaleUtils.currencyAmountToLocaleString(enabledNetworkCurrencyBalance, root.locale)
}
}

View File

@ -22,6 +22,7 @@ Control {
}
property var getNetworkColor: function(chainId){}
property var getNetworkIcon: function(chainId){}
property var formatBalance: function(balance){}
topPadding: Style.current.padding
@ -77,7 +78,7 @@ Control {
id: chainRepeater
model: balances ? balances : null
delegate: InformationTag {
tagPrimaryLabel.text: model.balance
tagPrimaryLabel.text: root.formatBalance(model.balance)
tagPrimaryLabel.color: root.getNetworkColor(model.chainId)
image.source: Style.svg("tiny/%1".arg(root.getNetworkIcon(model.chainId)))
}

View File

@ -8,14 +8,14 @@ import utils 1.0
StatusListItem {
id: root
property string currentCurrencySymbol
property var locale
property var getNetworkIcon: function(chainId){
return ""
}
signal tokenSelected(var selectedToken)
title: name
label: enabledNetworkCurrencyBalance.toLocaleCurrencyString(Qt.locale(), root.currentCurrencySymbol)
label: LocaleUtils.currencyAmountToLocaleString(enabledNetworkCurrencyBalance, root.locale)
asset.name: symbol ? Style.png("tokens/" + symbol) : ""
asset.isImage: true
asset.width: 32
@ -34,14 +34,14 @@ StatusListItem {
width: 16
height: 16
image.source: Style.svg("tiny/%1".arg(root.getNetworkIcon(chainId)))
visible: balance > 0
visible: balance.amount > 0
}
}
Component {
id: expandedItem
StatusListItemTag {
height: 16
title: balance
title: LocaleUtils.currencyAmountToLocaleString(balance, root.locale)
titleText.font.pixelSize: 12
closeButtonVisible: false
bgColor: "transparent"
@ -49,7 +49,7 @@ StatusListItem {
asset.height: 16
asset.isImage: true
asset.name: Style.svg("tiny/%1".arg(root.getNetworkIcon(chainId)))
visible: balance > 0
visible: balance.amount > 0
}
}
}

View File

@ -9,10 +9,10 @@ import StatusQ.Core 0.1
import utils 1.0
StatusListItem {
property string currentCurrencySymbol
id: root
property var locale
title: name
subTitle: `${enabledNetworkBalance} ${symbol}`
subTitle: LocaleUtils.currencyAmountToLocaleString(enabledNetworkBalance, root.locale)
asset.name: symbol ? Style.png("tokens/" + symbol) : ""
asset.isImage: true
components: [
@ -25,7 +25,7 @@ StatusListItem {
anchors.right: parent.right
font.pixelSize: 15
font.strikeout: false
text: enabledNetworkCurrencyBalance.toLocaleCurrencyString(Qt.locale(), currentCurrencySymbol)
text: LocaleUtils.currencyAmountToLocaleString(enabledNetworkCurrencyBalance, root.locale)
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
@ -35,7 +35,7 @@ StatusListItem {
font.pixelSize: 15
font.strikeout: false
color: valueColumn.textColor
text: currencyPrice.toLocaleCurrencyString(Qt.locale(), currentCurrencySymbol)
text: LocaleUtils.currencyAmountToLocaleString(currencyPrice, root.locale)
}
Rectangle {
width: 1
@ -46,7 +46,7 @@ StatusListItem {
font.pixelSize: 15
font.strikeout: false
color: valueColumn.textColor
text: changePct24hour !== "" ? "%1%".arg(changePct24hour) : "---"
text: changePct24hour !== "" ? changePct24hour.toFixed(2) + "%" : "---"
}
}
}

View File

@ -27,6 +27,7 @@ Item {
property string userSelectedToken
property string currentCurrencySymbol
property string placeholderText
property var locale
property var tokenAssetSourceFn: function (symbol) {
return ""
@ -149,7 +150,7 @@ Item {
delegate: TokenBalancePerChainDelegate {
objectName: "AssetSelector_ItemDelegate_" + symbol
width: comboBox.control.popup.width
currentCurrencySymbol: root.currentCurrencySymbol
locale: root.locale
getNetworkIcon: root.getNetworkIcon
onTokenSelected: {
userSelectedToken = selectedToken.symbol

View File

@ -18,6 +18,7 @@ import "../views"
StatusFloatingButtonsSelector {
id: root
property var locale
property var selectedAccount
// Expected signature: function(newAccount, newIndex)
property var changeSelectedAccount: function(){}
@ -88,7 +89,7 @@ StatusFloatingButtonsSelector {
popupMenuDelegate: StatusListItem {
implicitWidth: 272
title: name
subTitle: currencyBalance
subTitle: LocaleUtils.currencyAmountToLocaleString(currencyBalance, locale)
asset.emoji: !!emoji ? emoji: ""
asset.color: model.color
asset.name: !emoji ? "filled-account": ""

View File

@ -81,9 +81,9 @@ StatusDialog {
readonly property int errorType: !amountToSendInput.input.valid ? Constants.SendAmountExceedsBalance :
(networkSelector.bestRoutes && networkSelector.bestRoutes.length <= 0 && !!amountToSendInput.input.text && recipientReady && !popup.isLoading) ?
Constants.NoRoute : Constants.NoError
readonly property double maxFiatBalance: !!assetSelector.selectedAsset ? (amountToSendInput.cryptoFiatFlipped ?
readonly property var maxFiatBalance: !!assetSelector.selectedAsset ? (amountToSendInput.cryptoFiatFlipped ?
assetSelector.selectedAsset.totalCurrencyBalance :
assetSelector.selectedAsset.totalBalance): 0
assetSelector.selectedAsset.totalBalance): undefined
readonly property bool errorMode: popup.isLoading || !recipientReady ? false : errorType !== Constants.NoError || networkSelector.errorMode || isNaN(amountToSendInput.input.text)
readonly property bool recipientReady: (isAddressValid || isENSValid) && !recipientSelector.isPending
property bool isAddressValid: Utils.isValidAddress(popup.addressText)
@ -239,11 +239,12 @@ StatusDialog {
}
popup.recalculateRoutesAndFees()
}
locale: popup.store.locale
}
StatusListItemTag {
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
Layout.preferredHeight: 22
title: d.maxFiatBalance > 0 ? qsTr("Max: %1").arg(LocaleUtils.numberToLocaleString(d.maxFiatBalance)) : qsTr("No balances active")
title: d.maxFiatBalance && d.maxFiatBalance.amount > 0 ? qsTr("Max: %1").arg(LocaleUtils.currencyAmountToLocaleString(d.maxFiatBalance, popup.store.locale)) : qsTr("No balances active")
closeButtonVisible: false
titleText.font.pixelSize: 12
bgColor: amountToSendInput.input.valid ? Theme.palette.primaryColor3 : Theme.palette.dangerColor2
@ -255,6 +256,7 @@ StatusDialog {
AmountToSend {
id: amountToSendInput
Layout.fillWidth:true
locale: popup.store.locale
isBridgeTx: popup.isBridgeTx
interactive: popup.interactive
selectedAsset: assetSelector.selectedAsset
@ -272,6 +274,7 @@ StatusDialog {
id: amountToReceive
Layout.alignment: Qt.AlignRight
Layout.fillWidth:true
locale: popup.store.locale
visible: popup.bestRoutes !== undefined && popup.bestRoutes.length > 0
store: popup.store
isLoading: popup.isLoading
@ -287,7 +290,7 @@ StatusDialog {
anchors.right: parent.right
visible: !assetSelector.selectedAsset
assets: popup.selectedAccount && popup.selectedAccount.assets ? popup.selectedAccount.assets : []
currentCurrencySymbol: RootStore.currencyStore.currentCurrencySymbol
locale: popup.store.locale
searchTokenSymbolByAddressFn: function (address) {
if(popup.selectedAccount) {
return popup.selectedAccount.findTokenSymbolByAddress(address)
@ -400,6 +403,7 @@ StatusDialog {
d.waitTimer.restart()
}
visible: !d.recipientReady && !isBridgeTx && !!assetSelector.selectedAsset
locale: popup.store.locale
}
NetworkSelector {
@ -445,7 +449,7 @@ StatusDialog {
footer: SendModalFooter {
nextButtonText: popup.isBridgeTx ? qsTr("Bridge") : qsTr("Send")
maxFiatFees: popup.isLoading ? "..." : "%1 %2".arg(LocaleUtils.numberToLocaleString(d.totalFeesInFiat)).arg(popup.store.currentCurrency.toUpperCase())
maxFiatFees: popup.isLoading ? "..." : "%1 %2".arg(LocaleUtils.numberToLocaleString(d.totalFeesInFiat, -1, popup.store.locale)).arg(popup.store.currentCurrency.toUpperCase())
totalTimeEstimate: popup.isLoading? "..." : d.totalTimeEstimate
pending: d.isPendingTx || popup.isLoading
visible: d.recipientReady && !isNaN(amountToSendInput.cryptoValueToSend) && !d.errorMode

View File

@ -131,10 +131,10 @@ Rectangle {
text: {
if (Global.appMain) {
return "%1%2".arg(SharedStore.RootStore.currencyStore.currentCurrencySymbol)
.arg(Utils.toLocaleString(model.account.balance.toFixed(2), appSettings.locale, {"model.account.currency": true}))
.arg(Utils.toLocaleString(parseFloat(model.account.balance.amount).toFixed(2), appSettings.locale, {"model.account.currency": true}))
}
// without language/model refactor no way to read currency symbol or `appSettings.locale` before user logs in
return "$%1".arg(Utils.toLocaleString(model.account.balance.toFixed(2), localAppSettings.language, {"model.account.currency": true}))
return "$%1".arg(Utils.toLocaleString(parseFloat(model.account.balance.amount).toFixed(2), localAppSettings.language, {"model.account.currency": true}))
}
wrapMode: Text.WordWrap
font.pixelSize: Constants.keycard.general.fontSize2

View File

@ -4,15 +4,20 @@ import utils 1.0
QtObject {
id: root
property var locale: Qt.locale(localAppSettings.language)
property string currentCurrency: walletSection.currentCurrency
property string currentCurrencySymbol: {
property int currentCurrencyModelIndex: {
for (var i=0; i<currenciesModel.count; i++) {
if (currenciesModel.get(i).key === currentCurrency) {
return currenciesModel.get(i).symbol;
return i;
}
}
return "";
return 0;
}
property string currentCurrencySymbol: currenciesModel.get(currentCurrencyModelIndex).symbol
property ListModel currenciesModel: ListModel {
ListElement {
key: "usd"
@ -22,6 +27,7 @@ QtObject {
category: ""
imageSource: "../../assets/twemoji/svg/1f1fa-1f1f8.svg"
selected: false
isToken: false
}
ListElement {
@ -32,6 +38,7 @@ QtObject {
category: ""
imageSource: "../../assets/twemoji/svg/1f1ec-1f1e7.svg"
selected: false
isToken: false
}
ListElement {
@ -42,6 +49,7 @@ QtObject {
category: ""
imageSource: "../../assets/twemoji/svg/1f1ea-1f1fa.svg"
selected: false
isToken: false
}
ListElement {
@ -52,6 +60,7 @@ QtObject {
category: ""
imageSource: "../../assets/twemoji/svg/1f1f7-1f1fa.svg"
selected: false
isToken: false
}
ListElement {
@ -62,6 +71,7 @@ QtObject {
category: ""
imageSource: "../../assets/twemoji/svg/1f1f0-1f1f7.svg"
selected: false
isToken: false
}
ListElement {
@ -72,6 +82,7 @@ QtObject {
category: qsTr("Tokens")
imageSource: "../../../../imports/assets/png/tokens/ETH.png"
selected: false
isToken: true
}
ListElement {
@ -82,6 +93,7 @@ QtObject {
category: qsTr("Tokens")
imageSource: "../../../../imports/assets/png/tokens/WBTC.png"
selected: false
isToken: true
}
ListElement {
@ -92,6 +104,7 @@ QtObject {
category: qsTr("Tokens")
imageSource: "../../../../imports/assets/png/tokens/SNT.png"
selected: false
isToken: true
}
ListElement {
@ -102,6 +115,7 @@ QtObject {
category: qsTr("Tokens")
imageSource: "../../../../imports/assets/png/tokens/DAI.png"
selected: false
isToken: true
}
ListElement {
@ -112,6 +126,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e6-1f1ea.svg"
selected: false
isToken: false
}
ListElement {
@ -122,6 +137,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e6-1f1eb.svg"
selected: false
isToken: false
}
ListElement {
@ -132,6 +148,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e6-1f1f7.svg"
selected: false
isToken: false
}
ListElement {
@ -142,6 +159,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e6-1f1fa.svg"
selected: false
isToken: false
}
ListElement {
@ -152,6 +170,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e7-1f1e7.svg"
selected: false
isToken: false
}
ListElement {
@ -162,6 +181,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e7-1f1e9.svg"
selected: false
isToken: false
}
ListElement {
@ -172,6 +192,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e7-1f1ec.svg"
selected: false
isToken: false
}
ListElement {
@ -182,6 +203,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e7-1f1ed.svg"
selected: false
isToken: false
}
ListElement {
@ -192,6 +214,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e7-1f1f3.svg"
selected: false
isToken: false
}
ListElement {
@ -202,6 +225,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e7-1f1f4.svg"
selected: false
isToken: false
}
ListElement {
@ -212,6 +236,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e7-1f1f7.svg"
selected: false
isToken: false
}
ListElement {
@ -222,6 +247,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e7-1f1f9.svg"
selected: false
isToken: false
}
ListElement {
@ -232,6 +258,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e8-1f1e6.svg"
selected: false
isToken: false
}
ListElement {
@ -242,6 +269,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e8-1f1ed.svg"
selected: false
isToken: false
}
ListElement {
@ -252,6 +280,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e8-1f1f1.svg"
selected: false
isToken: false
}
ListElement {
@ -262,6 +291,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e8-1f1f3.svg"
selected: false
isToken: false
}
ListElement {
@ -282,6 +312,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e8-1f1f7.svg"
selected: false
isToken: false
}
ListElement {
@ -292,6 +323,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e8-1f1ff.svg"
selected: false
isToken: false
}
ListElement {
@ -302,6 +334,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e9-1f1f0.svg"
selected: false
isToken: false
}
ListElement {
@ -312,6 +345,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1e9-1f1f4.svg"
selected: false
isToken: false
}
ListElement {
@ -322,6 +356,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ea-1f1ec.svg"
selected: false
isToken: false
}
ListElement {
@ -332,6 +367,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ea-1f1f9.svg"
selected: false
isToken: false
}
ListElement {
@ -342,6 +378,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ec-1f1ea.svg"
selected: false
isToken: false
}
ListElement {
@ -352,6 +389,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ec-1f1ed.svg"
selected: false
isToken: false
}
ListElement {
@ -362,6 +400,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ed-1f1f0.svg"
selected: false
isToken: false
}
ListElement {
@ -372,6 +411,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ed-1f1f7.svg"
selected: false
isToken: false
}
ListElement {
@ -382,6 +422,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ed-1f1fa.svg"
selected: false
isToken: false
}
ListElement {
@ -392,6 +433,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ee-1f1e9.svg"
selected: false
isToken: false
}
ListElement {
@ -402,6 +444,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ee-1f1f1.svg"
selected: false
isToken: false
}
ListElement {
@ -412,6 +455,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ee-1f1f3.svg"
selected: false
isToken: false
}
ListElement {
@ -422,6 +466,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ee-1f1f8.svg"
selected: false
isToken: false
}
ListElement {
@ -432,6 +477,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ef-1f1f2.svg"
selected: false
isToken: false
}
ListElement {
@ -442,6 +488,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ef-1f1f5.svg"
selected: false
isToken: false
}
ListElement {
@ -452,6 +499,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f0-1f1ea.svg"
selected: false
isToken: false
}
ListElement {
@ -462,6 +510,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f0-1f1fc.svg"
selected: false
isToken: false
}
ListElement {
@ -472,6 +521,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f0-1f1ff.svg"
selected: false
isToken: false
}
ListElement {
@ -482,6 +532,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f1-1f1f0.svg"
selected: false
isToken: false
}
ListElement {
@ -492,6 +543,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f2-1f1e6.svg"
selected: false
isToken: false
}
ListElement {
@ -502,6 +554,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f2-1f1e9.svg"
selected: false
isToken: false
}
ListElement {
@ -512,6 +565,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f2-1f1f7.svg"
selected: false
isToken: false
}
ListElement {
@ -522,6 +576,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f2-1f1fc.svg"
selected: false
isToken: false
}
ListElement {
@ -532,6 +587,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f2-1f1fd.svg"
selected: false
isToken: false
}
ListElement {
@ -542,6 +598,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f2-1f1fe.svg"
selected: false
isToken: false
}
ListElement {
@ -552,6 +609,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f2-1f1ff.svg"
selected: false
isToken: false
}
ListElement {
@ -562,6 +620,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f3-1f1e6.svg"
selected: false
isToken: false
}
ListElement {
@ -572,6 +631,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f3-1f1ec.svg"
selected: false
isToken: false
}
ListElement {
@ -582,6 +642,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f3-1f1f4.svg"
selected: false
isToken: false
}
ListElement {
@ -592,6 +653,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f3-1f1f5.svg"
selected: false
isToken: false
}
ListElement {
@ -602,6 +664,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f3-1f1ff.svg"
selected: false
isToken: false
}
ListElement {
@ -622,6 +685,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f5-1f1ea.svg"
selected: false
isToken: false
}
ListElement {
@ -632,6 +696,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f5-1f1ec.svg"
selected: false
isToken: false
}
ListElement {
@ -642,6 +707,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f5-1f1ed.svg"
selected: false
isToken: false
}
ListElement {
@ -652,6 +718,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f5-1f1f0.svg"
selected: false
isToken: false
}
ListElement {
@ -662,6 +729,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f5-1f1f1.svg"
selected: false
isToken: false
}
ListElement {
@ -672,6 +740,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f5-1f1fe.svg"
selected: false
isToken: false
}
ListElement {
@ -682,6 +751,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f6-1f1e6.svg"
selected: false
isToken: false
}
ListElement {
@ -692,6 +762,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f7-1f1f4.svg"
selected: false
isToken: false
}
ListElement {
@ -702,6 +773,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f7-1f1f8.svg"
selected: false
isToken: false
}
ListElement {
@ -712,6 +784,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f8-1f1e6.svg"
selected: false
isToken: false
}
ListElement {
@ -722,6 +795,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f8-1f1ea.svg"
selected: false
isToken: false
}
ListElement {
@ -732,6 +806,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f8-1f1ec.svg"
selected: false
isToken: false
}
ListElement {
@ -742,6 +817,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f9-1f1ed.svg"
selected: false
isToken: false
}
ListElement {
@ -752,6 +828,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f9-1f1f9.svg"
selected: false
isToken: false
}
ListElement {
@ -762,6 +839,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f9-1f1fc.svg"
selected: false
isToken: false
}
ListElement {
@ -772,6 +850,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f9-1f1ff.svg"
selected: false
isToken: false
}
ListElement {
@ -782,6 +861,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1f9-1f1f7.svg"
selected: false
isToken: false
}
ListElement {
@ -792,6 +872,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1fa-1f1e6.svg"
selected: false
isToken: false
}
ListElement {
@ -802,6 +883,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1fa-1f1ec.svg"
selected: false
isToken: false
}
ListElement {
@ -812,6 +894,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1fa-1f1fe.svg"
selected: false
isToken: false
}
ListElement {
@ -822,6 +905,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1fb-1f1ea.svg"
selected: false
isToken: false
}
ListElement {
@ -832,6 +916,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1fb-1f1f3.svg"
selected: false
isToken: false
}
ListElement {
@ -842,6 +927,7 @@ QtObject {
category: qsTr("Other Fiat")
imageSource: "../../assets/twemoji/svg/1f1ff-1f1e6.svg"
selected: false
isToken: false
}
}

View File

@ -23,12 +23,12 @@ QtObject {
property bool isTenorWarningAccepted: !!accountSensitiveSettings ? accountSensitiveSettings.isTenorWarningAccepted : false
property bool displayChatImages: !!accountSensitiveSettings ? accountSensitiveSettings.displayChatImages : false
property string locale: Qt.locale().name
property var locale: Qt.locale(localAppSettings.language)
// property string signingPhrase: !!walletModelInst ? walletModelInst.utilsView.signingPhrase : ""
// property string gasPrice: !!walletModelInst ? walletModelInst.gasView.gasPrice : "0"
// property string gasEthValue: !!walletModelInst ? walletModelInst.gasView.getGasEthValue : "0"
property CurrenciesStore currencyStore: CurrenciesStore { }
property CurrenciesStore currencyStore: CurrenciesStore {}
property string currentCurrency: walletSection.currentCurrency
// property string defaultCurrency: !!walletModelInst ? walletModelInst.balanceView.defaultCurrency : "0"
// property string fiatValue: !!walletModelInst ? walletModelInst.balanceView.getFiatValue : "0"

View File

@ -8,14 +8,14 @@ import "../../../app/AppLayouts/Profile/stores"
QtObject {
id: root
property CurrenciesStore currencyStore: CurrenciesStore { }
property CurrenciesStore currencyStore: CurrenciesStore {}
property ProfileSectionStore profileSectionStore: ProfileSectionStore {}
property var contactStore: profileSectionStore.contactsStore
property var mainModuleInst: mainModule
property var walletSectionTransactionsInst: walletSectionTransactions
property string locale: localAppSettings.language
property var locale: Qt.locale(localAppSettings.language)
property string currentCurrency: walletSection.currentCurrency
property var allNetworks: networksModule.all
property var accounts: walletSectionAccounts.model
@ -246,4 +246,25 @@ QtObject {
}
}
}
function getTokenBalanceOnChain(selectedAccount, chainId: int, tokenSymbol: string) {
if (!selectedAccount) {
console.warn("selectedAccount invalid")
return undefined
}
const jsonObj = selectedAccount.getTokenBalanceOnChainAsJson(chainId, tokenSymbol)
if (jsonObj === "") {
console.warn("failed to get balance, returned json is empty")
return undefined
}
const obj = JSON.parse(jsonObj)
if (obj.error) {
console.warn("failed to get balance, json parse error: ", obj.error)
return undefined
}
return obj
}
}

View File

@ -9,6 +9,7 @@ import utils 1.0
ColumnLayout {
id: root
property var locale
property var store
property var selectedAsset
property bool isLoading: false
@ -20,7 +21,7 @@ ColumnLayout {
id: d
function formatValue(value) {
const precision = (value === 0 ? 2 : 0)
return LocaleUtils.numberToLocaleString(value, precision)
return LocaleUtils.numberToLocaleString(value, precision, root.locale)
}
readonly property string fiatValue: {
if(!root.selectedAsset || !amountToReceive)

View File

@ -14,10 +14,11 @@ ColumnLayout {
property alias input: amountToSendInput
property var locale
property var selectedAsset
property bool isBridgeTx: false
property bool interactive: false
property double maxFiatBalance: -1
property var maxFiatBalance
property bool cryptoFiatFlipped: false
property string cryptoValueToSend: !cryptoFiatFlipped ? amountToSendInput.text : txtFiatBalance.text
property string currentCurrency
@ -35,7 +36,7 @@ ColumnLayout {
}
function formatValue(value, precision) {
const precisionVal = !!precision ? precision : (value === 0 ? 2 : 0)
return LocaleUtils.numberToLocaleString(value, precisionVal)
return LocaleUtils.numberToLocaleString(value, precisionVal, root.locale)
}
function getFiatValue(value) {
if(!root.selectedAsset || !value)
@ -58,7 +59,7 @@ ColumnLayout {
}
onMaxFiatBalanceChanged: {
floatValidator.top = maxFiatBalance
floatValidator.top = maxFiatBalance.amount
input.validate()
}
@ -84,7 +85,7 @@ ColumnLayout {
StatusFloatValidator {
id: floatValidator
bottom: 0
top: root.maxFiatBalance
top: root.maxFiatBalance.amount
errorMessage: ""
}
]

View File

@ -58,15 +58,18 @@ Item {
asset.name: token && token.symbol ? Style.png("tokens/%1".arg(token.symbol)) : ""
asset.isImage: true
primaryText: token ? token.name : ""
secondaryText: token ? `${token.enabledNetworkBalance} ${token.symbol}` : ""
tertiaryText: token ? "%1 %2".arg(Utils.toLocaleString(token.enabledNetworkCurrencyBalance.toFixed(2), RootStore.locale, {"currency": true})).arg(RootStore.currencyStore.currentCurrency.toUpperCase()) : ""
balances: token && token.balances ? token.balances : null
secondaryText: token ? LocaleUtils.currencyAmountToLocaleString(token.enabledNetworkBalance, RootStore.locale) : ""
tertiaryText: token ? LocaleUtils.currencyAmountToLocaleString(token.enabledNetworkCurrencyBalance, RootStore.locale) : ""
balances: token && token.balances ? token.balances : null
getNetworkColor: function(chainId){
return RootStore.getNetworkColor(chainId)
}
getNetworkIcon: function(chainId){
return RootStore.getNetworkIcon(chainId)
}
formatBalance: function(balance){
return LocaleUtils.currencyAmountToLocaleString(balance, RootStore.locale)
}
}
enum GraphType {
@ -225,7 +228,7 @@ Item {
fontColor: (Theme.palette.name === "dark") ? '#909090' : '#939BA1',
padding: 8,
callback: function(value, index, ticks) {
return LocaleUtils.numberToLocaleString(value)
return LocaleUtils.numberToLocaleString(value, -1, RootStore.locale)
},
}
}]
@ -264,23 +267,23 @@ Item {
InformationTile {
maxWidth: parent.width
primaryText: qsTr("Market Cap")
secondaryText: token && token.marketCap !== "" ? token.marketCap : "---"
secondaryText: token && token.marketCap ? LocaleUtils.currencyAmountToLocaleString(token.marketCap, RootStore.locale) : "---"
}
InformationTile {
maxWidth: parent.width
primaryText: qsTr("Day Low")
secondaryText: token && token.lowDay !== "" ? token.lowDay : "---"
secondaryText: token && token.lowDay ? LocaleUtils.currencyAmountToLocaleString(token.lowDay, RootStore.locale) : "---"
}
InformationTile {
maxWidth: parent.width
primaryText: qsTr("Day High")
secondaryText: token && token.highDay ? token.highDay : "---"
secondaryText: token && token.highDay ? LocaleUtils.currencyAmountToLocaleString(token.highDay, RootStore.locale) : "---"
}
Item {
Layout.fillWidth: true
}
InformationTile {
readonly property string changePctHour: token ? token.changePctHour : ""
readonly property string changePctHour: token ? token.changePctHour.toFixed(2) : ""
maxWidth: parent.width
primaryText: qsTr("Hour")
secondaryText: changePctHour ? "%1%".arg(changePctHour) : "---"
@ -289,7 +292,7 @@ Item {
Theme.palette.successColor1
}
InformationTile {
readonly property string changePctDay: token ? token.changePctDay : ""
readonly property string changePctDay: token ? token.changePctDay.toFixed(2) : ""
maxWidth: parent.width
primaryText: qsTr("Day")
secondaryText: changePctDay ? "%1%".arg(changePctDay) : "---"
@ -298,7 +301,7 @@ Item {
Theme.palette.successColor1
}
InformationTile {
readonly property string changePct24hour: token ? token.changePct24hour : ""
readonly property string changePct24hour: token ? token.changePct24hour.toFixed(2) : ""
maxWidth: parent.width
primaryText: qsTr("24 Hours")
secondaryText: changePct24hour ? "%1%".arg(changePct24hour) : "---"

View File

@ -18,6 +18,7 @@ Item {
property var account
property bool assetDetailsLaunched: false
property var locale
signal assetClicked(var token)
@ -43,8 +44,8 @@ Item {
delegate: TokenDelegate {
objectName: "AssetView_TokenListItem_" + symbol
readonly property string balance: enabledNetworkBalance // Needed for the tests
currentCurrencySymbol: RootStore.currencyStore.currentCurrencySymbol
locale: root.locale
readonly property string balance: "%1".arg(enabledNetworkBalance.amount) // Needed for the tests
width: ListView.view.width
onClicked: {
RootStore.getHistoricalDataForToken(symbol, RootStore.currencyStore.currentCurrency)

View File

@ -91,13 +91,14 @@ Item {
objectName: model.chainId
property double amountToSend: 0
property int routeOnNetwork: 0
property string tokenBalanceOnChain: selectedAccount && selectedAccount!== undefined && selectedAsset!== undefined ? selectedAccount.getTokenBalanceOnChain(model.chainId, selectedAsset.symbol) : ""
property bool tokenBalanceOnChainValid: selectedAccount && selectedAccount !== undefined && selectedAsset !== undefined
property var tokenBalanceOnChain: tokenBalanceOnChainValid ? root.store.getTokenBalanceOnChain(selectedAccount, model.chainId, selectedAsset.symbol) : undefined
property var hasGas: selectedAccount.hasGas(model.chainId, model.nativeCurrencySymbol, requiredGasInEth)
primaryText: model.chainName
secondaryText: (parseFloat(tokenBalanceOnChain) === 0 && root.amountToSend !== 0) ?
secondaryText: (tokenBalanceOnChain.amount === 0) && root.amountToSend !== 0 ?
qsTr("No Balance") : !hasGas ? qsTr("No Gas") : advancedInputText
tertiaryText: root.errorMode && parseFloat(advancedInputText) !== 0 && advancedInput.valid ? qsTr("EXCEEDS SEND AMOUNT"): qsTr("BALANCE: ") + LocaleUtils.numberToLocaleString(parseFloat(tokenBalanceOnChain))
tertiaryText: root.errorMode && parseFloat(advancedInputText) !== 0 && advancedInput.valid ? qsTr("EXCEEDS SEND AMOUNT"): qsTr("BALANCE: ") + LocaleUtils.currencyAmountToLocaleString(tokenBalanceOnChain, root.store.locale)
locked: store.lockedInAmounts.findIndex(lockedItem => lockedItem !== undefined && lockedItem.chainID === model.chainId) !== -1
preCalculatedAdvancedText: {
let index = store.lockedInAmounts.findIndex(lockedItem => lockedItem!== undefined && lockedItem.chainID === model.chainId)
@ -106,8 +107,8 @@ Item {
}
else return LocaleUtils.numberToLocaleString(fromNetwork.amountToSend)
}
maxAdvancedValue: parseFloat(tokenBalanceOnChain)
state: tokenBalanceOnChain === 0 || !hasGas ?
maxAdvancedValue: tokenBalanceOnChain.amount
state: tokenBalanceOnChain.amount === 0 || !hasGas ?
"unavailable" :
(root.errorMode || !advancedInput.valid) && (parseFloat(advancedInputText) !== 0) ? "error" : "default"
cardIcon.source: Style.svg(model.iconUrl)

View File

@ -126,8 +126,9 @@ RowLayout {
rightPadding: 5
implicitWidth: 150
title: chainName
subTitle: selectedAccount && selectedAccount!== undefined && selectedAsset!== undefined ?
selectedAccount.getTokenBalanceOnChain(chainId, selectedAsset.symbol) : ""
property bool tokenBalanceOnChainValid: selectedAccount && selectedAccount !== undefined && selectedAsset !== undefined
property var tokenBalanceOnChain: tokenBalanceOnChainValid ? root.store.getTokenBalanceOnChain(selectedAccount, chainId, selectedAsset.symbol) : undefined
subTitle: tokenBalanceOnChain ? LocaleUtils.currencyAmountToLocaleString(tokenBalanceOnChain, root.store.locale) : "N/A"
statusListItemSubTitle.color: Theme.palette.primaryColor1
asset.width: 32
asset.height: 32

View File

@ -22,6 +22,7 @@ Item {
implicitHeight: visible ? accountSelectionTabBar.height + stackLayout.height + Style.current.bigPadding: 0
property var store
property var locale
signal contactSelected(string address, int type)
@ -152,7 +153,7 @@ Item {
objectName: model.name
height: visible ? 64 : 0
title: !!model.name ? model.name : ""
subTitle: "%1 %2".arg(LocaleUtils.numberToLocaleString(model.currencyBalance)).arg(store.currentCurrency.toUpperCase())
subTitle: LocaleUtils.currencyAmountToLocaleString(model.currencyBalance, root.locale)
asset.emoji: !!model.emoji ? model.emoji: ""
asset.color: model.color
asset.name: !model.emoji ? "filled-account": ""

View File

@ -14,8 +14,8 @@ import "../controls"
Rectangle {
id: root
property var locale
property var assets: []
property string currentCurrencySymbol
signal tokenSelected(var selectedToken)
property var searchTokenSymbolByAddressFn: function (address) {
return ""
@ -56,7 +56,7 @@ Rectangle {
}
delegate: TokenBalancePerChainDelegate {
width: ListView.view.width
currentCurrencySymbol: root.currentCurrencySymbol
locale: root.locale
getNetworkIcon: root.getNetworkIcon
onTokenSelected: root.tokenSelected(selectedToken)
}

View File

@ -11,6 +11,11 @@ QtObject {
return num.toString().split('.')[1].length
}
function stripTrailingZeroes(numStr, locale) {
let regEx = locale.decimalPoint == "." ? /(\.[0-9]*[1-9])0+$|\.0*$/ : /(\,[0-9]*[1-9])0+$|\,0*$/
return numStr.replace(regEx, '$1')
}
function numberToLocaleString(num, precision = -1, locale = null) {
locale = locale || Qt.locale()
@ -19,4 +24,23 @@ QtObject {
return num.toLocaleString(locale, 'f', precision)
}
function currencyAmountToLocaleString(currencyAmount, locale) {
if (!locale) {
console.log("Unspecified locale for: " + JSON.stringify(currencyAmount))
locale = Qt.locale()
}
if (typeof(currencyAmount) !== "object") {
console.log("Wrong type for currencyAmount: " + JSON.stringify(currencyAmount))
return NaN
}
var amountStr = numberToLocaleString(currencyAmount.amount, currencyAmount.displayDecimals, locale)
if (currencyAmount.stripTrailingZeroes) {
amountStr = stripTrailingZeroes(amountStr, locale)
}
if (currencyAmount.symbol) {
amountStr = "%1 %2".arg(amountStr).arg(currencyAmount.symbol)
}
return amountStr
}
}

View File

@ -88,7 +88,11 @@ QtObject {
}
function toLocaleString(val, locale, options) {
return NumberPolyFill.toLocaleString(val, locale, options)
if (typeof(val) === "object") {
console.log("Wrong type for val: " + JSON.stringify(val))
return NaN
}
return NumberPolyFill.toLocaleString(val, locale, options)
}
function isOnlyEmoji(inputText) {

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit 883f9677c593494eceadef004932c0434575a5be
Subproject commit 77a56e2b930c52709d462aa5add764014cc16a09