2026-01-13 14:49:19 +01:00

41 lines
1.7 KiB
TypeScript

import type { Event } from 'nostr-tools'
import { generateReviewTipHashId } from '../hashIdGenerator'
import type { ExtractedReviewTip } from './types'
import { readAmountSats, readPaymentHash, readPayerPubkeyFromZapReceipt, readTagValue, readZapReceiptKind } from './utils'
export async function extractReviewTipFromEvent(event: Event): Promise<ExtractedReviewTip | null> {
if (event.kind !== 9735 || readZapReceiptKind(event) !== 'review_tip') {
return null
}
const extracted = readReviewTipFields(event)
if (!extracted) {
return null
}
const id = await generateReviewTipHashId(extracted)
return { type: 'review_tip', id, ...extracted, eventId: event.id }
}
function readReviewTipFields(event: Event): Omit<ExtractedReviewTip, 'type' | 'id' | 'eventId'> | null {
const payerPubkey = readPayerPubkeyFromZapReceipt(event)
const amount = readAmountSats(event)
const paymentHash = readPaymentHash(event)
const reviewerPubkey = readTagValue(event, 'reviewer') ?? readTagValue(event, 'p')
const authorPubkey = readTagValue(event, 'author')
const articleId = readTagValue(event, 'article')
const reviewId = readTagValue(event, 'review_id') ?? readTagValue(event, 'e')
const required = { payerPubkey, reviewerPubkey, authorPubkey, articleId, reviewId }
if (!areAllNonEmptyStrings(required) || amount === undefined) {
console.error('[metadataExtractor] Invalid review_tip zap receipt: missing required fields', { eventId: event.id })
return null
}
return { ...required, amount, paymentHash }
}
function areAllNonEmptyStrings(values: Record<string, string | undefined>): values is Record<string, string> {
return Object.values(values).every((value) => typeof value === 'string' && value.length > 0)
}