diff --git a/lnbits/app.py b/lnbits/app.py index d9f2d9f6..e3c46f69 100644 --- a/lnbits/app.py +++ b/lnbits/app.py @@ -26,6 +26,7 @@ from lnbits.core.helpers import migrate_extension_database from lnbits.core.services.extensions import deactivate_extension, get_valid_extensions from lnbits.core.tasks import ( # watchdog_task audit_queue, + collect_exchange_rates_data, killswitch_task, purge_audit_data, wait_for_audit_data, @@ -455,6 +456,7 @@ def register_async_tasks(app: FastAPI): # create_permanent_task(watchdog_task) create_permanent_task(killswitch_task) create_permanent_task(purge_audit_data) + create_permanent_task(collect_exchange_rates_data) # server logs for websocket if settings.lnbits_admin_ui: diff --git a/lnbits/core/crud/settings.py b/lnbits/core/crud/settings.py index 39a0bc80..026eec89 100644 --- a/lnbits/core/crud/settings.py +++ b/lnbits/core/crud/settings.py @@ -4,6 +4,7 @@ from typing import Any, Optional from loguru import logger from lnbits.core.db import db +from lnbits.db import dict_to_model from lnbits.settings import ( AdminSettings, EditableSettings, @@ -18,7 +19,8 @@ async def get_super_settings() -> Optional[SuperSettings]: if data: super_user = await get_settings_field("super_user") super_user_id = super_user.value if super_user else None - return SuperSettings(**{"super_user": super_user_id, **data}) + settings_dict = {"super_user": super_user_id, **data} + return dict_to_model(settings_dict, SuperSettings) return None diff --git a/lnbits/core/services/settings.py b/lnbits/core/services/settings.py index 08e9f43f..8fa6c570 100644 --- a/lnbits/core/services/settings.py +++ b/lnbits/core/services/settings.py @@ -3,6 +3,7 @@ from loguru import logger from py_vapid import Vapid from py_vapid.utils import b64urlencode +from lnbits.db import dict_to_model from lnbits.settings import ( EditableSettings, readonly_variables, @@ -37,14 +38,16 @@ async def check_webpush_settings(): def update_cached_settings(sets_dict: dict): - for key, value in sets_dict.items(): + editable_settings = dict_to_model(sets_dict, EditableSettings) + for key in sets_dict.keys(): if key in readonly_variables: continue if key not in settings.dict().keys(): continue try: + value = getattr(editable_settings, key) setattr(settings, key, value) except Exception: - logger.warning(f"Failed overriding setting: {key}, value: {value}") + logger.warning(f"Failed overriding setting: {key}.") if "super_user" in sets_dict: settings.super_user = sets_dict["super_user"] diff --git a/lnbits/core/tasks.py b/lnbits/core/tasks.py index 2bbdf291..cf5ffeab 100644 --- a/lnbits/core/tasks.py +++ b/lnbits/core/tasks.py @@ -19,6 +19,7 @@ from lnbits.core.services import ( ) from lnbits.settings import get_funding_source, settings from lnbits.tasks import send_push_notification +from lnbits.utils.exchange_rates import btc_rates api_invoice_listeners: Dict[str, asyncio.Queue] = {} audit_queue: asyncio.Queue = asyncio.Queue() @@ -188,3 +189,27 @@ async def purge_audit_data(): # clean every hour await asyncio.sleep(60 * 60) + + +async def collect_exchange_rates_data(): + """ + Collect exchange rates data. Used for monitoring only. + """ + while settings.lnbits_running: + currency = settings.lnbits_default_accounting_currency or "USD" + max_history_size = settings.lnbits_exchange_history_size + sleep_time = settings.lnbits_exchange_history_refresh_interval_seconds + + if sleep_time > 0: + try: + rates = await btc_rates(currency) + if rates: + rates_values = [r[1] for r in rates] + lnbits_rate = sum(rates_values) / len(rates_values) + rates.append(("LNbits", lnbits_rate)) + settings.append_exchange_rate_datapoint(dict(rates), max_history_size) + except Exception as ex: + logger.warning(ex) + else: + sleep_time = 60 + await asyncio.sleep(sleep_time) diff --git a/lnbits/core/templates/admin/_tab_exchange_providers.html b/lnbits/core/templates/admin/_tab_exchange_providers.html new file mode 100644 index 00000000..90d2e2e2 --- /dev/null +++ b/lnbits/core/templates/admin/_tab_exchange_providers.html @@ -0,0 +1,195 @@ + +
Exchange Providers
+ +
+
+
+ +
+
+
+ + + + +
    +
  • + Refresh Interval and History Size are for + historical purposes only. +
  • +
  • These two settings do not affect the live price computation.
  • +
  • + Chart currency: + +
  • +
+
+
+ +
+
+ + +
+
+ + +
+
+ + + + + + + + +
+
+ + +
+
+
+
diff --git a/lnbits/core/templates/admin/index.html b/lnbits/core/templates/admin/index.html index e77e0936..9970d6cd 100644 --- a/lnbits/core/templates/admin/index.html +++ b/lnbits/core/templates/admin/index.html @@ -63,7 +63,12 @@