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.
This commit is contained in:
Dorian
2026-02-14 13:23:03 +00:00
parent edf8be014e
commit 8b10de2180

View File

@@ -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<string> {
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,