From 8b10de2180e93e27172c94a0c685fe3188812959 Mon Sep 17 00:00:00 2001 From: Dorian Date: Sat, 14 Feb 2026 13:23:03 +0000 Subject: [PATCH] feat: enhance pubkey decoding and processing in AuthModal - Updated decodePubkeyText function to support JSON input for NIP-98 events, improving flexibility in pubkey formats. - Enhanced processPubkey function to handle signed NIP-98 events directly, streamlining the login process. - Normalized input handling by trimming whitespace and stripping newlines, ensuring robust pubkey validation. These changes improve the user experience by allowing more diverse input formats for pubkeys and simplifying the login flow. --- src/components/AuthModal.vue | 53 ++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/src/components/AuthModal.vue b/src/components/AuthModal.vue index 911636d..ab2eb25 100644 --- a/src/components/AuthModal.vue +++ b/src/components/AuthModal.vue @@ -567,31 +567,73 @@ function handleAmberOpen() { } /** - * Decode a pubkey from text. Handles hex, npub, and nprofile formats. + * Decode a pubkey from text. Handles hex, npub, nprofile, and JSON (e.g. pasted NIP-98 event). + * Normalizes pasted content: trims, strips newlines, accepts hex with extra characters. */ async function decodePubkeyText(text: string): Promise { - if (/^[0-9a-f]{64}$/i.test(text)) return text - if (text.startsWith('npub') || text.startsWith('nprofile')) { + const raw = text.trim().replace(/\s+/g, '') + if (!raw) throw new Error('Not a valid public key. Expected hex or npub format.') + + // JSON: e.g. pasted NIP-98 request or signed event from Amber (use trim only so JSON stays valid) + if (raw.startsWith('{')) { + try { + const parsed = JSON.parse(text.trim()) + if (parsed.pubkey && /^[0-9a-f]{64}$/i.test(String(parsed.pubkey))) { + return String(parsed.pubkey) + } + } catch { + // Not valid JSON, fall through + } + } + + // Exact 64-char hex + if (/^[0-9a-f]{64}$/i.test(raw)) return raw + + // Hex with extra chars: take first 64 hex characters + const hexOnly = raw.replace(/[^0-9a-fA-F]/g, '') + if (hexOnly.length >= 64) { + return hexOnly.slice(0, 64) + } + + // npub / nprofile + const trimmed = text.trim() + if (trimmed.startsWith('npub') || trimmed.startsWith('nprofile')) { const { decodeProfilePointer } = await import('applesauce-core/helpers') - const decoded = decodeProfilePointer(text) + const decoded = decodeProfilePointer(trimmed) if (!decoded?.pubkey) throw new Error('Could not decode npub') return decoded.pubkey } + throw new Error('Not a valid public key. Expected hex or npub format.') } /** * Process a pubkey (from auto-read or paste), then open Amber to sign NIP-98. + * If the user pasted a full signed NIP-98 event (e.g. from Amber), complete login directly. */ async function processPubkey(text: string) { errorMessage.value = null try { + // If they pasted the signed event JSON from Amber, complete login without opening Amber again + const trimmed = text.trim() + if (trimmed.startsWith('{')) { + try { + const parsed = JSON.parse(trimmed) + if (parsed.sig && parsed.pubkey && /^[0-9a-f]{64}$/i.test(String(parsed.pubkey))) { + await processSignature(trimmed) + return + } + } catch { + // Not a signed event, continue to pubkey extraction + } + } + const pubkey = await decodePubkeyText(text) amberPubkey.value = pubkey showPasteFallback.value = false amberPasteInput.value = '' - // Build the unsigned NIP-98 event + // Build the unsigned NIP-98 event (name tag so Amber shows "IndeeHub" not "null") const sessionUrl = authService.getNostrSessionUrl() const unsignedEvent = { kind: 27235, @@ -599,6 +641,7 @@ async function processPubkey(text: string) { tags: [ ['u', sessionUrl], ['method', 'POST'], + ['name', 'IndeeHub'], ], content: '', pubkey,