Update get_account_balance to use sum(weight) for SATS

Replace sum(position) with sum(weight) for efficient SATS aggregation
from price notation. Also return fiat amount from sum(number).

This simplifies the parsing logic and provides consistent SATS totals
across all BQL-based balance methods.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
padreug 2025-12-15 01:10:46 +01:00
parent 048d19f90b
commit 49d18c3e73
2 changed files with 27 additions and 22 deletions

View file

@ -111,13 +111,16 @@ class FavaClient:
"""
Get balance for a specific account (excluding pending transactions).
Uses sum(weight) for efficient SATS aggregation from price notation.
Args:
account_name: Full account name (e.g., "Assets:Receivable:User-abc123")
Returns:
Dict with:
- sats: int (balance in satoshis)
- positions: dict (currency amount with cost basis)
- sats: int (balance in satoshis from weight column)
- fiat: Decimal (balance in fiat currency from number column)
- fiat_currency: str (currency code, defaults to EUR)
Note:
Excludes pending transactions (flag='!') from balance calculation.
@ -125,12 +128,13 @@ class FavaClient:
Example:
balance = await fava_client.get_account_balance("Assets:Receivable:User-abc")
# Returns: {
# "sats": 200000,
# "positions": {"SATS": {"{100.00 EUR}": 200000}}
# }
# Returns: {"sats": 200000, "fiat": Decimal("150.00"), "fiat_currency": "EUR"}
"""
query = f"SELECT sum(position) WHERE account = '{account_name}' AND flag != '!'"
from decimal import Decimal
# Use sum(weight) for SATS and sum(number) for fiat
# Note: BQL doesn't support != operator, so use flag = '*' to exclude pending
query = f"SELECT sum(number), sum(weight) WHERE account = '{account_name}' AND flag = '*'"
try:
async with httpx.AsyncClient(timeout=self.timeout) as client:
@ -141,26 +145,26 @@ class FavaClient:
response.raise_for_status()
data = response.json()
if not data['data']['rows']:
return {"sats": 0, "positions": {}}
if not data['data']['rows'] or not data['data']['rows'][0]:
return {"sats": 0, "fiat": Decimal(0), "fiat_currency": "EUR"}
# Fava returns: [[account, {"SATS": {cost: amount}}]]
positions = data['data']['rows'][0][1] if data['data']['rows'] else {}
row = data['data']['rows'][0]
fiat_sum = row[0] if len(row) > 0 else 0
weight_sum = row[1] if len(row) > 1 else {}
# Sum up all SATS positions
# Parse fiat amount
fiat_amount = Decimal(str(fiat_sum)) if fiat_sum else Decimal(0)
# Parse SATS from weight column
total_sats = 0
if isinstance(positions, dict) and "SATS" in positions:
sats_positions = positions["SATS"]
if isinstance(sats_positions, dict):
# Sum all amounts (with different cost bases)
total_sats = sum(int(amount) for amount in sats_positions.values())
elif isinstance(sats_positions, (int, float)):
# Simple number (no cost basis)
total_sats = int(sats_positions)
if isinstance(weight_sum, dict) and "SATS" in weight_sum:
sats_value = weight_sum["SATS"]
total_sats = int(Decimal(str(sats_value)))
return {
"sats": total_sats,
"positions": positions
"fiat": fiat_amount,
"fiat_currency": "EUR" # Default, could be extended to detect currency
}
except httpx.HTTPStatusError as e: