From cc2a96e2ef8d61f79bb5f8f0ab92a964714555c1 Mon Sep 17 00:00:00 2001 From: 9qeklajc Date: Tue, 14 Jul 2026 21:59:43 +0200 Subject: [PATCH] make trusted mint available for lightning topup --- routstr/lightning.py | 16 ++++++++++++---- .../integration/test_lightning_invoice_rip08.py | 8 +++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/routstr/lightning.py b/routstr/lightning.py index fafffef9..c4bc2b20 100644 --- a/routstr/lightning.py +++ b/routstr/lightning.py @@ -71,6 +71,14 @@ class InvoiceRecoverRequest(BaseModel): bolt11: str = Field(description="BOLT11 invoice string") +def _trusted_mint_candidates() -> list[str]: + return [ + mint + for mint in dict.fromkeys([settings.primary_mint, *settings.cashu_mints]) + if mint + ] + + async def _request_mint_with_fallback( amount_sats: int, *, @@ -167,13 +175,13 @@ async def create_invoice( try: description = f"Routstr {request.purpose} {request.amount_sats} sats" - # An API key is backed by one mint. A top-up must use that same mint; - # falling back to another would create mixed-mint collateral that the - # current single refund_mint_url field cannot account for or refund. allowed_mints = None if request.purpose == "topup": assert topup_api_key is not None - allowed_mints = [topup_api_key.refund_mint_url or settings.primary_mint] + # Top-ups are not pinned to the key's previous/backing mint. Use any + # currently available trusted mint so rate limits/cooldowns on one + # mint do not block Lightning top-ups. + allowed_mints = _trusted_mint_candidates() bolt11, payment_hash, mint_url = await generate_lightning_invoice( request.amount_sats, description, allowed_mints=allowed_mints ) diff --git a/tests/integration/test_lightning_invoice_rip08.py b/tests/integration/test_lightning_invoice_rip08.py index 766d0176..99634f12 100644 --- a/tests/integration/test_lightning_invoice_rip08.py +++ b/tests/integration/test_lightning_invoice_rip08.py @@ -16,6 +16,7 @@ from httpx import AsyncClient from sqlmodel.ext.asyncio.session import AsyncSession from routstr.core.db import ApiKey +from routstr.core.settings import settings RIP08_PATH = "/lightning/invoice" LEGACY_PATH = "/v1/balance/lightning/invoice" @@ -101,9 +102,10 @@ async def test_topup_with_authorization_header( body = resp.json() assert body["amount_sats"] == 500 assert body["bolt11"].startswith("lnbc") - assert patch_invoice_generation.call_args.kwargs["allowed_mints"] == [ - "http://localhost:3338" - ] + expected_mints = [settings.primary_mint, *settings.cashu_mints] + allowed_mints = patch_invoice_generation.call_args.kwargs["allowed_mints"] + assert allowed_mints == list(dict.fromkeys(mint for mint in expected_mints if mint)) + assert allowed_mints[0] == settings.primary_mint @pytest.mark.integration