Merge pull request #663 from lnbits/lnurlp/float_fiat_amount
lnurlp: support for floating point fiat values
This commit is contained in:
commit
399ff11b04
5 changed files with 36 additions and 13 deletions
|
|
@ -9,6 +9,12 @@ async def create_pay_link(data: CreatePayLinkData, wallet_id: str) -> PayLink:
|
||||||
|
|
||||||
returning = "" if db.type == SQLITE else "RETURNING ID"
|
returning = "" if db.type == SQLITE else "RETURNING ID"
|
||||||
method = db.execute if db.type == SQLITE else db.fetchone
|
method = db.execute if db.type == SQLITE else db.fetchone
|
||||||
|
# database only allows int4 entries for min and max. For fiat currencies,
|
||||||
|
# we multiply by data.fiat_base_multiplier (usually 100) to save the value in cents.
|
||||||
|
if data.currency and data.fiat_base_multiplier:
|
||||||
|
data.min *= data.fiat_base_multiplier
|
||||||
|
data.max *= data.fiat_base_multiplier
|
||||||
|
|
||||||
result = await (method)(
|
result = await (method)(
|
||||||
f"""
|
f"""
|
||||||
INSERT INTO lnurlp.pay_links (
|
INSERT INTO lnurlp.pay_links (
|
||||||
|
|
@ -22,9 +28,10 @@ async def create_pay_link(data: CreatePayLinkData, wallet_id: str) -> PayLink:
|
||||||
success_text,
|
success_text,
|
||||||
success_url,
|
success_url,
|
||||||
comment_chars,
|
comment_chars,
|
||||||
currency
|
currency,
|
||||||
|
fiat_base_multiplier
|
||||||
)
|
)
|
||||||
VALUES (?, ?, ?, ?, 0, 0, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, 0, 0, ?, ?, ?, ?, ?, ?)
|
||||||
{returning}
|
{returning}
|
||||||
""",
|
""",
|
||||||
(
|
(
|
||||||
|
|
@ -37,6 +44,7 @@ async def create_pay_link(data: CreatePayLinkData, wallet_id: str) -> PayLink:
|
||||||
data.success_url,
|
data.success_url,
|
||||||
data.comment_chars,
|
data.comment_chars,
|
||||||
data.currency,
|
data.currency,
|
||||||
|
data.fiat_base_multiplier,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
if db.type == SQLITE:
|
if db.type == SQLITE:
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,15 @@ async def api_lnurl_response(request: Request, link_id):
|
||||||
status_code=HTTPStatus.NOT_FOUND, detail="Pay link does not exist."
|
status_code=HTTPStatus.NOT_FOUND, detail="Pay link does not exist."
|
||||||
)
|
)
|
||||||
|
|
||||||
rate = await get_fiat_rate_satoshis(link.currency) if link.currency else 1
|
rate = (
|
||||||
|
await get_fiat_rate_satoshis(link.currency) / link.fiat_base_multiplier
|
||||||
|
if link.currency
|
||||||
|
else 1
|
||||||
|
)
|
||||||
|
|
||||||
resp = LnurlPayResponse(
|
resp = LnurlPayResponse(
|
||||||
callback=request.url_for("lnurlp.api_lnurl_callback", link_id=link.id),
|
callback=request.url_for("lnurlp.api_lnurl_callback", link_id=link.id),
|
||||||
min_sendable=math.ceil(link.min * rate) * 1000,
|
min_sendable=round(link.min * rate) * 1000,
|
||||||
max_sendable=round(link.max * rate) * 1000,
|
max_sendable=round(link.max * rate) * 1000,
|
||||||
metadata=link.lnurlpay_metadata,
|
metadata=link.lnurlpay_metadata,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -50,3 +50,13 @@ async def m003_min_max_comment_fiat(db):
|
||||||
await db.execute("ALTER TABLE lnurlp.pay_links ADD COLUMN max INTEGER;")
|
await db.execute("ALTER TABLE lnurlp.pay_links ADD COLUMN max INTEGER;")
|
||||||
await db.execute("UPDATE lnurlp.pay_links SET max = min;")
|
await db.execute("UPDATE lnurlp.pay_links SET max = min;")
|
||||||
await db.execute("DROP TABLE lnurlp.invoices")
|
await db.execute("DROP TABLE lnurlp.invoices")
|
||||||
|
|
||||||
|
|
||||||
|
async def m004_fiat_base_multiplier(db):
|
||||||
|
"""
|
||||||
|
Store the multiplier for fiat prices. We store the price in cents and
|
||||||
|
remember to multiply by 100 when we use it to convert to Dollars.
|
||||||
|
"""
|
||||||
|
await db.execute(
|
||||||
|
"ALTER TABLE lnurlp.pay_links ADD COLUMN fiat_base_multiplier INTEGER DEFAULT 1;"
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -11,20 +11,21 @@ from pydantic import BaseModel
|
||||||
|
|
||||||
class CreatePayLinkData(BaseModel):
|
class CreatePayLinkData(BaseModel):
|
||||||
description: str
|
description: str
|
||||||
min: int = Query(0.01, ge=0.01)
|
min: float = Query(1, ge=0.01)
|
||||||
max: int = Query(0.01, ge=0.01)
|
max: float = Query(1, ge=0.01)
|
||||||
currency: str = Query(None)
|
currency: str = Query(None)
|
||||||
comment_chars: int = Query(0, ge=0, lt=800)
|
comment_chars: int = Query(0, ge=0, lt=800)
|
||||||
webhook_url: str = Query(None)
|
webhook_url: str = Query(None)
|
||||||
success_text: str = Query(None)
|
success_text: str = Query(None)
|
||||||
success_url: str = Query(None)
|
success_url: str = Query(None)
|
||||||
|
fiat_base_multiplier: int = Query(100, ge=1)
|
||||||
|
|
||||||
|
|
||||||
class PayLink(BaseModel):
|
class PayLink(BaseModel):
|
||||||
id: int
|
id: int
|
||||||
wallet: str
|
wallet: str
|
||||||
description: str
|
description: str
|
||||||
min: int
|
min: float
|
||||||
served_meta: int
|
served_meta: int
|
||||||
served_pr: int
|
served_pr: int
|
||||||
webhook_url: Optional[str]
|
webhook_url: Optional[str]
|
||||||
|
|
@ -32,11 +33,15 @@ class PayLink(BaseModel):
|
||||||
success_url: Optional[str]
|
success_url: Optional[str]
|
||||||
currency: Optional[str]
|
currency: Optional[str]
|
||||||
comment_chars: int
|
comment_chars: int
|
||||||
max: int
|
max: float
|
||||||
|
fiat_base_multiplier: int
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_row(cls, row: Row) -> "PayLink":
|
def from_row(cls, row: Row) -> "PayLink":
|
||||||
data = dict(row)
|
data = dict(row)
|
||||||
|
if data["currency"] and data["fiat_base_multiplier"]:
|
||||||
|
data["min"] /= data["fiat_base_multiplier"]
|
||||||
|
data["max"] /= data["fiat_base_multiplier"]
|
||||||
return cls(**data)
|
return cls(**data)
|
||||||
|
|
||||||
def lnurl(self, req: Request) -> str:
|
def lnurl(self, req: Request) -> str:
|
||||||
|
|
|
||||||
|
|
@ -76,10 +76,6 @@ async def api_link_create_or_update(
|
||||||
link_id=None,
|
link_id=None,
|
||||||
wallet: WalletTypeInfo = Depends(get_key_type),
|
wallet: WalletTypeInfo = Depends(get_key_type),
|
||||||
):
|
):
|
||||||
if data.min < 1:
|
|
||||||
raise HTTPException(
|
|
||||||
detail="Min must be more than 1.", status_code=HTTPStatus.BAD_REQUEST
|
|
||||||
)
|
|
||||||
|
|
||||||
if data.min > data.max:
|
if data.min > data.max:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -87,7 +83,7 @@ async def api_link_create_or_update(
|
||||||
)
|
)
|
||||||
|
|
||||||
if data.currency == None and (
|
if data.currency == None and (
|
||||||
round(data.min) != data.min or round(data.max) != data.max
|
round(data.min) != data.min or round(data.max) != data.max or data.min < 1
|
||||||
):
|
):
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
detail="Must use full satoshis.", status_code=HTTPStatus.BAD_REQUEST
|
detail="Must use full satoshis.", status_code=HTTPStatus.BAD_REQUEST
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue