Repository: lnbits/lnbits

Issue:
[Feature request] make lnurl payable with a fiat amount
https://t.me/decentraleyes: `when i pay xyz@mydomain.com via pASTE REQUEST/READ  it asks for sats however i want to be able to enter a FIAT amt.
can someone point me to the area of code that i could chane to make that happen? or could i Pay someone to make that change? If someone needs 1000 pesos its too darn hard to figure out how many sats taht is`

there is a bounty. :)


Discussion:
This mockup was shared by dni on Telegram.

I think it is fine, I just suggest we also add amount in satoshi (circled in red) when paying not in satoshi but with fiat amount.
We need to compute this value anyway, because we need to check whether it fits within the requested range, so we could as well show it (and we should).

![aaaaaaaa](https://github.com/lnbits/lnbits/assets/42201/8d2c16b0-5176-4872-bfd7-20b52b5e0cee)

hm, i dont know, i agree it would be better to preview that sats, but i am not sure if we have rates on the frontend?
rn, i am doing it on the fly before request the lnurl invoice.

Resolving patch:
diff --git a/lnbits/core/models.py b/lnbits/core/models.py
--- a/lnbits/core/models.py
+++ b/lnbits/core/models.py
@@ -368,6 +368,7 @@ class CreateLnurl(BaseModel):
     amount: int
     comment: Optional[str] = None
     description: Optional[str] = None
+    unit: Optional[str] = None
 
 
 class CreateInvoice(BaseModel):
diff --git a/lnbits/core/views/api.py b/lnbits/core/views/api.py
--- a/lnbits/core/views/api.py
+++ b/lnbits/core/views/api.py
@@ -4,6 +4,7 @@
 import uuid
 from http import HTTPStatus
 from io import BytesIO
+from math import ceil
 from typing import Dict, List, Optional, Union
 from urllib.parse import ParseResult, parse_qs, urlencode, urlparse, urlunparse
 
@@ -408,9 +409,15 @@ async def api_payments_pay_lnurl(
     headers = {"User-Agent": settings.user_agent}
     async with httpx.AsyncClient(headers=headers, follow_redirects=True) as client:
         try:
+            if data.unit and data.unit != "sat":
+                amount_msat = await fiat_amount_as_satoshis(data.amount, data.unit)
+                # no msat precision
+                amount_msat = ceil(amount_msat // 1000) * 1000
+            else:
+                amount_msat = data.amount
             r = await client.get(
                 data.callback,
-                params={"amount": data.amount, "comment": data.comment},
+                params={"amount": amount_msat, "comment": data.comment},
                 timeout=40,
             )
             if r.is_error:
@@ -436,13 +443,13 @@ async def api_payments_pay_lnurl(
         )
 
     invoice = bolt11.decode(params["pr"])
-    if invoice.amount_msat != data.amount:
+    if invoice.amount_msat != amount_msat:
         raise HTTPException(
             status_code=HTTPStatus.BAD_REQUEST,
             detail=(
                 (
                     f"{domain} returned an invalid invoice. Expected"
-                    f" {data.amount} msat, got {invoice.amount_msat}."
+                    f" {amount_msat} msat, got {invoice.amount_msat}."
                 ),
             ),
         )
@@ -453,6 +460,9 @@ async def api_payments_pay_lnurl(
         extra["success_action"] = params["successAction"]
     if data.comment:
         extra["comment"] = data.comment
+    if data.unit and data.unit != "sat":
+        extra["fiat_currency"] = data.unit
+        extra["fiat_amount"] = data.amount / 1000
     assert data.description is not None, "description is required"
     payment_hash = await pay_invoice(
         wallet_id=wallet.wallet.id,


Test patch: