import type { EventTemplate, Event } from 'nostr-tools' import { getEventHash, signEvent } from 'nostr-tools' import { nostrAuthService } from './nostrAuth' import { nostrService } from './nostr' /** * Remote signer using Alby (NIP-07) * Alby exposes window.nostr API for signing events */ export class NostrRemoteSigner { /** * Sign an event template using Alby (window.nostr) */ async signEvent(eventTemplate: EventTemplate): Promise { // Get the event hash first const pubkey = nostrService.getPublicKey() if (!pubkey) { throw new Error('Public key required for signing. Please connect with Alby.') } const unsignedEvent = { pubkey, ...eventTemplate, created_at: eventTemplate.created_at ?? Math.floor(Date.now() / 1000), } const eventId = getEventHash(unsignedEvent) // Use Alby (window.nostr) for signing if (typeof window !== 'undefined' && window.nostr) { try { const signedEvent = await window.nostr.signEvent({ kind: unsignedEvent.kind, created_at: unsignedEvent.created_at, tags: unsignedEvent.tags, content: unsignedEvent.content, }) return signedEvent as Event } catch (e) { console.error('Error signing with Alby:', e) throw new Error('Failed to sign event with Alby extension') } } // Fallback to private key signing (should not happen if Alby is properly connected) const privateKey = nostrService.getPrivateKey() if (!privateKey) { throw new Error( 'Alby extension required for signing. ' + 'Please install and connect Alby browser extension.' ) } const event = { ...unsignedEvent, id: eventId, sig: signEvent(unsignedEvent, privateKey), } as Event return event } /** * Check if remote signing is available */ isAvailable(): boolean { const state = nostrAuthService.getState() return state.connected && !!state.pubkey } /** * Check if Alby is available */ isAlbyAvailable(): boolean { return typeof window !== 'undefined' && typeof window.nostr !== 'undefined' } } export const nostrRemoteSigner = new NostrRemoteSigner()