You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

126 lines
4.4 KiB

import { buildAttestedPaymentIdSet } from '@/lib/superchat'
import {
hydrateAttestedSuperchatTargetEvents,
mergeAttestedPaymentIdSets,
peekAttestedSuperchatTargetEvents,
resolveAttestedPaymentIdSet,
resolveAttestedPaymentIdSetSync
} from '@/lib/payment-attestation-cache'
import { getPaymentAttestationTargetId } from '@/lib/superchat'
import { ExtendedKind } from '@/constants'
import client from '@/services/client.service'
import { normalizeAnyRelayUrl } from '@/lib/url'
import type { Event as NEvent } from 'nostr-tools'
import { useCallback, useEffect, useState, type MutableRefObject } from 'react'
/** Attested kind 9735/9740 ids + hydration for the thread recipient (OP). */
export function useThreadAttestedPayments(
recipientPubkey: string | undefined,
addReplies: (events: NEvent[]) => void,
threadRelayUrlsRef: MutableRefObject<string[]>,
browsingRelayUrls: string[],
replyFetchGenRef: MutableRefObject<number>
) {
const [attestedPaymentIds, setAttestedPaymentIds] = useState<Set<string>>(() =>
recipientPubkey ? resolveAttestedPaymentIdSetSync(recipientPubkey) : new Set()
)
const mergeAttestedPaymentIds = useCallback((incoming: ReadonlySet<string>) => {
setAttestedPaymentIds((prev) => {
const next = mergeAttestedPaymentIdSets(prev, incoming)
return next.size === prev.size ? prev : next
})
}, [])
const applyAttestedSuperchatWave = useCallback(
async (
relayAttestations: NEvent[],
relayUrls: string[],
fetchGeneration: number,
foreground: boolean
) => {
const pk = recipientPubkey
if (!pk) return
if (relayAttestations.length > 0) {
mergeAttestedPaymentIds(buildAttestedPaymentIdSet(relayAttestations, pk))
}
const syncIds = resolveAttestedPaymentIdSetSync(pk)
mergeAttestedPaymentIds(syncIds)
const syncTargets = peekAttestedSuperchatTargetEvents(syncIds)
if (syncTargets.length > 0) addReplies(syncTargets)
const attestedIds = await resolveAttestedPaymentIdSet(pk, relayAttestations)
if (fetchGeneration !== replyFetchGenRef.current) return
mergeAttestedPaymentIds(attestedIds)
const targets = await hydrateAttestedSuperchatTargetEvents(attestedIds, relayUrls, {
foreground
})
if (fetchGeneration !== replyFetchGenRef.current) return
if (targets.length > 0) addReplies(targets)
},
[recipientPubkey, addReplies, mergeAttestedPaymentIds, replyFetchGenRef]
)
useEffect(() => {
const pk = recipientPubkey
if (!pk) return
let cancelled = false
const syncIds = resolveAttestedPaymentIdSetSync(pk)
mergeAttestedPaymentIds(syncIds)
const syncTargets = peekAttestedSuperchatTargetEvents(syncIds)
if (syncTargets.length > 0) addReplies(syncTargets)
void (async () => {
const relayHints = threadRelayUrlsRef.current.length
? threadRelayUrlsRef.current
: browsingRelayUrls.map((u) => normalizeAnyRelayUrl(u) || u).filter(Boolean)
await applyAttestedSuperchatWave([], relayHints, replyFetchGenRef.current, true)
if (cancelled) return
})()
return () => {
cancelled = true
}
}, [
recipientPubkey,
addReplies,
browsingRelayUrls,
mergeAttestedPaymentIds,
applyAttestedSuperchatWave,
threadRelayUrlsRef,
replyFetchGenRef
])
useEffect(() => {
const pk = recipientPubkey
if (!pk) return
const handleAttestation = (data: Event) => {
const ce = data as CustomEvent<NEvent>
const evt = ce.detail
if (!evt || evt.kind !== ExtendedKind.PAYMENT_ATTESTATION) return
if (evt.pubkey.toLowerCase() !== pk.toLowerCase()) return
const targetId = getPaymentAttestationTargetId(evt)
if (!targetId) return
mergeAttestedPaymentIds(new Set([targetId]))
const cached = client.peekSessionCachedEvent(targetId)
if (cached) addReplies([cached])
void client
.fetchEvent(targetId, { relayHints: threadRelayUrlsRef.current })
.then((target) => {
if (target) addReplies([target])
})
.catch(() => {
/* optional */
})
}
client.addEventListener('newEvent', handleAttestation)
return () => client.removeEventListener('newEvent', handleAttestation)
}, [recipientPubkey, addReplies, mergeAttestedPaymentIds, threadRelayUrlsRef])
return { attestedPaymentIds, mergeAttestedPaymentIds, applyAttestedSuperchatWave }
}