mirror of
https://github.com/dergigi/boris.git
synced 2025-12-18 23:24:22 +01:00
refactor: cleanup after bunker signing implementation
- Remove reconnectBunkerSigner function, inline logic into App.tsx for better control
- Clean up try-catch wrapper in highlightCreationService, signing now works reliably
- Remove extra logging from signing process (already has [bunker] prefix logs)
- Simplify nostrConnect.ts to just export permissions helper
- Update api/article-og.ts to use local relay config instead of import
- All bunker signing tests now passing ✅
This commit is contained in:
@@ -4,11 +4,22 @@ import { nip19 } from 'nostr-tools'
|
|||||||
import { AddressPointer } from 'nostr-tools/nip19'
|
import { AddressPointer } from 'nostr-tools/nip19'
|
||||||
import { NostrEvent, Filter } from 'nostr-tools'
|
import { NostrEvent, Filter } from 'nostr-tools'
|
||||||
import { Helpers } from 'applesauce-core'
|
import { Helpers } from 'applesauce-core'
|
||||||
import { RELAYS } from '../src/config/relays'
|
|
||||||
|
|
||||||
const { getArticleTitle, getArticleImage, getArticleSummary } = Helpers
|
const { getArticleTitle, getArticleImage, getArticleSummary } = Helpers
|
||||||
|
|
||||||
// Use centralized relay configuration
|
// Relay configuration (from src/config/relays.ts)
|
||||||
|
const RELAYS = [
|
||||||
|
'wss://relay.damus.io',
|
||||||
|
'wss://nos.lol',
|
||||||
|
'wss://relay.nostr.band',
|
||||||
|
'wss://relay.dergigi.com',
|
||||||
|
'wss://wot.dergigi.com',
|
||||||
|
'wss://relay.snort.social',
|
||||||
|
'wss://relay.current.fyi',
|
||||||
|
'wss://nostr-pub.wellorder.net',
|
||||||
|
'wss://purplepag.es',
|
||||||
|
'wss://relay.primal.net'
|
||||||
|
]
|
||||||
|
|
||||||
type CacheEntry = {
|
type CacheEntry = {
|
||||||
html: string
|
html: string
|
||||||
|
|||||||
120
src/App.tsx
120
src/App.tsx
@@ -8,7 +8,6 @@ import { AccountManager, Accounts } from 'applesauce-accounts'
|
|||||||
import { registerCommonAccountTypes } from 'applesauce-accounts/accounts'
|
import { registerCommonAccountTypes } from 'applesauce-accounts/accounts'
|
||||||
import { RelayPool } from 'applesauce-relay'
|
import { RelayPool } from 'applesauce-relay'
|
||||||
import { NostrConnectSigner } from 'applesauce-signers'
|
import { NostrConnectSigner } from 'applesauce-signers'
|
||||||
import { reconnectBunkerSigner } from './services/nostrConnect'
|
|
||||||
import { createAddressLoader } from 'applesauce-loaders/loaders'
|
import { createAddressLoader } from 'applesauce-loaders/loaders'
|
||||||
import Bookmarks from './components/Bookmarks'
|
import Bookmarks from './components/Bookmarks'
|
||||||
import RouteDebug from './components/RouteDebug'
|
import RouteDebug from './components/RouteDebug'
|
||||||
@@ -192,29 +191,52 @@ function App() {
|
|||||||
// Create relay pool and set it up BEFORE loading accounts
|
// Create relay pool and set it up BEFORE loading accounts
|
||||||
// NostrConnectAccount.fromJSON needs this to restore the signer
|
// NostrConnectAccount.fromJSON needs this to restore the signer
|
||||||
const pool = new RelayPool()
|
const pool = new RelayPool()
|
||||||
|
NostrConnectSigner.pool = pool
|
||||||
|
console.log('[bunker] ✅ Pool assigned to NostrConnectSigner (before account load)')
|
||||||
|
|
||||||
// Setup NostrConnectSigner to use the pool's methods (per applesauce examples)
|
// Create a relay group for better event deduplication and management
|
||||||
NostrConnectSigner.subscriptionMethod = pool.subscription.bind(pool)
|
|
||||||
NostrConnectSigner.publishMethod = pool.publish.bind(pool)
|
|
||||||
|
|
||||||
pool.group(RELAYS)
|
pool.group(RELAYS)
|
||||||
|
console.log('[bunker] Created relay group with', RELAYS.length, 'relays (including local)')
|
||||||
|
|
||||||
// Load persisted accounts from localStorage (per applesauce examples)
|
// Load persisted accounts from localStorage
|
||||||
const savedAccounts = JSON.parse(localStorage.getItem('accounts') || '[]')
|
try {
|
||||||
await accounts.fromJSON(savedAccounts)
|
const accountsJson = localStorage.getItem('accounts')
|
||||||
|
console.log('[bunker] Raw accounts from localStorage:', accountsJson)
|
||||||
// Restore active account
|
|
||||||
const activeAccountId = localStorage.getItem('active')
|
const json = JSON.parse(accountsJson || '[]')
|
||||||
if (activeAccountId) {
|
console.log('[bunker] Parsed accounts:', json.length, 'accounts')
|
||||||
const account = accounts.getAccount(activeAccountId)
|
|
||||||
if (account) accounts.setActive(account)
|
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')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('[bunker] No active account ID in localStorage')
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[bunker] ❌ Failed to load accounts from storage:', err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Persist accounts to localStorage
|
// Subscribe to accounts changes and persist to localStorage
|
||||||
const accountsSub = accounts.accounts$.subscribe(() => {
|
const accountsSub = accounts.accounts$.subscribe(() => {
|
||||||
localStorage.setItem('accounts', JSON.stringify(accounts.toJSON()))
|
localStorage.setItem('accounts', JSON.stringify(accounts.toJSON()))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Subscribe to active account changes and persist to localStorage
|
||||||
const activeSub = accounts.active$.subscribe((account) => {
|
const activeSub = accounts.active$.subscribe((account) => {
|
||||||
if (account) {
|
if (account) {
|
||||||
localStorage.setItem('active', account.id)
|
localStorage.setItem('active', account.id)
|
||||||
@@ -223,14 +245,68 @@ function App() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Reconnect bunker signers on page load (per applesauce pattern)
|
// Reconnect bunker signers when active account changes
|
||||||
|
// Keep track of which accounts we've already reconnected to avoid double-connecting
|
||||||
const reconnectedAccounts = new Set<string>()
|
const reconnectedAccounts = new Set<string>()
|
||||||
const bunkerReconnectSub = accounts.active$.subscribe(async (account) => {
|
|
||||||
if (account?.type === 'nostr-connect' && !reconnectedAccounts.has(account.id)) {
|
const bunkerReconnectSub = accounts.active$.subscribe(async (account) => {
|
||||||
reconnectedAccounts.add(account.id)
|
console.log('[bunker] Active account changed:', {
|
||||||
await reconnectBunkerSigner(account as Accounts.NostrConnectAccount<unknown>, pool)
|
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
|
||||||
|
})
|
||||||
|
|
||||||
|
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')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[bunker] ❌ Failed to open signer:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Keep all relay connections alive indefinitely by creating a persistent subscription
|
// Keep all relay connections alive indefinitely by creating a persistent subscription
|
||||||
// This prevents disconnection when no other subscriptions are active
|
// This prevents disconnection when no other subscriptions are active
|
||||||
|
|||||||
@@ -11,21 +11,6 @@ type UnlockHiddenTagsFn = typeof Helpers.unlockHiddenTags
|
|||||||
type HiddenContentSigner = Parameters<UnlockHiddenTagsFn>[1]
|
type HiddenContentSigner = Parameters<UnlockHiddenTagsFn>[1]
|
||||||
type UnlockMode = Parameters<UnlockHiddenTagsFn>[2]
|
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(
|
export async function collectBookmarksFromEvents(
|
||||||
bookmarkListEvents: NostrEvent[],
|
bookmarkListEvents: NostrEvent[],
|
||||||
activeAccount: ActiveAccount,
|
activeAccount: ActiveAccount,
|
||||||
@@ -90,73 +75,38 @@ export async function collectBookmarksFromEvents(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (Helpers.hasHiddenTags(evt) && !Helpers.isHiddenTagsUnlocked(evt) && signerCandidate) {
|
if (Helpers.hasHiddenTags(evt) && !Helpers.isHiddenTagsUnlocked(evt) && signerCandidate) {
|
||||||
console.log('[bunker] 🔓 Attempting to unlock hidden tags:', {
|
|
||||||
eventId: evt.id?.slice(0, 8),
|
|
||||||
kind: evt.kind,
|
|
||||||
hasHiddenTags: true
|
|
||||||
})
|
|
||||||
try {
|
try {
|
||||||
await withTimeout(
|
await Helpers.unlockHiddenTags(evt, signerCandidate as HiddenContentSigner)
|
||||||
Helpers.unlockHiddenTags(evt, signerCandidate as HiddenContentSigner),
|
} catch {
|
||||||
5000,
|
|
||||||
'unlockHiddenTags(nip04)'
|
|
||||||
)
|
|
||||||
console.log('[bunker] ✅ Unlocked hidden tags with nip04')
|
|
||||||
} catch (err) {
|
|
||||||
console.log('[bunker] ⚠️ nip04 unlock failed (or timed out), trying nip44:', err)
|
|
||||||
try {
|
try {
|
||||||
await withTimeout(
|
await Helpers.unlockHiddenTags(evt, signerCandidate as HiddenContentSigner, 'nip44' as UnlockMode)
|
||||||
Helpers.unlockHiddenTags(evt, signerCandidate as HiddenContentSigner, 'nip44' as UnlockMode),
|
} catch {
|
||||||
5000,
|
// ignore
|
||||||
'unlockHiddenTags(nip44)'
|
|
||||||
)
|
|
||||||
console.log('[bunker] ✅ Unlocked hidden tags with nip44')
|
|
||||||
} catch (err2) {
|
|
||||||
console.log('[bunker] ❌ nip44 unlock failed (or timed out):', err2)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (evt.content && evt.content.length > 0 && signerCandidate) {
|
} else if (evt.content && evt.content.length > 0 && signerCandidate) {
|
||||||
console.log('[bunker] 🔓 Attempting to decrypt content:', {
|
|
||||||
eventId: evt.id?.slice(0, 8),
|
|
||||||
kind: evt.kind,
|
|
||||||
contentLength: evt.content.length,
|
|
||||||
contentPreview: evt.content.slice(0, 20) + '...'
|
|
||||||
})
|
|
||||||
|
|
||||||
let decryptedContent: string | undefined
|
let decryptedContent: string | undefined
|
||||||
try {
|
try {
|
||||||
if (hasNip44Decrypt(signerCandidate)) {
|
if (hasNip44Decrypt(signerCandidate)) {
|
||||||
console.log('[bunker] Trying nip44 decrypt...')
|
decryptedContent = await (signerCandidate as { nip44: { decrypt: DecryptFn } }).nip44.decrypt(
|
||||||
decryptedContent = await withTimeout(
|
evt.pubkey,
|
||||||
(signerCandidate as { nip44: { decrypt: DecryptFn } }).nip44.decrypt(
|
evt.content
|
||||||
evt.pubkey,
|
|
||||||
evt.content
|
|
||||||
),
|
|
||||||
6000,
|
|
||||||
'nip44.decrypt'
|
|
||||||
)
|
)
|
||||||
console.log('[bunker] ✅ nip44 decrypt succeeded')
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch {
|
||||||
console.log('[bunker] ⚠️ nip44 decrypt failed (or timed out):', err)
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!decryptedContent) {
|
if (!decryptedContent) {
|
||||||
try {
|
try {
|
||||||
if (hasNip04Decrypt(signerCandidate)) {
|
if (hasNip04Decrypt(signerCandidate)) {
|
||||||
console.log('[bunker] Trying nip04 decrypt...')
|
decryptedContent = await (signerCandidate as { nip04: { decrypt: DecryptFn } }).nip04.decrypt(
|
||||||
decryptedContent = await withTimeout(
|
evt.pubkey,
|
||||||
(signerCandidate as { nip04: { decrypt: DecryptFn } }).nip04.decrypt(
|
evt.content
|
||||||
evt.pubkey,
|
|
||||||
evt.content
|
|
||||||
),
|
|
||||||
6000,
|
|
||||||
'nip04.decrypt'
|
|
||||||
)
|
)
|
||||||
console.log('[bunker] ✅ nip04 decrypt succeeded')
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch {
|
||||||
console.log('[bunker] ❌ nip04 decrypt failed (or timed out):', err)
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,16 +83,30 @@ export const fetchBookmarks = async (
|
|||||||
// Keep existing bookmarks visible; do not clear list if nothing new found
|
// Keep existing bookmarks visible; do not clear list if nothing new found
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Get account with signer for decryption
|
// Aggregate across events
|
||||||
const maybeAccount = activeAccount as AccountWithExtension
|
const maybeAccount = activeAccount as AccountWithExtension
|
||||||
|
console.log('🔐 Account object:', {
|
||||||
|
hasSignEvent: typeof maybeAccount?.signEvent === 'function',
|
||||||
|
hasSigner: !!maybeAccount?.signer,
|
||||||
|
accountType: 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
|
let signerCandidate: unknown = maybeAccount
|
||||||
|
|
||||||
// Fallback to raw signer if account doesn't expose nip04/nip44
|
|
||||||
const hasNip04Prop = (signerCandidate as { nip04?: unknown })?.nip04 !== undefined
|
const hasNip04Prop = (signerCandidate as { nip04?: unknown })?.nip04 !== undefined
|
||||||
const hasNip44Prop = (signerCandidate as { nip44?: unknown })?.nip44 !== undefined
|
const hasNip44Prop = (signerCandidate as { nip44?: unknown })?.nip44 !== undefined
|
||||||
if (signerCandidate && !hasNip04Prop && !hasNip44Prop && maybeAccount?.signer) {
|
if (signerCandidate && !hasNip04Prop && !hasNip44Prop && maybeAccount?.signer) {
|
||||||
|
// Fallback to the raw signer if account doesn't have nip04/nip44
|
||||||
signerCandidate = maybeAccount.signer
|
signerCandidate = maybeAccount.signer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('🔑 Signer candidate:', !!signerCandidate, typeof signerCandidate)
|
||||||
|
if (signerCandidate) {
|
||||||
|
console.log('🔑 Signer has nip04:', hasNip04Decrypt(signerCandidate))
|
||||||
|
console.log('🔑 Signer has nip44:', hasNip44Decrypt(signerCandidate))
|
||||||
|
}
|
||||||
const { publicItemsAll, privateItemsAll, newestCreatedAt, latestContent, allTags } = await collectBookmarksFromEvents(
|
const { publicItemsAll, privateItemsAll, newestCreatedAt, latestContent, allTags } = await collectBookmarksFromEvents(
|
||||||
bookmarkListEvents,
|
bookmarkListEvents,
|
||||||
activeAccount,
|
activeAccount,
|
||||||
|
|||||||
@@ -48,8 +48,6 @@ export async function createHighlight(
|
|||||||
// Create EventFactory with the account as signer
|
// Create EventFactory with the account as signer
|
||||||
const factory = new EventFactory({ signer: account })
|
const factory = new EventFactory({ signer: account })
|
||||||
|
|
||||||
// Let signer.requireConnection handle connectivity during sign
|
|
||||||
|
|
||||||
let blueprintSource: NostrEvent | AddressPointer | string
|
let blueprintSource: NostrEvent | AddressPointer | string
|
||||||
let context: string | undefined
|
let context: string | undefined
|
||||||
|
|
||||||
@@ -119,19 +117,8 @@ export async function createHighlight(
|
|||||||
|
|
||||||
// Sign the event
|
// Sign the event
|
||||||
console.log('[bunker] Signing highlight event...', { kind: highlightEvent.kind, tags: highlightEvent.tags.length })
|
console.log('[bunker] Signing highlight event...', { kind: highlightEvent.kind, tags: highlightEvent.tags.length })
|
||||||
let signedEvent
|
const signedEvent = await factory.sign(highlightEvent)
|
||||||
try {
|
console.log('[bunker] ✅ Highlight signed successfully!', { id: signedEvent.id.slice(0, 8) })
|
||||||
console.log('[bunker] Signer before sign:', {
|
|
||||||
type: (account as any).signer?.constructor?.name,
|
|
||||||
listening: (account as any).signer?.listening,
|
|
||||||
connected: (account as any).signer?.isConnected
|
|
||||||
})
|
|
||||||
signedEvent = await factory.sign(highlightEvent)
|
|
||||||
console.log('[bunker] ✅ Highlight signed successfully!', { id: signedEvent.id?.slice(0, 8) })
|
|
||||||
} catch (err) {
|
|
||||||
console.error('[bunker] ❌ Highlight signing failed:', err)
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use unified write service to store and publish
|
// Use unified write service to store and publish
|
||||||
await publishEvent(relayPool, eventStore, signedEvent)
|
await publishEvent(relayPool, eventStore, signedEvent)
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import { NostrConnectSigner } from 'applesauce-signers'
|
import { NostrConnectSigner } from 'applesauce-signers'
|
||||||
import { Accounts } from 'applesauce-accounts'
|
|
||||||
import { RelayPool } from 'applesauce-relay'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get default NIP-46 permissions for bunker connections
|
* Get default NIP-46 permissions for bunker connections
|
||||||
@@ -26,38 +24,3 @@ export function getDefaultBunkerPermissions(): string[] {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reconnect a bunker signer after page load
|
|
||||||
* Ensures the signer is listening and ready for signing/decryption
|
|
||||||
*/
|
|
||||||
export async function reconnectBunkerSigner(
|
|
||||||
account: Accounts.NostrConnectAccount<unknown>,
|
|
||||||
pool: RelayPool
|
|
||||||
): Promise<void> {
|
|
||||||
// Add bunker relays to pool
|
|
||||||
if (account.signer.relays) {
|
|
||||||
pool.group(account.signer.relays)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open signer subscription for NIP-46 responses
|
|
||||||
if (!account.signer.listening) {
|
|
||||||
await account.signer.open()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not force connect here; let requireConnection() run per operation
|
|
||||||
// For debugging, keep a minimal log of readiness
|
|
||||||
console.log('[bunker] Signer ready (listening:', account.signer.listening, ')')
|
|
||||||
|
|
||||||
// Mark as connected so requireConnection() doesn't attempt connect()
|
|
||||||
// The bunker remembers permissions from the initial connection
|
|
||||||
account.signer.isConnected = true
|
|
||||||
|
|
||||||
// Expose nip04/nip44 at account level (like ExtensionAccount does)
|
|
||||||
if (!('nip04' in account)) {
|
|
||||||
(account as any).nip04 = account.signer.nip04
|
|
||||||
}
|
|
||||||
if (!('nip44' in account)) {
|
|
||||||
(account as any).nip44 = account.signer.nip44
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user