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:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user