Compare commits

..

No commits in common. "9a9539224c6bf109445f75dece45be56a585c7ab" and "f0f224fd3fbad8e410d365ba3582940e4fb01a78" have entirely different histories.

2 changed files with 17 additions and 18 deletions

View file

@ -106,16 +106,16 @@ def stubs(monkeypatch):
async def get_wallet(wallet_id):
return state["wallet"]
def cache_get(key, default=None):
# A warm LNbits rate cache: 1 BTC = 80,000 USD → 123456 sats = 98.7648
return 80_000.0 if key == "btc-price-USD" else default
async def satoshis_amount_as_fiat(amount, currency):
assert currency == "USD"
return amount * 0.0008 # 123456 sats → 98.7648
monkeypatch.setattr(v, "get_card_by_external_id", get_card_by_external_id)
monkeypatch.setattr(v, "update_card_counter", update_card_counter)
monkeypatch.setattr(v, "get_hits_today", get_hits_today)
monkeypatch.setattr(v, "create_hit", create_hit)
monkeypatch.setattr(v, "get_wallet", get_wallet)
monkeypatch.setattr(v.cache, "get", cache_get)
monkeypatch.setattr(v, "satoshis_amount_as_fiat", satoshis_amount_as_fiat)
monkeypatch.setattr(
v.settings, "lnbits_default_accounting_currency", state["default_currency"]
)
@ -209,18 +209,18 @@ async def test_session_falls_back_to_instance_default_currency(stubs, monkeypatc
p, c = make_sun(counter=6)
out = await v.api_session(p, c, FakeRequest(), "ext123")
assert out["currency"] == "USD"
assert out["fiat"] == pytest.approx(5 / 100_000_000 * 80_000)
assert out["fiat"] == pytest.approx(5 * 0.0008)
@pytest.mark.asyncio
async def test_session_leaves_fiat_null_on_a_cold_rate_cache(stubs, monkeypatch):
# No external rate lookup ever happens on the unlock path: a cache miss
# simply means the terminal prices the balance itself.
monkeypatch.setattr(v.cache, "get", lambda key, default=None: default)
async def test_session_survives_rate_failure(stubs, monkeypatch):
async def boom(amount, currency):
raise ValueError("no rate")
monkeypatch.setattr(v, "satoshis_amount_as_fiat", boom)
p, c = make_sun(counter=6)
out = await v.api_session(p, c, FakeRequest(), "ext123")
assert out["authenticated"] is True
assert out["currency"] == "USD"
assert out["fiat"] is None

View file

@ -8,7 +8,7 @@ from fastapi import APIRouter, HTTPException, Query, Request
from lnbits.core.crud import get_wallet
from lnbits.core.services import create_invoice, pay_invoice
from lnbits.settings import settings
from lnbits.utils.cache import cache
from lnbits.utils.exchange_rates import satoshis_amount_as_fiat
from lnurl import (
CallbackUrl,
LightningInvoice,
@ -507,10 +507,8 @@ async def api_session(p, c, request: Request, external_id: str):
# Balance + fiat, the way the LNbits wallet page shows them: the wallet's
# own currency first (per-wallet setting, LNbits ≥ 1.6), then the
# instance's default accounting currency. The fiat figure comes ONLY from
# LNbits' already-warm rate cache: this response gates the terminal
# unlocking, and a cold lookup queries external exchanges (~1 s). Cache
# miss → `fiat: null`; the terminal prices the sats itself.
# instance's default accounting currency; no currency → no fiat, and a
# rate failure never fails the session.
wallet = await get_wallet(card.wallet)
balance_msat = int(wallet.balance_msat) if wallet else 0
currency = (getattr(wallet, "currency", None) if wallet else None) or getattr(
@ -518,9 +516,10 @@ async def api_session(p, c, request: Request, external_id: str):
)
fiat = None
if currency:
price = cache.get(f"btc-price-{currency}") # fiat per BTC, as btc_price()
if isinstance(price, (int, float)) and price > 0:
fiat = balance_msat / 1000 / 100_000_000 * float(price)
try:
fiat = await satoshis_amount_as_fiat(balance_msat / 1000, currency)
except Exception:
fiat = None
return {
"authenticated": True,