From 685aaf43b08f177dd61f997a3be979bc06567bbb Mon Sep 17 00:00:00 2001 From: Gigi Date: Thu, 16 Oct 2025 23:54:31 +0200 Subject: [PATCH] fix: add timeout to bookmark decryption to prevent hanging - Wrap nip04/nip44 decrypt calls with 5 second timeout - Prevents UI from hanging if decrypt request doesn't receive response - Allows graceful degradation instead of infinite wait - With bunker, decrypt responses may not arrive if perms/relay issues --- src/services/bookmarkProcessing.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/services/bookmarkProcessing.ts b/src/services/bookmarkProcessing.ts index 888699c0..9957c7ae 100644 --- a/src/services/bookmarkProcessing.ts +++ b/src/services/bookmarkProcessing.ts @@ -11,6 +11,18 @@ type UnlockHiddenTagsFn = typeof Helpers.unlockHiddenTags type HiddenContentSigner = Parameters[1] type UnlockMode = Parameters[2] +/** + * Wrap a decrypt promise with a timeout to prevent hanging + */ +function withDecryptTimeout(promise: Promise, timeoutMs = 5000): Promise { + return Promise.race([ + promise, + new Promise((_, reject) => + setTimeout(() => reject(new Error(`Decrypt timeout after ${timeoutMs}ms`)), timeoutMs) + ) + ]) +} + export async function collectBookmarksFromEvents( bookmarkListEvents: NostrEvent[], activeAccount: ActiveAccount, @@ -88,10 +100,10 @@ export async function collectBookmarksFromEvents( let decryptedContent: string | undefined try { if (hasNip44Decrypt(signerCandidate)) { - decryptedContent = await (signerCandidate as { nip44: { decrypt: DecryptFn } }).nip44.decrypt( + decryptedContent = await withDecryptTimeout((signerCandidate as { nip44: { decrypt: DecryptFn } }).nip44.decrypt( evt.pubkey, evt.content - ) + )) } } catch { // ignore @@ -100,10 +112,10 @@ export async function collectBookmarksFromEvents( if (!decryptedContent) { try { if (hasNip04Decrypt(signerCandidate)) { - decryptedContent = await (signerCandidate as { nip04: { decrypt: DecryptFn } }).nip04.decrypt( + decryptedContent = await withDecryptTimeout((signerCandidate as { nip04: { decrypt: DecryptFn } }).nip04.decrypt( evt.pubkey, evt.content - ) + )) } } catch { // ignore