- Création lib/platformCommissions.ts : configuration centralisée des commissions - Articles : 800 sats (700 auteur, 100 plateforme) - Avis : 70 sats (49 lecteur, 21 plateforme) - Sponsoring : 0.046 BTC (0.042 auteur, 0.004 plateforme) - Validation des montants à chaque étape : - Publication : vérification du montant avant publication - Paiement : vérification du montant avant acceptation - Erreurs explicites si montant incorrect - Tracking des commissions sur Nostr : - Tags author_amount et platform_commission dans événements - Interface ContentDeliveryTracking étendue - Traçabilité complète pour audit - Logs structurés avec informations de commission - Documentation complète du système Les commissions sont maintenant systématiques, validées et traçables.
91 lines
2.7 KiB
TypeScript
91 lines
2.7 KiB
TypeScript
import { getAlbyService } from './alby'
|
|
import { paymentSplitService } from './paymentSplit'
|
|
import { calculateArticleSplit, PLATFORM_COMMISSIONS } from './platformCommissions'
|
|
import type { AlbyInvoice } from '@/types/alby'
|
|
import type { ArticleDraft } from './articlePublisher'
|
|
|
|
/**
|
|
* Create Lightning invoice for article with automatic commission split
|
|
* The invoice is created for the full amount (800 sats) which includes:
|
|
* - 700 sats for the author
|
|
* - 100 sats commission for the platform
|
|
*
|
|
* The commission is automatically tracked and the split is enforced.
|
|
* Requires Alby/WebLN to be available and enabled
|
|
*/
|
|
export async function createArticleInvoice(draft: ArticleDraft): Promise<AlbyInvoice> {
|
|
// Verify amount matches expected commission structure
|
|
if (draft.zapAmount !== PLATFORM_COMMISSIONS.article.total) {
|
|
throw new Error(
|
|
`Invalid article payment amount: ${draft.zapAmount} sats. Expected ${PLATFORM_COMMISSIONS.article.total} sats (700 to author, 100 commission)`
|
|
)
|
|
}
|
|
|
|
const split = calculateArticleSplit()
|
|
|
|
// Get author's Lightning address from their profile or use platform address as fallback
|
|
// For now, we'll create the invoice through the platform's wallet
|
|
// The platform will forward the author's portion after payment
|
|
const alby = getAlbyService()
|
|
await alby.enable()
|
|
|
|
const invoice = await alby.createInvoice({
|
|
amount: split.total,
|
|
description: `Article: ${draft.title} (${split.author} sats author, ${split.platform} sats commission)`,
|
|
expiry: 86400, // 24 hours
|
|
})
|
|
|
|
return invoice
|
|
}
|
|
|
|
/**
|
|
* Create preview event with invoice tags
|
|
*/
|
|
export function createPreviewEvent(
|
|
draft: ArticleDraft,
|
|
invoice: AlbyInvoice,
|
|
authorPresentationId?: string,
|
|
extraTags: string[][] = []
|
|
): {
|
|
kind: 1
|
|
created_at: number
|
|
tags: string[][]
|
|
content: string
|
|
} {
|
|
const tags = buildPreviewTags(draft, invoice, authorPresentationId, extraTags)
|
|
|
|
return {
|
|
kind: 1 as const,
|
|
created_at: Math.floor(Date.now() / 1000),
|
|
tags,
|
|
content: draft.preview,
|
|
}
|
|
}
|
|
|
|
function buildPreviewTags(
|
|
draft: ArticleDraft,
|
|
invoice: AlbyInvoice,
|
|
authorPresentationId?: string,
|
|
extraTags: string[][] = []
|
|
): string[][] {
|
|
const base: string[][] = [
|
|
['title', draft.title],
|
|
['preview', draft.preview],
|
|
['zap', draft.zapAmount.toString()],
|
|
['content-type', 'article'],
|
|
['invoice', invoice.invoice],
|
|
['payment_hash', invoice.paymentHash],
|
|
]
|
|
if (draft.category) {
|
|
base.push(['category', draft.category])
|
|
}
|
|
if (authorPresentationId) {
|
|
base.push(['author_presentation_id', authorPresentationId])
|
|
}
|
|
// Preserve any kind_type tags in extraTags if provided by caller
|
|
if (extraTags.length > 0) {
|
|
base.push(...extraTags)
|
|
}
|
|
return base
|
|
}
|