fix: prevent decrypt hangs with timeout + fallback

- Wrap nip44/nip04 decrypt and unlockHiddenTags in timeouts
- Fallback nip44->nip04 if nip44 hangs/fails
- Add detailed [bunker] logs for each stage
- Keeps UI responsive while debugging bunker responses
This commit is contained in:
Gigi
2025-10-16 22:51:58 +02:00
parent 77cbb9394f
commit a352e2616e

View File

@@ -11,6 +11,21 @@ type UnlockHiddenTagsFn = typeof Helpers.unlockHiddenTags
type HiddenContentSigner = Parameters<UnlockHiddenTagsFn>[1]
type UnlockMode = Parameters<UnlockHiddenTagsFn>[2]
// Timeout helper to avoid hanging decrypt/unlock calls
async function withTimeout<T>(promise: Promise<T>, ms: number, label: string): Promise<T> {
let timer: number | NodeJS.Timeout | undefined
try {
return await Promise.race([
promise,
new Promise<never>((_, reject) => {
timer = setTimeout(() => reject(new Error(`[timeout] ${label} after ${ms}ms`)), ms)
})
])
} finally {
if (timer) clearTimeout(timer as NodeJS.Timeout)
}
}
export async function collectBookmarksFromEvents(
bookmarkListEvents: NostrEvent[],
activeAccount: ActiveAccount,
@@ -81,15 +96,23 @@ export async function collectBookmarksFromEvents(
hasHiddenTags: true
})
try {
await Helpers.unlockHiddenTags(evt, signerCandidate as HiddenContentSigner)
await withTimeout(
Helpers.unlockHiddenTags(evt, signerCandidate as HiddenContentSigner),
5000,
'unlockHiddenTags(nip04)'
)
console.log('[bunker] ✅ Unlocked hidden tags with nip04')
} catch (err) {
console.log('[bunker] ⚠️ nip04 unlock failed, trying nip44:', err)
console.log('[bunker] ⚠️ nip04 unlock failed (or timed out), trying nip44:', err)
try {
await Helpers.unlockHiddenTags(evt, signerCandidate as HiddenContentSigner, 'nip44' as UnlockMode)
await withTimeout(
Helpers.unlockHiddenTags(evt, signerCandidate as HiddenContentSigner, 'nip44' as UnlockMode),
5000,
'unlockHiddenTags(nip44)'
)
console.log('[bunker] ✅ Unlocked hidden tags with nip44')
} catch (err2) {
console.log('[bunker] ❌ nip44 unlock failed:', err2)
console.log('[bunker] ❌ nip44 unlock failed (or timed out):', err2)
}
}
} else if (evt.content && evt.content.length > 0 && signerCandidate) {
@@ -104,23 +127,31 @@ export async function collectBookmarksFromEvents(
try {
if (hasNip44Decrypt(signerCandidate)) {
console.log('[bunker] Trying nip44 decrypt...')
decryptedContent = await (signerCandidate as { nip44: { decrypt: DecryptFn } }).nip44.decrypt(
evt.pubkey,
evt.content
decryptedContent = await withTimeout(
(signerCandidate as { nip44: { decrypt: DecryptFn } }).nip44.decrypt(
evt.pubkey,
evt.content
),
6000,
'nip44.decrypt'
)
console.log('[bunker] ✅ nip44 decrypt succeeded')
}
} catch (err) {
console.log('[bunker] ⚠️ nip44 decrypt failed:', err)
console.log('[bunker] ⚠️ nip44 decrypt failed (or timed out):', err)
}
if (!decryptedContent) {
try {
if (hasNip04Decrypt(signerCandidate)) {
console.log('[bunker] Trying nip04 decrypt...')
decryptedContent = await (signerCandidate as { nip04: { decrypt: DecryptFn } }).nip04.decrypt(
evt.pubkey,
evt.content
decryptedContent = await withTimeout(
(signerCandidate as { nip04: { decrypt: DecryptFn } }).nip04.decrypt(
evt.pubkey,
evt.content
),
6000,
'nip04.decrypt'
)
console.log('[bunker] ✅ nip04 decrypt succeeded')
}