From 254fbd26f2de709d865c0e1130dfcf64540b234f Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Sun, 1 Mar 2026 15:36:18 -0500 Subject: [PATCH] =?UTF-8?q?fix(machine):=20UI=20polish=20=E2=80=94=20fiat?= =?UTF-8?q?=20rate=20display,=2015s=20receipt=20with=20QR,=20remove=20CLIN?= =?UTF-8?q?K?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Show exchange rate as fiat/BTC (e.g. Q615,000/BTC) instead of sats/fiat - Show USD/BTC rate when currency != USD - Complete screen stays 15s (was 3s) with txid QR code for receipt photo - Add "Done" button for manual dismiss on complete screen - Remove CLINK ndebit UI (mode selector, pubkey entry) pending k1 fix (#23) - Remove askForReceipt/sendingReceipt screens (npub scan not active, #36) - Remove negative sign on commission display - Set timezone to America/Guatemala Co-Authored-By: Claude Opus 4.6 --- apps/machine/src/views/CashInView.vue | 266 ++++++++----------------- apps/machine/src/views/CashOutView.vue | 127 ++++++------ deploy/nixos/configuration.nix | 2 +- packages/state-machine/src/machine.ts | 14 +- 4 files changed, 162 insertions(+), 247 deletions(-) diff --git a/apps/machine/src/views/CashInView.vue b/apps/machine/src/views/CashInView.vue index 3f069a2..4b7eb45 100644 --- a/apps/machine/src/views/CashInView.vue +++ b/apps/machine/src/views/CashInView.vue @@ -45,17 +45,12 @@ const showCancelButton = computed(() => { return false }) -// CLINK Debit: customer's npub/pubkey -const pubkeyInput = ref('') - // Invoice input for manual payment const invoiceInput = ref('') // Copy state for ndebit URI const copied = ref(false) -// QR display mode: unified (default), lnurl-only, or clink-only -const qrMode = ref<'unified' | 'lnurl' | 'clink'>('unified') const lnurlWithdraw = ref(null) const isGeneratingLnurl = ref(false) @@ -77,32 +72,9 @@ watch( { immediate: true } ) -// Compute the unified QR value (lightning + clink on separate lines) -const unifiedQrValue = computed(() => { - const ndebit = atmStore.context?.ndebitUri - const lnurl = lnurlWithdraw.value - - if (lnurl && ndebit) { - // Unified: lightning scheme first (more universal), then clink - return `lightning:${lnurl}\n${ndebit}` - } else if (lnurl) { - return `lightning:${lnurl}` - } else if (ndebit) { - return ndebit - } - return null -}) - -// Get the appropriate QR value based on mode +// QR value — LNURL-withdraw only (CLINK ndebit disabled until k1 single-use fix) const currentQrValue = computed(() => { - switch (qrMode.value) { - case 'unified': - return unifiedQrValue.value - case 'lnurl': - return lnurlWithdraw.value ? `lightning:${lnurlWithdraw.value}` : null - case 'clink': - return atmStore.context?.ndebitUri || null - } + return lnurlWithdraw.value ? `lightning:${lnurlWithdraw.value}` : null }) // Copy current QR value to clipboard @@ -142,10 +114,6 @@ function finishInserting() { atmStore.finishInserting() } -function skipReceipt() { - atmStore.skipReceipt() -} - // Check if a bill denomination can still be accepted without exceeding available balance function canAcceptBill(denomination: number): boolean { const ctx = context.value @@ -168,29 +136,6 @@ function simulateBill(denomination: number) { atmStore.insertBill(denomination) } -// Convert npub to hex pubkey if needed -function normalizePubkey(input: string): string { - const trimmed = input.trim() - if (trimmed.startsWith('npub1')) { - console.log('[CashIn] npub detected, would decode in production') - } - return trimmed -} - -// Request CLINK Debit (Nostr-native payment) -async function submitDebitRequest() { - const pubkey = normalizePubkey(pubkeyInput.value) - if (!pubkey) return - - // Basic validation - should be 64 hex chars or npub - if (!pubkey.startsWith('npub1') && !/^[0-9a-fA-F]{64}$/.test(pubkey)) { - alert('Please enter a valid Nostr pubkey (64 hex chars) or npub') - return - } - - await atmStore.requestDebit(pubkey) -} - // Pay invoice (manual BOLT-11 payment) async function submitInvoice() { const invoice = invoiceInput.value.trim() @@ -209,7 +154,14 @@ function formatSats(sats: number): string { return sats.toLocaleString() } -const isProcessing = computed(() => atmStore.isPayingInvoice || atmStore.isRequestingDebit) +/** Convert sats-per-fiat-unit exchange rate to fiat-per-BTC display string */ +function formatFiatPrice(rateOrPrice: number): string { + // If it looks like a sats/fiat rate, convert to fiat/BTC + const price = rateOrPrice > 10000 ? rateOrPrice : Math.round(100_000_000 / rateOrPrice) + return price.toLocaleString() +} + +const isProcessing = computed(() => atmStore.isPayingInvoice)