mirror of
https://git.wownero.com/wowlet/wowlet-backend.git
synced 2024-08-15 01:03:13 +00:00
feather-ws -> wowlet-backend
This commit is contained in:
parent
04e10f6d2b
commit
abfe22e89c
20 changed files with 72 additions and 75 deletions
114
wowlet_backend/tasks/historical_prices.py
Normal file
114
wowlet_backend/tasks/historical_prices.py
Normal file
|
@ -0,0 +1,114 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (c) 2020, The Monero Project.
|
||||
# Copyright (c) 2020, dsc@xmr.pm
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import json
|
||||
from typing import List, Union
|
||||
from datetime import datetime
|
||||
|
||||
import aiofiles
|
||||
|
||||
import settings
|
||||
from wowlet_backend.utils import httpget
|
||||
from wowlet_backend.tasks import FeatherTask
|
||||
|
||||
|
||||
class HistoricalPriceTask(FeatherTask):
|
||||
"""
|
||||
This class manages a historical price (USD) database, saved in a
|
||||
textfile at `self._path`. A Feather wallet instance will ask
|
||||
for the historical fiat price database on startup (but only
|
||||
in chunks of a month for anti-fingerprinting reasons).
|
||||
|
||||
The task in this class simply keeps the fiat database
|
||||
up-to-date locally.
|
||||
"""
|
||||
def __init__(self, interval: int = 43200):
|
||||
super(HistoricalPriceTask, self).__init__(interval)
|
||||
|
||||
self._cache_key = f"historical_fiat"
|
||||
self._path = f"data/historical_prices_{settings.COIN_SYMBOL}.json"
|
||||
self._http_endpoint = f"https://www.coingecko.com/price_charts/{settings.COIN_NAME}/usd/max.json"
|
||||
|
||||
self._year_genesis = int(settings.COIN_GENESIS_DATE[:4])
|
||||
|
||||
asyncio.create_task(self._load())
|
||||
|
||||
async def task(self) -> Union[dict, None]:
|
||||
content = await httpget(self._http_endpoint, json=True, raise_for_status=False)
|
||||
if "stats" not in content:
|
||||
raise Exception()
|
||||
|
||||
stats: List[List] = content.get('stats', []) # [[timestamp,USD],]
|
||||
if not stats:
|
||||
return
|
||||
|
||||
data = {
|
||||
year: {
|
||||
month: {} for month in range(1, 13)
|
||||
} for year in range(self._year_genesis, datetime.now().year + 1)
|
||||
}
|
||||
|
||||
# timestamp:USD
|
||||
daily_price_blob = {day[0]: day[1] for day in stats}
|
||||
|
||||
# normalize
|
||||
for timestamp, usd in daily_price_blob.items():
|
||||
_date = datetime.fromtimestamp(timestamp / 1000)
|
||||
data[_date.year].setdefault(_date.month, {})
|
||||
data[_date.year][_date.month][_date.day] = usd
|
||||
|
||||
# update local database
|
||||
await self._write(data)
|
||||
return data
|
||||
|
||||
async def _load(self) -> None:
|
||||
if not os.path.exists(self._path):
|
||||
return
|
||||
|
||||
async with aiofiles.open(self._path, mode="r") as f:
|
||||
content = await f.read()
|
||||
blob = json.loads(content)
|
||||
|
||||
# ¯\_(ツ)_/¯
|
||||
blob = {int(k): {
|
||||
int(_k): {
|
||||
int(__k): __v for __k, __v in _v.items()
|
||||
} for _k, _v in v.items()
|
||||
} for k, v in blob.items()}
|
||||
|
||||
await self.cache_set(self._cache_key, blob)
|
||||
|
||||
async def _write(self, blob: dict) -> None:
|
||||
data = json.dumps(blob, sort_keys=True, indent=4)
|
||||
async with aiofiles.open(self._path, mode="w") as f:
|
||||
await f.write(data)
|
||||
|
||||
@staticmethod
|
||||
async def get(year: int, month: int = None) -> Union[dict, None]:
|
||||
"""This function is called when a Feather wallet client asks
|
||||
for (a range of) historical fiat information. It returns the
|
||||
data filtered by the parameters."""
|
||||
from wowlet_backend.factory import cache
|
||||
|
||||
blob = await cache.get("historical_fiat")
|
||||
blob = json.loads(blob)
|
||||
if year not in blob:
|
||||
return
|
||||
|
||||
rtn = {}
|
||||
if not month:
|
||||
for _m, days in blob[year].items():
|
||||
for day, price in days.items():
|
||||
rtn[datetime(year, _m, day).strftime('%Y%m%d')] = price
|
||||
return rtn
|
||||
|
||||
if month not in blob[year]:
|
||||
return
|
||||
|
||||
for day, price in blob[year][month].items():
|
||||
rtn[datetime(year, month, day).strftime('%Y%m%d')] = price
|
||||
|
||||
return rtn
|
Loading…
Add table
Add a link
Reference in a new issue