import { nostrService } from './nostr' import { getPrimaryRelaySync } from './config' import type { Event } from 'nostr-tools' export function createMessageVerificationFilters(messageEventId: string, authorPubkey: string, recipientPubkey: string, articleId: string) { return [ { kinds: [4], ids: [messageEventId], authors: [authorPubkey], '#p': [recipientPubkey], '#e': [articleId], limit: 1, }, ] } export function handleMessageVerificationEvent( event: import('nostr-tools').Event, articleId: string, recipientPubkey: string, authorPubkey: string, finalize: (value: boolean) => void ): void { console.log('Private message verified on relay', { messageEventId: event.id, articleId, recipientPubkey, authorPubkey, timestamp: new Date().toISOString(), }) finalize(true) } export function setupMessageVerificationHandlers( sub: import('@/types/nostr-tools-extended').SimplePoolWithSub['sub'] extends (...args: any[]) => infer R ? R : never, messageEventId: string, articleId: string, recipientPubkey: string, authorPubkey: string, finalize: (value: boolean) => void, isResolved: () => boolean ): void { sub.on('event', (event: Event) => { handleMessageVerificationEvent(event, articleId, recipientPubkey, authorPubkey, finalize) }) sub.on('eose', () => { console.warn('Private message not found on relay after EOSE', { messageEventId, articleId, recipientPubkey, timestamp: new Date().toISOString(), }) finalize(false) }) setTimeout(() => { if (!isResolved()) { console.warn('Timeout verifying private message on relay', { messageEventId, articleId, recipientPubkey, timestamp: new Date().toISOString(), }) finalize(false) } }, 5000) } function createMessageVerificationSubscription( pool: import('@/types/nostr-tools-extended').SimplePoolWithSub, messageEventId: string, authorPubkey: string, recipientPubkey: string, articleId: string ) { const filters = createMessageVerificationFilters(messageEventId, authorPubkey, recipientPubkey, articleId) const relayUrl = getPrimaryRelaySync() return pool.sub([relayUrl], filters) } function createVerificationPromise( sub: import('@/types/nostr-tools-extended').SimplePoolWithSub['sub'] extends (...args: any[]) => infer R ? R : never, messageEventId: string, articleId: string, recipientPubkey: string, authorPubkey: string ): Promise { return new Promise((resolve) => { let resolved = false const finalize = (value: boolean) => { if (resolved) { return } resolved = true sub.unsub() resolve(value) } setupMessageVerificationHandlers(sub, messageEventId, articleId, recipientPubkey, authorPubkey, finalize, () => resolved) }) } export function verifyPrivateMessagePublished( messageEventId: string, authorPubkey: string, recipientPubkey: string, articleId: string ): Promise { try { const pool = nostrService.getPool() if (!pool) { console.error('Pool not initialized for message verification', { messageEventId, articleId, recipientPubkey, }) return Promise.resolve(false) } const sub = createMessageVerificationSubscription( pool as import('@/types/nostr-tools-extended').SimplePoolWithSub, messageEventId, authorPubkey, recipientPubkey, articleId ) return createVerificationPromise(sub, messageEventId, articleId, recipientPubkey, authorPubkey) } catch (error) { console.error('Error verifying private message', { messageEventId, articleId, recipientPubkey, error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString(), }) return Promise.resolve(false) } } export async function publishAndVerifyMessage( articleId: string, recipientPubkey: string, authorPubkey: string, messageEventId: string ): Promise { const verified = await verifyPrivateMessagePublished(messageEventId, authorPubkey, recipientPubkey, articleId) if (verified) { console.log('Private message verified on relay', { messageEventId, articleId, recipientPubkey }) } else { console.warn('Private message published but not yet verified on relay', { messageEventId, articleId, recipientPubkey }) } return verified }