parent
e3499c2e26
commit
d560b1264d
|
@ -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
|
|
@ -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(
|
||||
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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue