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 ../settings/service as settings_service
|
||||||
import ../token/service as token_service
|
import ../token/service as token_service
|
||||||
import ./dto, ./utils
|
import ./dto, ./utils
|
||||||
|
import ../../common/cache
|
||||||
|
|
||||||
export dto
|
export dto
|
||||||
|
|
||||||
|
@ -11,6 +12,9 @@ QtObject:
|
||||||
type Service* = ref object of QObject
|
type Service* = ref object of QObject
|
||||||
tokenService: token_service.Service
|
tokenService: token_service.Service
|
||||||
settingsService: settings_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) =
|
proc delete*(self: Service) =
|
||||||
self.QObject.delete
|
self.QObject.delete
|
||||||
|
@ -23,33 +27,50 @@ QtObject:
|
||||||
result.QObject.setup
|
result.QObject.setup
|
||||||
result.tokenService = tokenService
|
result.tokenService = tokenService
|
||||||
result.settingsService = settingsService
|
result.settingsService = settingsService
|
||||||
|
result.tokenCurrencyFormatCache = newTimedCache[CurrencyFormatDto]()
|
||||||
|
|
||||||
proc init*(self: Service) =
|
proc init*(self: Service) =
|
||||||
discard
|
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 =
|
proc getFiatCurrencyFormat(self: Service, symbol: string): CurrencyFormatDto =
|
||||||
return CurrencyFormatDto(
|
if not self.fiatCurrencyFormatCache.hasKey(symbol):
|
||||||
|
self.fiatCurrencyFormatCache[symbol] = CurrencyFormatDto(
|
||||||
symbol: toUpperAscii(symbol),
|
symbol: toUpperAscii(symbol),
|
||||||
displayDecimals: getFiatDisplayDecimals(symbol),
|
displayDecimals: getFiatDisplayDecimals(symbol),
|
||||||
stripTrailingZeroes: false
|
stripTrailingZeroes: false
|
||||||
)
|
)
|
||||||
|
return self.fiatCurrencyFormatCache[symbol]
|
||||||
|
|
||||||
proc getTokenCurrencyFormat(self: Service, symbol: string): CurrencyFormatDto =
|
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)
|
let pegSymbol = self.tokenService.getTokenPegSymbol(symbol)
|
||||||
if pegSymbol != "":
|
if pegSymbol != "":
|
||||||
var currencyFormat = self.getFiatCurrencyFormat(pegSymbol)
|
var currencyFormat = self.getFiatCurrencyFormat(pegSymbol)
|
||||||
currencyFormat.symbol = symbol
|
currencyFormat.symbol = symbol
|
||||||
return currencyFormat
|
result = currencyFormat
|
||||||
|
updateCache = true
|
||||||
else:
|
else:
|
||||||
let price = self.tokenService.getTokenPrice(symbol, DECIMALS_CALCULATION_CURRENCY, false)
|
let price = self.tokenService.getCachedTokenPrice(symbol, DECIMALS_CALCULATION_CURRENCY)
|
||||||
return CurrencyFormatDto(
|
result = CurrencyFormatDto(
|
||||||
symbol: symbol,
|
symbol: symbol,
|
||||||
displayDecimals: getTokenDisplayDecimals(price),
|
displayDecimals: getTokenDisplayDecimals(price),
|
||||||
stripTrailingZeroes: true
|
stripTrailingZeroes: true
|
||||||
)
|
)
|
||||||
|
updateCache = self.tokenService.isCachedTokenPriceRecent(symbol, DECIMALS_CALCULATION_CURRENCY)
|
||||||
|
|
||||||
|
if updateCache:
|
||||||
|
self.tokenCurrencyFormatCache.set(symbol, result)
|
||||||
|
|
||||||
proc getCurrencyFormat*(self: Service, symbol: string): CurrencyFormatDto =
|
proc getCurrencyFormat*(self: Service, symbol: string): CurrencyFormatDto =
|
||||||
if isCurrencyFiat(symbol):
|
if self.isCurrencyFiat(symbol):
|
||||||
return self.getFiatCurrencyFormat(symbol)
|
return self.getFiatCurrencyFormat(symbol)
|
||||||
else:
|
else:
|
||||||
return self.getTokenCurrencyFormat(symbol)
|
return self.getTokenCurrencyFormat(symbol)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import ../../../app/global/global_singleton
|
||||||
|
|
||||||
import ../../../app/core/eventemitter
|
import ../../../app/core/eventemitter
|
||||||
import ../../../app/core/tasks/[qt, threadpool]
|
import ../../../app/core/tasks/[qt, threadpool]
|
||||||
import ../../../backend/cache
|
import ../../common/cache
|
||||||
import ./dto
|
import ./dto
|
||||||
|
|
||||||
export dto
|
export dto
|
||||||
|
@ -39,7 +39,7 @@ QtObject:
|
||||||
threadpool: ThreadPool
|
threadpool: ThreadPool
|
||||||
networkService: network_service.Service
|
networkService: network_service.Service
|
||||||
tokens: Table[int, seq[TokenDto]]
|
tokens: Table[int, seq[TokenDto]]
|
||||||
priceCache: TimedCache
|
priceCache: TimedCache[float64]
|
||||||
|
|
||||||
proc updateCachedTokenPrice(self: Service, crypto: string, fiat: string, price: float64)
|
proc updateCachedTokenPrice(self: Service, crypto: string, fiat: string, price: float64)
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ QtObject:
|
||||||
result.threadpool = threadpool
|
result.threadpool = threadpool
|
||||||
result.networkService = networkService
|
result.networkService = networkService
|
||||||
result.tokens = initTable[int, seq[TokenDto]]()
|
result.tokens = initTable[int, seq[TokenDto]]()
|
||||||
result.priceCache = newTimedCache()
|
result.priceCache = newTimedCache[float64]()
|
||||||
|
|
||||||
proc init*(self: Service) =
|
proc init*(self: Service) =
|
||||||
try:
|
try:
|
||||||
|
@ -130,12 +130,21 @@ QtObject:
|
||||||
proc getTokenPriceCacheKey(crypto: string, fiat: string) : string =
|
proc getTokenPriceCacheKey(crypto: string, fiat: string) : string =
|
||||||
return renameSymbol(crypto) & renameSymbol(fiat)
|
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 =
|
proc getTokenPrice*(self: Service, crypto: string, fiat: string, fetchIfNotAvailable: bool = true): float64 =
|
||||||
let cacheKey = getTokenPriceCacheKey(crypto, fiat)
|
let cacheKey = getTokenPriceCacheKey(crypto, fiat)
|
||||||
if self.priceCache.isCached(cacheKey) or (self.priceCache.hasKey(cacheKey) and not fetchIfNotAvailable):
|
if self.priceCache.isCached(cacheKey):
|
||||||
return parseFloat(self.priceCache.get(cacheKey))
|
return self.priceCache.get(cacheKey)
|
||||||
elif not fetchIfNotAvailable:
|
|
||||||
return 0.0
|
|
||||||
var prices = initTable[string, Table[string, float]]()
|
var prices = initTable[string, Table[string, float]]()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -143,6 +152,7 @@ QtObject:
|
||||||
let fiatKey = renameSymbol(fiat)
|
let fiatKey = renameSymbol(fiat)
|
||||||
let response = backend.fetchPrices(@[cryptoKey], @[fiatKey])
|
let response = backend.fetchPrices(@[cryptoKey], @[fiatKey])
|
||||||
for (symbol, pricePerCurrency) in response.result.pairs:
|
for (symbol, pricePerCurrency) in response.result.pairs:
|
||||||
|
prices[symbol] = initTable[string, float]()
|
||||||
for (currency, price) in pricePerCurrency.pairs:
|
for (currency, price) in pricePerCurrency.pairs:
|
||||||
prices[symbol][currency] = price.getFloat
|
prices[symbol][currency] = price.getFloat
|
||||||
|
|
||||||
|
@ -155,7 +165,7 @@ QtObject:
|
||||||
|
|
||||||
proc updateCachedTokenPrice(self: Service, crypto: string, fiat: string, price: float64) =
|
proc updateCachedTokenPrice(self: Service, crypto: string, fiat: string, price: float64) =
|
||||||
let cacheKey = getTokenPriceCacheKey(crypto, fiat)
|
let cacheKey = getTokenPriceCacheKey(crypto, fiat)
|
||||||
self.priceCache.set(cacheKey, $price)
|
self.priceCache.set(cacheKey, price)
|
||||||
|
|
||||||
proc getTokenPegSymbol*(self: Service, symbol: string): string =
|
proc getTokenPegSymbol*(self: Service, symbol: string): string =
|
||||||
for _, tokens in self.tokens:
|
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