From 77cbb9394f7b13d3986d39b602355c5049ab71e6 Mon Sep 17 00:00:00 2001 From: Gigi Date: Thu, 16 Oct 2025 22:48:46 +0200 Subject: [PATCH] refactor: simplify bunker implementation following applesauce patterns - Remove bunkerFixVersion migration logic - Simplify account loading to match applesauce examples - Simplify reconnectBunkerSigner (no waiting, no complex logging) - Direct nip04/nip44 exposure from signer (like ExtensionAccount) - Clean up bookmark service account checking - Keep debug logs for now until verified working --- src/App.tsx | 47 +++++------------- src/services/bookmarkService.ts | 39 ++------------- src/services/nostrConnect.ts | 85 +++------------------------------ 3 files changed, 21 insertions(+), 150 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 3dd53db2..a39f8a6e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -199,34 +199,15 @@ function App() { pool.group(RELAYS) - // Load persisted accounts from localStorage - try { - const accountsJson = localStorage.getItem('accounts') - if (accountsJson) { - const parsed = JSON.parse(accountsJson) - - // Clear old bunker accounts (they were created with wrong setup) - const bunkerFixVersion = localStorage.getItem('bunkerFixVersion') - if (bunkerFixVersion !== '1') { - console.log('[bunker] Clearing old bunker accounts (need to reconnect with fixed setup)') - const nonBunkerAccounts = parsed.filter((acc: any) => acc.type !== 'nostr-connect') - if (nonBunkerAccounts.length > 0) { - await accounts.fromJSON(nonBunkerAccounts) - } - localStorage.setItem('bunkerFixVersion', '1') - localStorage.removeItem('active') - } else { - await accounts.fromJSON(parsed) - - // Restore active account - const activeId = localStorage.getItem('active') - if (activeId && accounts.getAccount(activeId)) { - accounts.setActive(activeId) - } - } - } - } catch (err) { - console.error('[bunker] Failed to restore accounts:', err) + // Load persisted accounts from localStorage (per applesauce examples) + const savedAccounts = JSON.parse(localStorage.getItem('accounts') || '[]') + await accounts.fromJSON(savedAccounts) + + // Restore active account + const activeAccountId = localStorage.getItem('active') + if (activeAccountId) { + const account = accounts.getAccount(activeAccountId) + if (account) accounts.setActive(account) } // Persist accounts to localStorage @@ -242,18 +223,12 @@ function App() { } }) - // Reconnect bunker signers on page load + // Reconnect bunker signers on page load (per applesauce pattern) const reconnectedAccounts = new Set() const bunkerReconnectSub = accounts.active$.subscribe(async (account) => { if (account?.type === 'nostr-connect' && !reconnectedAccounts.has(account.id)) { reconnectedAccounts.add(account.id) - - try { - await reconnectBunkerSigner(account as Accounts.NostrConnectAccount, pool) - console.log('[bunker] Reconnected to bunker signer') - } catch (error) { - console.error('[bunker] Failed to reconnect signer:', error) - } + await reconnectBunkerSigner(account as Accounts.NostrConnectAccount, pool) } }) diff --git a/src/services/bookmarkService.ts b/src/services/bookmarkService.ts index 8b549818..8b625966 100644 --- a/src/services/bookmarkService.ts +++ b/src/services/bookmarkService.ts @@ -83,49 +83,16 @@ export const fetchBookmarks = async ( // Keep existing bookmarks visible; do not clear list if nothing new found return } - // Aggregate across events + // Get account with signer for decryption const maybeAccount = activeAccount as AccountWithExtension - console.log('[bunker] 🔐 Account object:', { - hasSignEvent: typeof maybeAccount?.signEvent === 'function', - hasSigner: !!maybeAccount?.signer, - accountType: maybeAccount?.type || typeof maybeAccount, - accountKeys: maybeAccount ? Object.keys(maybeAccount) : [] - }) - - // For ExtensionAccount, we need a signer with nip04/nip44 for decrypting hidden content - // The ExtensionAccount itself has nip04/nip44 getters that proxy to the signer let signerCandidate: unknown = maybeAccount + + // Fallback to raw signer if account doesn't expose nip04/nip44 const hasNip04Prop = (signerCandidate as { nip04?: unknown })?.nip04 !== undefined const hasNip44Prop = (signerCandidate as { nip44?: unknown })?.nip44 !== undefined - - console.log('[bunker] 🔍 Account nip04/nip44 check:', { - hasNip04Prop, - hasNip44Prop, - nip04Type: typeof (signerCandidate as { nip04?: unknown })?.nip04, - nip44Type: typeof (signerCandidate as { nip44?: unknown })?.nip44 - }) - if (signerCandidate && !hasNip04Prop && !hasNip44Prop && maybeAccount?.signer) { - // Fallback to the raw signer if account doesn't have nip04/nip44 - console.log('[bunker] ⚠️ Account missing nip04/nip44, falling back to signer') signerCandidate = maybeAccount.signer - - const signerHasNip04 = (signerCandidate as { nip04?: unknown })?.nip04 !== undefined - const signerHasNip44 = (signerCandidate as { nip44?: unknown })?.nip44 !== undefined - console.log('[bunker] 🔍 Signer nip04/nip44 check:', { - signerHasNip04, - signerHasNip44, - nip04Type: typeof (signerCandidate as { nip04?: unknown })?.nip04, - nip44Type: typeof (signerCandidate as { nip44?: unknown })?.nip44 - }) } - - console.log('[bunker] 🔑 Final signer candidate:', { - exists: !!signerCandidate, - type: typeof signerCandidate, - hasNip04: hasNip04Decrypt(signerCandidate), - hasNip44: hasNip44Decrypt(signerCandidate) - }) const { publicItemsAll, privateItemsAll, newestCreatedAt, latestContent, allTags } = await collectBookmarksFromEvents( bookmarkListEvents, activeAccount, diff --git a/src/services/nostrConnect.ts b/src/services/nostrConnect.ts index 39620015..3cbc36dc 100644 --- a/src/services/nostrConnect.ts +++ b/src/services/nostrConnect.ts @@ -28,102 +28,31 @@ export function getDefaultBunkerPermissions(): string[] { /** * Reconnect a bunker signer after page load - * Ensures the signer is listening and connected to the correct relays + * Ensures the signer is listening and ready for signing/decryption */ export async function reconnectBunkerSigner( account: Accounts.NostrConnectAccount, pool: RelayPool ): Promise { - // Add bunker relays to pool for signing communication + // Add bunker relays to pool if (account.signer.relays) { - const bunkerRelays = account.signer.relays - pool.group(bunkerRelays) - - // Wait for at least one bunker relay to be connected - // This ensures signing/decryption requests can be sent - console.log('[bunker] Waiting for relay connections...', bunkerRelays) - await new Promise((resolve) => { - const checkInterval = setInterval(() => { - const connectedRelays = bunkerRelays.filter(url => { - const relay = pool.relays.get(url) - return relay?.connected - }) - - if (connectedRelays.length > 0) { - console.log('[bunker] ✅ Connected to', connectedRelays.length, 'bunker relay(s)') - clearInterval(checkInterval) - resolve() - } - }, 100) - - // Timeout after 5 seconds - setTimeout(() => { - clearInterval(checkInterval) - console.warn('[bunker] ⚠️ Timeout waiting for relay connections, proceeding anyway') - resolve() - }, 5000) - }) + pool.group(account.signer.relays) } - // Open signer subscription if not already listening + // Open signer subscription for NIP-46 responses if (!account.signer.listening) { - console.log('[bunker] Opening signer subscription for NIP-46 responses...') await account.signer.open() - console.log('[bunker] ✅ Signer subscription active, listening for bunker responses') - } else { - console.log('[bunker] Signer already listening') } // Mark as connected (bunker remembers permissions from initial connection) account.signer.isConnected = true - console.log('[bunker] Signer marked as connected, ready for signing/decryption') - // Expose nip04/nip44 at account level for compatibility with logging - // Cache wrapped methods to ensure they're used consistently + // Expose nip04/nip44 at account level (like ExtensionAccount does) if (!('nip04' in account)) { - const nip04Wrapped = { - encrypt: async (pubkey: string, plaintext: string) => { - console.log('[bunker] 🔐 nip04.encrypt called', { pubkey: pubkey.slice(0, 8) }) - const result = await account.signer.nip04!.encrypt(pubkey, plaintext) - console.log('[bunker] ✅ nip04.encrypt completed') - return result - }, - decrypt: async (pubkey: string, ciphertext: string) => { - console.log('[bunker] 🔓 nip04.decrypt called', { pubkey: pubkey.slice(0, 8), ciphertextLength: ciphertext.length }) - try { - const result = await account.signer.nip04!.decrypt(pubkey, ciphertext) - console.log('[bunker] ✅ nip04.decrypt completed') - return result - } catch (err) { - console.error('[bunker] ❌ nip04.decrypt failed:', err) - throw err - } - } - }; - (account as any).nip04 = nip04Wrapped + (account as any).nip04 = account.signer.nip04 } - if (!('nip44' in account)) { - const nip44Wrapped = { - encrypt: async (pubkey: string, plaintext: string) => { - console.log('[bunker] 🔐 nip44.encrypt called', { pubkey: pubkey.slice(0, 8) }) - const result = await account.signer.nip44!.encrypt(pubkey, plaintext) - console.log('[bunker] ✅ nip44.encrypt completed') - return result - }, - decrypt: async (pubkey: string, ciphertext: string) => { - console.log('[bunker] 🔓 nip44.decrypt called', { pubkey: pubkey.slice(0, 8), ciphertextLength: ciphertext.length }) - try { - const result = await account.signer.nip44!.decrypt(pubkey, ciphertext) - console.log('[bunker] ✅ nip44.decrypt completed', { plaintextLength: result.length }) - return result - } catch (err) { - console.error('[bunker] ❌ nip44.decrypt failed:', err) - throw err - } - } - }; - (account as any).nip44 = nip44Wrapped + (account as any).nip44 = account.signer.nip44 } }