From cdd00bf747ee97f4e80a5b02aa02b029011596d1 Mon Sep 17 00:00:00 2001 From: padreug Date: Mon, 15 Sep 2025 00:52:52 +0200 Subject: [PATCH] Implement QR code generation for LNURL payment links in WalletPage - Added functionality to generate a QR code for the first available pay link using LNURL encoding. - Introduced reactive properties to manage QR code state and generation status. - Updated the onMounted lifecycle hook to generate the QR code upon component mount if a pay link is available. - Enhanced the UI to display the generated QR code along with payment range and lightning address information. These changes improve the user experience by facilitating quick payment link sharing through QR codes. --- src/modules/wallet/views/WalletPage.vue | 106 +++++++++++++++++++++++- 1 file changed, 104 insertions(+), 2 deletions(-) diff --git a/src/modules/wallet/views/WalletPage.vue b/src/modules/wallet/views/WalletPage.vue index 54ad90c..4312377 100644 --- a/src/modules/wallet/views/WalletPage.vue +++ b/src/modules/wallet/views/WalletPage.vue @@ -12,6 +12,7 @@ import CurrencyDisplay from '@/components/ui/CurrencyDisplay.vue' import ReceiveDialog from '../components/ReceiveDialog.vue' import SendDialog from '../components/SendDialog.vue' import { format } from 'date-fns' +import { nip19 } from 'nostr-tools' // Services const walletService = injectService(SERVICE_TOKENS.WALLET_SERVICE) as any @@ -22,6 +23,8 @@ const authService = injectService(SERVICE_TOKENS.AUTH_SERVICE) as any const showReceiveDialog = ref(false) const showSendDialog = ref(false) const selectedTab = ref('transactions') +const defaultQrCode = ref(null) +const isGeneratingQR = ref(false) // Computed const transactions = computed(() => walletService?.transactions?.value || []) @@ -35,6 +38,9 @@ const totalBalance = computed(() => { }, 0) }) +const payLinks = computed(() => walletService?.payLinks?.value || []) +const firstPayLink = computed(() => payLinks.value[0] || null) + // Get transactions grouped by date const groupedTransactions = computed(() => { const groups: Record = {} @@ -60,6 +66,10 @@ async function refresh() { await walletService?.refresh() // Also refresh auth data to update balance await authService?.refresh() + // Regenerate QR if pay link is available + if (firstPayLink.value) { + await generateDefaultQR() + } } function getTransactionIcon(type: string, status: string) { @@ -77,9 +87,44 @@ function getTransactionColor(type: string, status: string) { } +// QR Code generation +function encodeLNURL(url: string): string { + try { + // Convert URL to bytes + const bytes = new TextEncoder().encode(url) + // Encode as bech32 with 'lnurl' prefix + const bech32 = nip19.encodeBytes('lnurl', bytes) + // Return with lightning: prefix in uppercase + return `lightning:${bech32.toUpperCase()}` + } catch (error) { + console.error('Failed to encode LNURL:', error) + return url // Fallback to original URL + } +} + +async function generateDefaultQR() { + if (!firstPayLink.value?.lnurl) return + + isGeneratingQR.value = true + try { + // Encode LNURL with proper bech32 format and lightning: prefix + const encodedLNURL = encodeLNURL(firstPayLink.value.lnurl) + // Use the existing PaymentService QR code generation + defaultQrCode.value = await paymentService?.generateQRCode(encodedLNURL) + } catch (error) { + console.error('Failed to generate default QR code:', error) + } finally { + isGeneratingQR.value = false + } +} + // Initialize on mount -onMounted(() => { - refresh() +onMounted(async () => { + await refresh() + // Generate QR for first pay link if available + if (firstPayLink.value) { + await generateDefaultQR() + } }) @@ -143,6 +188,63 @@ onMounted(() => { + + + + + + Quick Receive + + {{ firstPayLink.description }} + + +
+ +
+
+ +
+
+ LNURL QR Code +
+
+ +
+
+ + +
+
+

Payment Range

+
+ {{ firstPayLink.min?.toLocaleString() }} - {{ firstPayLink.max?.toLocaleString() }} sats +
+
+ +
+

Lightning Address

+
+ {{ firstPayLink.lnaddress }} +
+
+ + +
+
+
+
+