Skip to content

Commit 8a20df7

Browse files
PatMulliganclaude
andauthored
FIX: generate LNURL server-side for unique voucher links (#68)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 68ff753 commit 8a20df7

File tree

5 files changed

+19
-3
lines changed

5 files changed

+19
-3
lines changed

models.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ class WithdrawLink(BaseModel):
4747
"Example: lnurlw://${window.location.hostname}/lnurlw/${id}"
4848
),
4949
)
50+
lnurl_url: str | None = Field(
51+
default=None,
52+
no_database=True,
53+
description="The raw LNURL callback URL (use for QR code generation)",
54+
)
5055

5156
@property
5257
def is_spent(self) -> bool:

static/js/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ window.app = Vue.createApp({
138138
const link = _.findWhere(this.withdrawLinks, {id: linkId})
139139
this.qrCodeDialog.data = _.clone(link)
140140
this.qrCodeDialog.show = true
141-
this.activeUrl = `${window.location.origin}/withdraw/api/v1/lnurl/${link.unique_hash}`
141+
this.activeUrl = link.lnurl_url
142142
},
143143
openUpdateDialog(linkId) {
144144
let link = _.findWhere(this.withdrawLinks, {id: linkId})

templates/withdraw/display.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ <h6 class="text-subtitle1 q-mb-sm q-mt-none">
5555
data() {
5656
return {
5757
spent: {{ 'true' if spent else 'false' }},
58-
url: `${window.location.origin}/withdraw/api/v1/lnurl/{{ unique_hash }}`,
58+
url: '{{ lnurl_url }}',
5959
lnurl: '',
6060
nfcTagWriting: false
6161
}

views.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,20 @@ async def display(request: Request, link_id):
3333
status_code=HTTPStatus.NOT_FOUND, detail="Withdraw link does not exist."
3434
)
3535

36+
try:
37+
lnurl = create_lnurl(link, request)
38+
except ValueError as exc:
39+
raise HTTPException(
40+
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
41+
detail=str(exc),
42+
) from exc
43+
3644
return withdraw_renderer().TemplateResponse(
3745
"withdraw/display.html",
3846
{
3947
"request": request,
4048
"spent": link.is_spent,
41-
"unique_hash": link.unique_hash,
49+
"lnurl_url": str(lnurl.url),
4250
},
4351
)
4452

views_api.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ async def api_links(
4545
detail=str(exc),
4646
) from exc
4747
linkk.lnurl = str(lnurl.bech32)
48+
linkk.lnurl_url = str(lnurl.url)
4849

4950
return links
5051

@@ -75,6 +76,7 @@ async def api_link_retrieve(
7576
detail=str(exc),
7677
) from exc
7778
link.lnurl = str(lnurl.bech32)
79+
link.lnurl_url = str(lnurl.url)
7880
return link
7981

8082

@@ -166,6 +168,7 @@ async def api_link_create_or_update(
166168
) from exc
167169

168170
link.lnurl = str(lnurl.bech32)
171+
link.lnurl_url = str(lnurl.url)
169172

170173
return link
171174

0 commit comments

Comments
 (0)