import { calculateArticleSplit, calculateReviewSplit } from './platformCommissions' /** * Automatic transfer service * Handles automatic forwarding of author/reviewer portions after payment * * Since WebLN doesn't support BOLT12 with split, the platform receives the full amount * and must automatically forward the author/reviewer portion. * * This service tracks transfers and ensures they are executed correctly. */ export interface TransferResult { success: boolean transferInvoiceId?: string error?: string amount: number recipient: string } export class AutomaticTransferService { /** * Transfer author portion after article payment * Creates a Lightning invoice from the platform to the author */ private logTransferRequired(params: { type: 'article' | 'review' id: string pubkey: string amount: number recipient: string platformCommission: number }): void { const logData = { [params.type === 'article' ? 'articleId' : 'reviewId']: params.id, [params.type === 'article' ? 'articlePubkey' : 'reviewerPubkey']: params.pubkey, amount: params.amount, recipient: params.recipient, platformCommission: params.platformCommission, timestamp: new Date().toISOString(), } console.warn(`Automatic transfer required${params.type === 'review' ? ' for review' : ''}`, logData) } private buildTransferError(error: unknown, recipient: string, amount: number = 0): TransferResult { const errorMessage = error instanceof Error ? error.message : 'Unknown error' return { success: false, error: errorMessage, amount, recipient, } } async transferAuthorPortion( authorLightningAddress: string, articleId: string, articlePubkey: string, paymentAmount: number ): Promise { try { const split = calculateArticleSplit(paymentAmount) if (!authorLightningAddress) { return { success: false, error: 'Author Lightning address not available', amount: split.author, recipient: authorLightningAddress, } } this.logTransferRequired({ type: 'article', id: articleId, pubkey: articlePubkey, amount: split.author, recipient: authorLightningAddress, platformCommission: split.platform, }) this.trackTransferRequirement({ type: 'article', id: articleId, recipientPubkey: articlePubkey, amount: split.author, recipientAddress: authorLightningAddress, }) return { success: true, amount: split.author, recipient: authorLightningAddress, } } catch (error) { console.error('Error transferring author portion', { articleId, articlePubkey, error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString(), }) return this.buildTransferError(error, authorLightningAddress) } } /** * Transfer reviewer portion after review reward payment */ async transferReviewerPortion( reviewerLightningAddress: string, reviewId: string, reviewerPubkey: string, paymentAmount: number ): Promise { try { const split = calculateReviewSplit(paymentAmount) if (!reviewerLightningAddress) { return { success: false, error: 'Reviewer Lightning address not available', amount: split.reviewer, recipient: reviewerLightningAddress, } } this.logTransferRequired({ type: 'review', id: reviewId, pubkey: reviewerPubkey, amount: split.reviewer, recipient: reviewerLightningAddress, platformCommission: split.platform, }) this.trackTransferRequirement({ type: 'review', id: reviewId, recipientPubkey: reviewerPubkey, amount: split.reviewer, recipientAddress: reviewerLightningAddress, }) return { success: true, amount: split.reviewer, recipient: reviewerLightningAddress, } } catch (error) { console.error('Error transferring reviewer portion', { reviewId, reviewerPubkey, error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString(), }) return this.buildTransferError(error, reviewerLightningAddress) } } /** * Track transfer requirement for later processing * In production, this would be stored in a database or queue */ private trackTransferRequirement( params: { type: 'article' | 'review' id: string recipientPubkey: string amount: number recipientAddress: string } ): void { // In production, this would: // 1. Store in a database/queue for processing // 2. Trigger automatic transfer via platform's Lightning node // 3. Update tracking when transfer is complete console.warn('Transfer requirement tracked', { type: params.type, id: params.id, recipientPubkey: params.recipientPubkey, amount: params.amount, recipientAddress: params.recipientAddress, timestamp: new Date().toISOString(), }) } } export const automaticTransferService = new AutomaticTransferService()