From b7008495b86db1082ed85b981fe4ceed2d848d52 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Fri, 10 Jun 2022 15:35:35 +0200 Subject: [PATCH 1/3] lnurlp: support for floating point fiat values --- lnbits/extensions/lnurlp/crud.py | 6 ++++++ lnbits/extensions/lnurlp/lnurl.py | 4 ++-- lnbits/extensions/lnurlp/models.py | 11 +++++++---- lnbits/extensions/lnurlp/views_api.py | 6 +----- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lnbits/extensions/lnurlp/crud.py b/lnbits/extensions/lnurlp/crud.py index 4215faf6..0559e063 100644 --- a/lnbits/extensions/lnurlp/crud.py +++ b/lnbits/extensions/lnurlp/crud.py @@ -9,6 +9,12 @@ async def create_pay_link(data: CreatePayLinkData, wallet_id: str) -> PayLink: returning = "" if db.type == SQLITE else "RETURNING ID" 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 100 to save the value in cents. + if data.currency: + data.min *= 100 + data.max *= 100 + result = await (method)( f""" INSERT INTO lnurlp.pay_links ( diff --git a/lnbits/extensions/lnurlp/lnurl.py b/lnbits/extensions/lnurlp/lnurl.py index 173b4823..b193aa44 100644 --- a/lnbits/extensions/lnurlp/lnurl.py +++ b/lnbits/extensions/lnurlp/lnurl.py @@ -29,11 +29,11 @@ async def api_lnurl_response(request: Request, link_id): 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) / 100 if link.currency else 1 resp = LnurlPayResponse( 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, metadata=link.lnurlpay_metadata, ) diff --git a/lnbits/extensions/lnurlp/models.py b/lnbits/extensions/lnurlp/models.py index 6fc9cc1a..6d0b0ee0 100644 --- a/lnbits/extensions/lnurlp/models.py +++ b/lnbits/extensions/lnurlp/models.py @@ -11,8 +11,8 @@ from pydantic import BaseModel class CreatePayLinkData(BaseModel): description: str - min: int = Query(0.01, ge=0.01) - max: int = Query(0.01, ge=0.01) + min: float = Query(1, ge=0.01) + max: float = Query(1, ge=0.01) currency: str = Query(None) comment_chars: int = Query(0, ge=0, lt=800) webhook_url: str = Query(None) @@ -24,7 +24,7 @@ class PayLink(BaseModel): id: int wallet: str description: str - min: int + min: float served_meta: int served_pr: int webhook_url: Optional[str] @@ -32,11 +32,14 @@ class PayLink(BaseModel): success_url: Optional[str] currency: Optional[str] comment_chars: int - max: int + max: float @classmethod def from_row(cls, row: Row) -> "PayLink": data = dict(row) + if data["currency"]: + data["min"] /= 100 + data["max"] /= 100 return cls(**data) def lnurl(self, req: Request) -> str: diff --git a/lnbits/extensions/lnurlp/views_api.py b/lnbits/extensions/lnurlp/views_api.py index ff6e96e2..52d729a9 100644 --- a/lnbits/extensions/lnurlp/views_api.py +++ b/lnbits/extensions/lnurlp/views_api.py @@ -76,10 +76,6 @@ async def api_link_create_or_update( link_id=None, 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: raise HTTPException( @@ -87,7 +83,7 @@ async def api_link_create_or_update( ) 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( detail="Must use full satoshis.", status_code=HTTPStatus.BAD_REQUEST From 6617450c2146fdc77e5dc477ce361bf14b2a18ac Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Fri, 10 Jun 2022 16:05:33 +0200 Subject: [PATCH 2/3] store fiat_base_multiplier in db --- lnbits/extensions/lnurlp/crud.py | 14 ++++++++------ lnbits/extensions/lnurlp/migrations.py | 10 ++++++++++ lnbits/extensions/lnurlp/models.py | 7 ++++--- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/lnbits/extensions/lnurlp/crud.py b/lnbits/extensions/lnurlp/crud.py index 0559e063..2eda3322 100644 --- a/lnbits/extensions/lnurlp/crud.py +++ b/lnbits/extensions/lnurlp/crud.py @@ -10,10 +10,10 @@ async def create_pay_link(data: CreatePayLinkData, wallet_id: str) -> PayLink: returning = "" if db.type == SQLITE else "RETURNING ID" 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 100 to save the value in cents. - if data.currency: - data.min *= 100 - data.max *= 100 + # 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)( f""" @@ -28,9 +28,10 @@ async def create_pay_link(data: CreatePayLinkData, wallet_id: str) -> PayLink: success_text, success_url, comment_chars, - currency + currency, + fiat_base_multiplier ) - VALUES (?, ?, ?, ?, 0, 0, ?, ?, ?, ?, ?) + VALUES (?, ?, ?, ?, 0, 0, ?, ?, ?, ?, ?, ?) {returning} """, ( @@ -43,6 +44,7 @@ async def create_pay_link(data: CreatePayLinkData, wallet_id: str) -> PayLink: data.success_url, data.comment_chars, data.currency, + data.fiat_base_multiplier, ), ) if db.type == SQLITE: diff --git a/lnbits/extensions/lnurlp/migrations.py b/lnbits/extensions/lnurlp/migrations.py index 428bde2c..81dd62f8 100644 --- a/lnbits/extensions/lnurlp/migrations.py +++ b/lnbits/extensions/lnurlp/migrations.py @@ -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("UPDATE lnurlp.pay_links SET max = min;") 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;" + ) diff --git a/lnbits/extensions/lnurlp/models.py b/lnbits/extensions/lnurlp/models.py index 6d0b0ee0..c4cae5eb 100644 --- a/lnbits/extensions/lnurlp/models.py +++ b/lnbits/extensions/lnurlp/models.py @@ -18,6 +18,7 @@ class CreatePayLinkData(BaseModel): webhook_url: str = Query(None) success_text: str = Query(None) success_url: str = Query(None) + fiat_base_multiplier: int = Query(100, ge=1) class PayLink(BaseModel): @@ -37,9 +38,9 @@ class PayLink(BaseModel): @classmethod def from_row(cls, row: Row) -> "PayLink": data = dict(row) - if data["currency"]: - data["min"] /= 100 - data["max"] /= 100 + if data["currency"] and data["fiat_base_multiplier"]: + data["min"] /= data["fiat_base_multiplier"] + data["max"] /= data["fiat_base_multiplier"] return cls(**data) def lnurl(self, req: Request) -> str: From c5ddd1a2c685463abce2b9b12251fc1956ba6353 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Fri, 10 Jun 2022 16:08:29 +0200 Subject: [PATCH 3/3] fiat_base_multiplier also in rate conversion --- lnbits/extensions/lnurlp/lnurl.py | 6 +++++- lnbits/extensions/lnurlp/models.py | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lnbits/extensions/lnurlp/lnurl.py b/lnbits/extensions/lnurlp/lnurl.py index b193aa44..9052b99b 100644 --- a/lnbits/extensions/lnurlp/lnurl.py +++ b/lnbits/extensions/lnurlp/lnurl.py @@ -29,7 +29,11 @@ async def api_lnurl_response(request: Request, link_id): status_code=HTTPStatus.NOT_FOUND, detail="Pay link does not exist." ) - rate = await get_fiat_rate_satoshis(link.currency) / 100 if link.currency else 1 + rate = ( + await get_fiat_rate_satoshis(link.currency) / link.fiat_base_multiplier + if link.currency + else 1 + ) resp = LnurlPayResponse( callback=request.url_for("lnurlp.api_lnurl_callback", link_id=link.id), diff --git a/lnbits/extensions/lnurlp/models.py b/lnbits/extensions/lnurlp/models.py index c4cae5eb..bd121cc8 100644 --- a/lnbits/extensions/lnurlp/models.py +++ b/lnbits/extensions/lnurlp/models.py @@ -34,6 +34,7 @@ class PayLink(BaseModel): currency: Optional[str] comment_chars: int max: float + fiat_base_multiplier: int @classmethod def from_row(cls, row: Row) -> "PayLink":