From 9821be0406a0bd7ae5aed578a872fe0a7266e430 Mon Sep 17 00:00:00 2001 From: padreug Date: Sun, 22 Jun 2025 16:02:43 +0200 Subject: [PATCH] Enhance client dashboard summary: Add current fiat value of Bitcoin holdings and wallet currency to the summary metrics. Update model and frontend to display current value and unrealized gains/losses, improving financial insights for users. --- crud.py | 22 +++++++++++++++++++++- models.py | 1 + static/js/index.js | 14 ++++++++++++++ templates/satmachineclient/index.html | 26 ++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/crud.py b/crud.py index aeb7c81..f20baf7 100644 --- a/crud.py +++ b/crud.py @@ -4,6 +4,8 @@ from typing import List, Optional from datetime import datetime, timedelta from lnbits.db import Database +from lnbits.utils.exchange_rates import satoshis_amount_as_fiat +from lnbits.core.crud.wallets import get_wallet from .models import ( ClientDashboardSummary, @@ -32,6 +34,13 @@ async def get_client_dashboard_summary(user_id: str) -> Optional[ClientDashboard if not client: return None + # Get wallet to determine currency + wallet = await get_wallet(client["wallet_id"]) + # TODO: Get currency from wallet; bit more difficult to do in a different + # currency than deposit cause of cross exchange rates + # currency = wallet.currency or "GTQ" # Default to GTQ if no currency set + currency = "GTQ" # Default to GTQ if no currency set + # Get total sats accumulated from DCA transactions sats_result = await db.fetchone( """ @@ -95,17 +104,28 @@ async def get_client_dashboard_summary(user_id: str) -> Optional[ClientDashboard remaining_balance = confirmed_deposits - dca_spent # Remaining = deposits - DCA spending avg_cost_basis = total_sats / dca_spent if dca_spent > 0 else 0 # Cost basis = sats / fiat spent + # Calculate current fiat value of total sats + current_sats_fiat_value = 0.0 + if total_sats > 0: + try: + current_sats_fiat_value = await satoshis_amount_as_fiat(total_sats, currency) + except Exception as e: + print(f"Warning: Could not fetch exchange rate for {currency}: {e}") + current_sats_fiat_value = 0.0 + return ClientDashboardSummary( user_id=user_id, total_sats_accumulated=total_sats, total_fiat_invested=total_invested, # Sum of confirmed deposits pending_fiat_deposits=pending_deposits, # Sum of pending deposits + current_sats_fiat_value=current_sats_fiat_value, # Current fiat value of sats average_cost_basis=avg_cost_basis, current_fiat_balance=remaining_balance, # Confirmed deposits - DCA spent total_transactions=tx_stats["tx_count"] if tx_stats else 0, dca_mode=client["dca_mode"], dca_status=client["status"], - last_transaction_date=tx_stats["last_tx_date"] if tx_stats else None + last_transaction_date=tx_stats["last_tx_date"] if tx_stats else None, + currency=currency # Wallet's currency ) diff --git a/models.py b/models.py index 3104ead..543c5b4 100644 --- a/models.py +++ b/models.py @@ -13,6 +13,7 @@ class ClientDashboardSummary(BaseModel): total_sats_accumulated: int total_fiat_invested: int # Confirmed deposits pending_fiat_deposits: int # Pending deposits awaiting confirmation + current_sats_fiat_value: float # Current fiat value of total sats average_cost_basis: float # Average sats per fiat unit current_fiat_balance: int # Available balance for DCA total_transactions: int diff --git a/static/js/index.js b/static/js/index.js index 6002076..d36528b 100644 --- a/static/js/index.js +++ b/static/js/index.js @@ -21,6 +21,20 @@ window.app = Vue.createApp({ }).format(amount); }, + formatCurrencyWithCode(amount, currencyCode) { + if (!amount) return `${currencyCode} 0.00`; + // Format with the provided currency code + try { + return new Intl.NumberFormat('en-US', { + style: 'currency', + currency: currencyCode, + }).format(amount); + } catch (error) { + // Fallback if currency code is not supported + return `${currencyCode} ${amount.toFixed(2)}`; + } + }, + formatDate(dateString) { if (!dateString) return '' return new Date(dateString).toLocaleDateString() diff --git a/templates/satmachineclient/index.html b/templates/satmachineclient/index.html index 40f2a05..0756cf3 100644 --- a/templates/satmachineclient/index.html +++ b/templates/satmachineclient/index.html @@ -57,6 +57,32 @@ + +
+
+ + +
${formatCurrencyWithCode(dashboardData.current_sats_fiat_value, dashboardData.currency)}
+
Current Value of Bitcoin Holdings
+
at today's ${dashboardData.currency} exchange rate
+
+
+
+
+ + +
+ ${dashboardData.current_sats_fiat_value > (dashboardData.total_fiat_invested / 100) ? '+' : ''} + ${formatCurrencyWithCode(dashboardData.current_sats_fiat_value - (dashboardData.total_fiat_invested / 100), dashboardData.currency)} +
+
+ ${dashboardData.current_sats_fiat_value > (dashboardData.total_fiat_invested / 100) ? 'Unrealized Gain' : 'Unrealized Loss'} +
+
vs total invested
+
+
+
+