import { getAlbyService } from './alby' import { calculateReviewSplit, PLATFORM_COMMISSIONS } from './platformCommissions' import { automaticTransferService } from './automaticTransfer' import { platformTracking } from './platformTracking' import { nostrService } from './nostr' import type { AlbyInvoice } from '@/types/alby' /** * Review reward service * Handles Lightning payments for rewarding reviews with automatic commission split * * Review reward: 70 sats total * - Reviewer: 49 sats * - Platform: 21 sats */ export interface ReviewRewardRequest { reviewId: string articleId: string reviewerPubkey: string reviewerLightningAddress?: string authorPubkey: string authorPrivateKey: string } export interface ReviewRewardResult { success: boolean invoice?: AlbyInvoice paymentHash?: string error?: string split: { reviewer: number platform: number total: number } } export class ReviewRewardService { /** * Create review reward payment with commission split */ async createReviewRewardPayment(request: ReviewRewardRequest): Promise { try { const split = calculateReviewSplit() // Verify author has permission to reward this review // (should be verified before calling this function) const alby = getAlbyService() await alby.enable() const invoice = await alby.createInvoice({ amount: split.total, description: `Review reward: ${request.reviewId} (${split.reviewer} sats to reviewer, ${split.platform} sats commission)`, expiry: 3600, // 1 hour }) console.log('Review reward invoice created', { reviewId: request.reviewId, articleId: request.articleId, reviewerPubkey: request.reviewerPubkey, amount: split.total, reviewerPortion: split.reviewer, platformCommission: split.platform, timestamp: new Date().toISOString(), }) return { success: true, invoice, paymentHash: invoice.paymentHash, split, } } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error' console.error('Error creating review reward payment', { reviewId: request.reviewId, articleId: request.articleId, error: errorMessage, timestamp: new Date().toISOString(), }) return { success: false, error: errorMessage, split: calculateReviewSplit(), } } } /** * Process review reward payment after confirmation * Transfers reviewer portion and tracks commission */ async processReviewRewardPayment( request: ReviewRewardRequest, paymentHash: string ): Promise { try { const split = calculateReviewSplit() // Verify payment was made // (should be verified via zap receipt before calling this) // Transfer reviewer portion if (request.reviewerLightningAddress) { const transferResult = await automaticTransferService.transferReviewerPortion( request.reviewerLightningAddress, request.reviewId, request.reviewerPubkey, split.total ) if (!transferResult.success) { console.error('Failed to transfer reviewer portion', { reviewId: request.reviewId, error: transferResult.error, timestamp: new Date().toISOString(), }) // Continue anyway - transfer can be done manually later } } // Track the reward payment await this.trackReviewReward(request, split, paymentHash) // Update review event with reward tag await this.updateReviewWithReward(request.reviewId, request.authorPrivateKey) console.log('Review reward processed', { reviewId: request.reviewId, articleId: request.articleId, reviewerPubkey: request.reviewerPubkey, reviewerAmount: split.reviewer, platformCommission: split.platform, timestamp: new Date().toISOString(), }) return true } catch (error) { console.error('Error processing review reward payment', { reviewId: request.reviewId, error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString(), }) return false } } /** * Track review reward payment */ private async trackReviewReward( request: ReviewRewardRequest, split: { reviewer: number; platform: number; total: number }, paymentHash: string ): Promise { try { // In production, publish tracking event on Nostr similar to article payments console.log('Review reward tracked', { reviewId: request.reviewId, articleId: request.articleId, reviewerPubkey: request.reviewerPubkey, authorPubkey: request.authorPubkey, reviewerAmount: split.reviewer, platformCommission: split.platform, paymentHash, timestamp: new Date().toISOString(), }) } catch (error) { console.error('Error tracking review reward', { reviewId: request.reviewId, error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString(), }) } } /** * Update review event with reward tag */ private async updateReviewWithReward(reviewId: string, authorPrivateKey: string): Promise { try { // In production, this would: // 1. Fetch the review event // 2. Add tags: ['rewarded', 'true'], ['reward_amount', '70'] // 3. Publish updated event console.log('Review updated with reward tag', { reviewId, timestamp: new Date().toISOString(), }) } catch (error) { console.error('Error updating review with reward', { reviewId, error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString(), }) } } } export const reviewRewardService = new ReviewRewardService()