refactor: clean up bunker implementation for better maintainability

- Extract reconnectBunkerSigner into reusable helper function
- Reduce excessive debug logging in App.tsx (90+ lines → 30 lines)
- Simplify account restoration logic with cleaner conditionals
- Remove verbose signing logs from highlightCreationService
- Keep only essential error logs for debugging
- Follows DRY principles and applesauce patterns
This commit is contained in:
Gigi
2025-10-16 22:32:06 +02:00
parent 118ab46ac0
commit bf849c9faa
3 changed files with 46 additions and 93 deletions

View File

@@ -8,6 +8,7 @@ import { AccountManager, Accounts } from 'applesauce-accounts'
import { registerCommonAccountTypes } from 'applesauce-accounts/accounts'
import { RelayPool } from 'applesauce-relay'
import { NostrConnectSigner } from 'applesauce-signers'
import { reconnectBunkerSigner } from './services/nostrConnect'
import { createAddressLoader } from 'applesauce-loaders/loaders'
import Bookmarks from './components/Bookmarks'
import RouteDebug from './components/RouteDebug'
@@ -192,51 +193,29 @@ function App() {
// NostrConnectAccount.fromJSON needs this to restore the signer
const pool = new RelayPool()
NostrConnectSigner.pool = pool
console.log('[bunker] ✅ Pool assigned to NostrConnectSigner (before account load)')
// Create a relay group for better event deduplication and management
pool.group(RELAYS)
console.log('[bunker] Created relay group with', RELAYS.length, 'relays (including local)')
// Load persisted accounts from localStorage
try {
const accountsJson = localStorage.getItem('accounts')
console.log('[bunker] Raw accounts from localStorage:', accountsJson)
const json = JSON.parse(accountsJson || '[]')
console.log('[bunker] Parsed accounts:', json.length, 'accounts')
await accounts.fromJSON(json)
console.log('[bunker] Loaded', accounts.accounts.length, 'accounts from storage')
console.log('[bunker] Account types:', accounts.accounts.map(a => ({ id: a.id, type: a.type })))
// Load active account from storage
const activeId = localStorage.getItem('active')
console.log('[bunker] Active ID from localStorage:', activeId)
if (activeId) {
const account = accounts.getAccount(activeId)
console.log('[bunker] Found account for ID?', !!account, account?.type)
if (account) {
accounts.setActive(activeId)
console.log('[bunker] ✅ Restored active account:', activeId, 'type:', account.type)
} else {
console.warn('[bunker] ⚠️ Active ID found but account not in list')
if (accountsJson) {
await accounts.fromJSON(JSON.parse(accountsJson))
}
} else {
console.log('[bunker] No active account ID in localStorage')
// Restore active account
const activeId = localStorage.getItem('active')
if (activeId && accounts.getAccount(activeId)) {
accounts.setActive(activeId)
}
} catch (err) {
console.error('[bunker] Failed to load accounts from storage:', err)
console.error('[bunker] Failed to restore accounts:', err)
}
// Subscribe to accounts changes and persist to localStorage
// Persist accounts to localStorage
const accountsSub = accounts.accounts$.subscribe(() => {
localStorage.setItem('accounts', JSON.stringify(accounts.toJSON()))
})
// Subscribe to active account changes and persist to localStorage
const activeSub = accounts.active$.subscribe((account) => {
if (account) {
localStorage.setItem('active', account.id)
@@ -245,65 +224,17 @@ function App() {
}
})
// Reconnect bunker signers when active account changes
// Keep track of which accounts we've already reconnected to avoid double-connecting
// Reconnect bunker signers on page load
const reconnectedAccounts = new Set<string>()
const bunkerReconnectSub = accounts.active$.subscribe(async (account) => {
console.log('[bunker] Active account changed:', {
hasAccount: !!account,
type: account?.type,
id: account?.id
})
if (account && account.type === 'nostr-connect') {
const nostrConnectAccount = account as Accounts.NostrConnectAccount<unknown>
// Skip if we've already reconnected this account
if (reconnectedAccounts.has(account.id)) {
console.log('[bunker] ⏭️ Already reconnected this account, skipping')
return
}
console.log('[bunker] Account detected. Status:', {
listening: nostrConnectAccount.signer.listening,
isConnected: nostrConnectAccount.signer.isConnected,
hasRemote: !!nostrConnectAccount.signer.remote,
bunkerRelays: nostrConnectAccount.signer.relays
})
if (account?.type === 'nostr-connect' && !reconnectedAccounts.has(account.id)) {
reconnectedAccounts.add(account.id)
try {
// Add bunker's relays to the pool so signing requests can be sent/received
const bunkerRelays = nostrConnectAccount.signer.relays || []
console.log('[bunker] Adding bunker relays to pool:', bunkerRelays)
pool.group(bunkerRelays)
// Just ensure the signer is listening for responses - don't call connect() again
// The fromBunkerURI already connected with permissions during login
if (!nostrConnectAccount.signer.listening) {
console.log('[bunker] Opening signer subscription...')
await nostrConnectAccount.signer.open()
console.log('[bunker] ✅ Signer subscription opened')
} else {
console.log('[bunker] ✅ Signer already listening')
}
// Mark as connected so requireConnection() doesn't call connect() again
// The bunker remembers the permissions from the initial connection
nostrConnectAccount.signer.isConnected = true
console.log('[bunker] Final signer status:', {
listening: nostrConnectAccount.signer.listening,
isConnected: nostrConnectAccount.signer.isConnected,
remote: nostrConnectAccount.signer.remote,
relays: nostrConnectAccount.signer.relays
})
// Mark this account as reconnected
reconnectedAccounts.add(account.id)
console.log('[bunker] 🎉 Signer ready for signing')
await reconnectBunkerSigner(account as Accounts.NostrConnectAccount<unknown>, pool)
console.log('[bunker] Reconnected to bunker signer')
} catch (error) {
console.error('[bunker] Failed to open signer:', error)
console.error('[bunker] Failed to reconnect signer:', error)
}
}
})

View File

@@ -116,9 +116,7 @@ export async function createHighlight(
}
// Sign the event
console.log('[bunker] Signing highlight event...', { kind: highlightEvent.kind, tags: highlightEvent.tags.length })
const signedEvent = await factory.sign(highlightEvent)
console.log('[bunker] ✅ Highlight signed successfully!', { id: signedEvent.id.slice(0, 8) })
// Use unified write service to store and publish
await publishEvent(relayPool, eventStore, signedEvent)

View File

@@ -1,4 +1,6 @@
import { NostrConnectSigner } from 'applesauce-signers'
import { Accounts } from 'applesauce-accounts'
import { RelayPool } from 'applesauce-relay'
/**
* Get default NIP-46 permissions for bunker connections
@@ -24,3 +26,25 @@ export function getDefaultBunkerPermissions(): string[] {
]
}
/**
* Reconnect a bunker signer after page load
* Ensures the signer is listening and connected to the correct relays
*/
export async function reconnectBunkerSigner(
account: Accounts.NostrConnectAccount<unknown>,
pool: RelayPool
): Promise<void> {
// Add bunker relays to pool for signing communication
if (account.signer.relays) {
pool.group(account.signer.relays)
}
// Open signer subscription if not already listening
if (!account.signer.listening) {
await account.signer.open()
}
// Mark as connected (bunker remembers permissions from initial connection)
account.signer.isConnected = true
}