story-research-zapwall/lib/sponsoring.ts
Nicolas Cantu 3000872dbc refactoring
- **Motivations :** Assurer passage du lint strict et clarifier la logique paiements/publications.

- **Root causes :** Fonctions trop longues, promesses non gérées et typages WebLN/Nostr incomplets.

- **Correctifs :** Refactor PaymentModal (handlers void), extraction helpers articlePublisher, simplification polling sponsoring/zap, corrections curly et awaits.

- **Evolutions :** Nouveau module articlePublisherHelpers pour présentation/aiguillage contenu privé.

- **Page affectées :** components/PaymentModal.tsx, lib/articlePublisher.ts, lib/articlePublisherHelpers.ts, lib/paymentPolling.ts, lib/sponsoring.ts, lib/nostrZapVerification.ts et dépendances liées.
2025-12-22 17:56:00 +01:00

83 lines
2.3 KiB
TypeScript

import { nostrService } from './nostr'
import { SimplePoolWithSub } from '@/types/nostr-tools-extended'
import type { Article } from '@/types/nostr'
const RELAY = process.env.NEXT_PUBLIC_NOSTR_RELAY_URL ?? 'wss://relay.damus.io'
function subscribeToPresentation(pool: SimplePoolWithSub, pubkey: string): Promise<number> {
const filters = [
{
kinds: [1],
authors: [pubkey],
'#category': ['author-presentation'],
limit: 1,
},
]
return new Promise((resolve) => {
let resolved = false
const sub = pool.sub([RELAY], filters)
const finalize = (value: number) => {
if (resolved) {
return
}
resolved = true
sub.unsub()
resolve(value)
}
sub.on('event', (event: import('nostr-tools').Event) => {
const isPresentation = event.tags.some((tag) => tag[0] === 'presentation' && tag[1] === 'true')
if (!isPresentation) {
return
}
const sponsoringTag = event.tags.find((tag) => tag[0] === 'total_sponsoring')
const total = sponsoringTag ? parseInt(sponsoringTag[1] ?? '0', 10) : 0
finalize(total)
})
sub.on('eose', () => finalize(0))
setTimeout(() => finalize(0), 5000)
})
}
/**
* Get total sponsoring for an author by their pubkey
*/
export function getAuthorSponsoring(pubkey: string): Promise<number> {
const pool = nostrService.getPool()
if (!pool) {
return Promise.resolve(0)
}
return subscribeToPresentation(pool as SimplePoolWithSub, pubkey)
}
/**
* Get sponsoring for multiple authors (for sorting)
* Returns a map of pubkey -> total sponsoring
*/
export function getAuthorsSponsoring(pubkeys: string[]): Map<string, number> {
const sponsoringMap = new Map<string, number>()
// For now, we'll extract sponsoring from articles that are already loaded
// In a real implementation, we'd query all presentation articles
// For performance, we'll use the sponsoring from the article's totalSponsoring field
pubkeys.forEach((pubkey) => {
sponsoringMap.set(pubkey, 0)
})
return sponsoringMap
}
/**
* Get sponsoring from an article (if it's a presentation article)
*/
export function getSponsoringFromArticle(article: Article): number {
if (article.isPresentation && article.totalSponsoring !== undefined) {
return article.totalSponsoring
}
return 0
}