import { calculateSponsoringSplit, PLATFORM_COMMISSIONS, PLATFORM_BITCOIN_ADDRESS } from './platformCommissions' import { platformTracking } from './platformTracking' /** * Sponsoring payment service * Handles Bitcoin mainnet payments for sponsoring with automatic commission split * * Sponsoring: 0.046 BTC total * - Author: 0.042 BTC (4,200,000 sats) * - Platform: 0.004 BTC (400,000 sats) * * Since Bitcoin mainnet doesn't support automatic split like Lightning, * we use a two-output transaction approach: * 1. User creates transaction with two outputs (author + platform) * 2. Platform verifies both outputs are present * 3. Transaction is broadcast */ export interface SponsoringPaymentRequest { authorPubkey: string authorMainnetAddress: string amount: number // Should be 0.046 BTC } export interface SponsoringPaymentResult { success: boolean transactionId?: string error?: string split: { author: number platform: number total: number authorSats: number platformSats: number totalSats: number } platformAddress: string authorAddress: string } export class SponsoringPaymentService { /** * Create sponsoring payment request with split information * Returns addresses and amounts for the user to create a Bitcoin transaction */ async createSponsoringPayment(request: SponsoringPaymentRequest): Promise { try { // Verify amount matches expected commission structure if (request.amount !== PLATFORM_COMMISSIONS.sponsoring.total) { return { success: false, error: `Invalid sponsoring amount: ${request.amount} BTC. Expected ${PLATFORM_COMMISSIONS.sponsoring.total} BTC`, split: calculateSponsoringSplit(), platformAddress: PLATFORM_BITCOIN_ADDRESS, authorAddress: request.authorMainnetAddress, } } const split = calculateSponsoringSplit(request.amount) // Verify addresses are valid Bitcoin addresses if (!this.isValidBitcoinAddress(request.authorMainnetAddress)) { return { success: false, error: 'Invalid author Bitcoin address', split, platformAddress: PLATFORM_BITCOIN_ADDRESS, authorAddress: request.authorMainnetAddress, } } console.log('Sponsoring payment request created', { authorPubkey: request.authorPubkey, authorAddress: request.authorMainnetAddress, platformAddress: PLATFORM_BITCOIN_ADDRESS, authorAmount: split.authorSats, platformAmount: split.platformSats, totalAmount: split.totalSats, timestamp: new Date().toISOString(), }) return { success: true, split, platformAddress: PLATFORM_BITCOIN_ADDRESS, authorAddress: request.authorMainnetAddress, } } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error' console.error('Error creating sponsoring payment', { authorPubkey: request.authorPubkey, error: errorMessage, timestamp: new Date().toISOString(), }) return { success: false, error: errorMessage, split: calculateSponsoringSplit(), platformAddress: PLATFORM_BITCOIN_ADDRESS, authorAddress: request.authorMainnetAddress, } } } /** * Verify sponsoring payment transaction * Checks that transaction has correct outputs for both author and platform */ async verifySponsoringPayment( transactionId: string, authorPubkey: string, authorMainnetAddress: string ): Promise { try { const split = calculateSponsoringSplit() // In production, this would: // 1. Fetch transaction from blockchain // 2. Verify it has two outputs: // - Output 1: split.authorSats to authorMainnetAddress // - Output 2: split.platformSats to PLATFORM_BITCOIN_ADDRESS // 3. Verify transaction is confirmed console.log('Verifying sponsoring payment', { transactionId, authorPubkey, authorAddress: authorMainnetAddress, platformAddress: PLATFORM_BITCOIN_ADDRESS, expectedAuthorAmount: split.authorSats, expectedPlatformAmount: split.platformSats, timestamp: new Date().toISOString(), }) // For now, return true (in production, implement actual verification) return true } catch (error) { console.error('Error verifying sponsoring payment', { transactionId, authorPubkey, error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString(), }) return false } } /** * Track sponsoring payment */ async trackSponsoringPayment( transactionId: string, authorPubkey: string, authorMainnetAddress: string, authorPrivateKey: string ): Promise { try { const split = calculateSponsoringSplit() // Track the sponsoring payment on Nostr // This would be similar to article payment tracking console.log('Tracking sponsoring payment', { transactionId, authorPubkey, authorAddress: authorMainnetAddress, platformAddress: PLATFORM_BITCOIN_ADDRESS, authorAmount: split.authorSats, platformCommission: split.platformSats, timestamp: new Date().toISOString(), }) // In production, publish tracking event on Nostr } catch (error) { console.error('Error tracking sponsoring payment', { transactionId, authorPubkey, error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString(), }) } } /** * Validate Bitcoin address format */ private isValidBitcoinAddress(address: string): boolean { // Basic validation: starts with 1, 3, or bc1 const bitcoinAddressRegex = /^(1|3|bc1)[a-zA-Z0-9]{25,62}$/ return bitcoinAddressRegex.test(address) } } export const sponsoringPaymentService = new SponsoringPaymentService()