Skip to content

Commit

Permalink
fix(@desktop/wallet): cache currency format
Browse files Browse the repository at this point in the history
Fixes #9132
  • Loading branch information
dlipicar committed Jan 16, 2023
1 parent e3499c2 commit d560b12
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 36 deletions.
22 changes: 22 additions & 0 deletions src/app_service/common/cache.nim
Original file line number Diff line number Diff line change
@@ -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
41 changes: 31 additions & 10 deletions src/app_service/service/currency/service.nim
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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
Expand All @@ -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(
symbol: toUpperAscii(symbol),
displayDecimals: getFiatDisplayDecimals(symbol),
stripTrailingZeroes: false
)
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)
26 changes: 18 additions & 8 deletions src/app_service/service/token/service.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand All @@ -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:
Expand Down Expand Up @@ -130,19 +130,29 @@ QtObject:
proc getTokenPriceCacheKey(crypto: string, fiat: string) : string =
return renameSymbol(crypto) & renameSymbol(fiat)

proc getTokenPrice*(self: Service, crypto: string, fiat: string, fetchIfNotAvailable: bool = true): float64 =
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.isCached(cacheKey) or (self.priceCache.hasKey(cacheKey) and not fetchIfNotAvailable):
return parseFloat(self.priceCache.get(cacheKey))
elif not fetchIfNotAvailable:
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):
return self.priceCache.get(cacheKey)
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:
prices[symbol] = initTable[string, float]()
for (currency, price) in pricePerCurrency.pairs:
prices[symbol][currency] = price.getFloat

Expand All @@ -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:
Expand Down
18 changes: 0 additions & 18 deletions src/backend/cache.nim

This file was deleted.

0 comments on commit d560b12

Please sign in to comment.