fix(@desktop/wallet): cache currency format

Fixes #9132
This commit is contained in:
Dario Gabriel Lipicar 2023-01-16 09:51:32 -03:00 committed by dlipicar
parent e3499c2e26
commit d560b1264d
4 changed files with 71 additions and 36 deletions

View File

@ -0,0 +1,22 @@
import tables, times
export tables, times
type Value*[T] = ref object
value*: T
timestamp*: DateTime
type TimedCache*[T] = Table[string, Value[T]]
proc newTimedCache*[T](): TimedCache[T] = initTable[string, Value[T]]()
proc getTimestamp[T](self: TimedCache[T], cacheKey: string): DateTime = self[cacheKey].timestamp
proc isCached*[T](self: TimedCache[T], cacheKey: string, duration=initDuration(minutes = 5)): bool =
self.hasKey(cacheKey) and ((self.getTimestamp(cacheKey) + duration) >= now())
proc set*[T](self: var TimedCache[T], cacheKey: string, value: T) =
self[cacheKey] = Value[T](value: value, timestamp: now())
proc get*[T](self: TimedCache[T], cacheKey: string): T = self[cacheKey].value

View File

@ -1,7 +1,8 @@
import NimQml, strformat, strutils
import NimQml, strformat, strutils, tables
import ../settings/service as settings_service
import ../token/service as token_service
import ./dto, ./utils
import ../../common/cache
export dto
@ -11,6 +12,9 @@ QtObject:
type Service* = ref object of QObject
tokenService: token_service.Service
settingsService: settings_service.Service
isCurrencyFiatCache: Table[string, bool] # Fiat info does not change, we can fetch/calculate once and
fiatCurrencyFormatCache: Table[string, CurrencyFormatDto] # keep the results forever.
tokenCurrencyFormatCache: TimedCache[CurrencyFormatDto] # Token format changes with price, so we use a timed cache.
proc delete*(self: Service) =
self.QObject.delete
@ -23,33 +27,50 @@ QtObject:
result.QObject.setup
result.tokenService = tokenService
result.settingsService = settingsService
result.tokenCurrencyFormatCache = newTimedCache[CurrencyFormatDto]()
proc init*(self: Service) =
discard
proc isCurrencyFiat(self: Service, symbol: string): bool =
if not self.isCurrencyFiatCache.hasKey(symbol):
self.isCurrencyFiatCache[symbol] = isCurrencyFiat(symbol)
return self.isCurrencyFiatCache[symbol]
proc getFiatCurrencyFormat(self: Service, symbol: string): CurrencyFormatDto =
return CurrencyFormatDto(
if not self.fiatCurrencyFormatCache.hasKey(symbol):
self.fiatCurrencyFormatCache[symbol] = CurrencyFormatDto(
symbol: toUpperAscii(symbol),
displayDecimals: getFiatDisplayDecimals(symbol),
stripTrailingZeroes: false
)
return self.fiatCurrencyFormatCache[symbol]
proc getTokenCurrencyFormat(self: Service, symbol: string): CurrencyFormatDto =
if self.tokenCurrencyFormatCache.isCached(symbol):
return self.tokenCurrencyFormatCache.get(symbol)
var updateCache = true
let pegSymbol = self.tokenService.getTokenPegSymbol(symbol)
if pegSymbol != "":
var currencyFormat = self.getFiatCurrencyFormat(pegSymbol)
currencyFormat.symbol = symbol
return currencyFormat
result = currencyFormat
updateCache = true
else:
let price = self.tokenService.getTokenPrice(symbol, DECIMALS_CALCULATION_CURRENCY, false)
return CurrencyFormatDto(
let price = self.tokenService.getCachedTokenPrice(symbol, DECIMALS_CALCULATION_CURRENCY)
result = CurrencyFormatDto(
symbol: symbol,
displayDecimals: getTokenDisplayDecimals(price),
stripTrailingZeroes: true
)
updateCache = self.tokenService.isCachedTokenPriceRecent(symbol, DECIMALS_CALCULATION_CURRENCY)
if updateCache:
self.tokenCurrencyFormatCache.set(symbol, result)
proc getCurrencyFormat*(self: Service, symbol: string): CurrencyFormatDto =
if isCurrencyFiat(symbol):
if self.isCurrencyFiat(symbol):
return self.getFiatCurrencyFormat(symbol)
else:
return self.getTokenCurrencyFormat(symbol)

View File

@ -11,7 +11,7 @@ import ../../../app/global/global_singleton
import ../../../app/core/eventemitter
import ../../../app/core/tasks/[qt, threadpool]
import ../../../backend/cache
import ../../common/cache
import ./dto
export dto
@ -39,7 +39,7 @@ QtObject:
threadpool: ThreadPool
networkService: network_service.Service
tokens: Table[int, seq[TokenDto]]
priceCache: TimedCache
priceCache: TimedCache[float64]
proc updateCachedTokenPrice(self: Service, crypto: string, fiat: string, price: float64)
@ -57,7 +57,7 @@ QtObject:
result.threadpool = threadpool
result.networkService = networkService
result.tokens = initTable[int, seq[TokenDto]]()
result.priceCache = newTimedCache()
result.priceCache = newTimedCache[float64]()
proc init*(self: Service) =
try:
@ -130,12 +130,21 @@ QtObject:
proc getTokenPriceCacheKey(crypto: string, fiat: string) : string =
return renameSymbol(crypto) & renameSymbol(fiat)
proc isCachedTokenPriceRecent*(self: Service, crypto: string, fiat: string): bool =
let cacheKey = getTokenPriceCacheKey(crypto, fiat)
return self.priceCache.isCached(cacheKey)
proc getCachedTokenPrice*(self: Service, crypto: string, fiat: string): float64 =
let cacheKey = getTokenPriceCacheKey(crypto, fiat)
if self.priceCache.hasKey(cacheKey):
return self.priceCache.get(cacheKey)
else:
return 0.0
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
if self.priceCache.isCached(cacheKey):
return self.priceCache.get(cacheKey)
var prices = initTable[string, Table[string, float]]()
try:
@ -143,6 +152,7 @@ QtObject:
let fiatKey = renameSymbol(fiat)
let response = backend.fetchPrices(@[cryptoKey], @[fiatKey])
for (symbol, pricePerCurrency) in response.result.pairs:
prices[symbol] = initTable[string, float]()
for (currency, price) in pricePerCurrency.pairs:
prices[symbol][currency] = price.getFloat
@ -155,7 +165,7 @@ QtObject:
proc updateCachedTokenPrice(self: Service, crypto: string, fiat: string, price: float64) =
let cacheKey = getTokenPriceCacheKey(crypto, fiat)
self.priceCache.set(cacheKey, $price)
self.priceCache.set(cacheKey, price)
proc getTokenPegSymbol*(self: Service, symbol: string): string =
for _, tokens in self.tokens:

View File

@ -1,18 +0,0 @@
import tables, times
type Value* = ref object
value*: string
timestamp*: DateTime
type TimedCache* = Table[string, Value]
proc newTimedCache*(): TimedCache = initTable[string, Value]()
proc isCached*(self: TimedCache, cacheKey: string, duration=initDuration(minutes = 5)): bool =
self.hasKey(cacheKey) and ((self[cacheKey].timestamp + duration) >= now())
proc set*(self: var TimedCache, cacheKey: string, value: string) =
self[cacheKey] = Value(value: value, timestamp: now())
proc get*(self: var TimedCache, cacheKey: string): string = self[cacheKey].value