story-research-zapwall/lib/paymentPolling.ts
2025-12-22 09:48:57 +01:00

96 lines
2.6 KiB
TypeScript

import { nostrService } from './nostr'
import { articlePublisher } from './articlePublisher'
import { getStoredPrivateContent } from './articleStorage'
/**
* Poll for payment completion via zap receipt verification
* After payment is confirmed, sends private content to the user
*/
export async function waitForArticlePayment(
paymentHash: string,
articleId: string,
articlePubkey: string,
amount: number,
recipientPubkey: string,
timeout: number = 300000 // 5 minutes
): Promise<boolean> {
try {
// With Alby/WebLN, we rely on zap receipts for payment verification
// Poll for zap receipt confirmation
const startTime = Date.now()
const interval = 2000 // 2 seconds
return new Promise((resolve) => {
const checkZapReceipt = async () => {
try {
const zapReceiptExists = await nostrService.checkZapReceipt(
articlePubkey,
articleId,
amount,
recipientPubkey
)
if (zapReceiptExists) {
await sendPrivateContentAfterPayment(articleId, recipientPubkey)
resolve(true)
return
}
if (Date.now() - startTime > timeout) {
resolve(false)
return
}
setTimeout(checkZapReceipt, interval)
} catch (error) {
console.error('Error checking zap receipt:', error)
if (Date.now() - startTime > timeout) {
resolve(false)
} else {
setTimeout(checkZapReceipt, interval)
}
}
}
checkZapReceipt()
})
} catch (error) {
console.error('Wait for payment error:', error)
return false
}
}
/**
* Send private content to user after payment confirmation
*/
async function sendPrivateContentAfterPayment(
articleId: string,
recipientPubkey: string
): Promise<void> {
// Send private content to the user
const storedContent = await getStoredPrivateContent(articleId)
if (storedContent) {
const authorPrivateKey = nostrService.getPrivateKey()
if (authorPrivateKey) {
const sent = await articlePublisher.sendPrivateContent(
articleId,
recipientPubkey,
storedContent.authorPubkey,
authorPrivateKey
)
if (sent) {
console.log('Private content sent successfully to user')
} else {
console.warn('Failed to send private content, but payment was confirmed')
}
} else {
console.warn('Author private key not available, cannot send private content automatically')
}
} else {
console.warn('Stored private content not found for article:', articleId)
}
}