|
|
|
@ -6,9 +6,7 @@ import { |
|
|
|
import { hexPubkeysEqual } from '@/lib/pubkey' |
|
|
|
import { hexPubkeysEqual } from '@/lib/pubkey' |
|
|
|
import { |
|
|
|
import { |
|
|
|
hydrateAttestationsForAuthor, |
|
|
|
hydrateAttestationsForAuthor, |
|
|
|
isLocallyMarkedAttested, |
|
|
|
|
|
|
|
loadPaymentAttestationLocal, |
|
|
|
loadPaymentAttestationLocal, |
|
|
|
markLocalAttestationTarget, |
|
|
|
|
|
|
|
peekCachedPaymentAttestation, |
|
|
|
peekCachedPaymentAttestation, |
|
|
|
refreshPaymentAttestationFromRelays, |
|
|
|
refreshPaymentAttestationFromRelays, |
|
|
|
rememberPaymentAttestationFromPublish |
|
|
|
rememberPaymentAttestationFromPublish |
|
|
|
@ -26,6 +24,17 @@ function attestationFilter(recipientPubkey: string, targetEventId: string) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function isPaymentAttestationForTarget( |
|
|
|
|
|
|
|
attestation: NostrEvent, |
|
|
|
|
|
|
|
targetEventId: string, |
|
|
|
|
|
|
|
recipientPubkey: string |
|
|
|
|
|
|
|
): boolean { |
|
|
|
|
|
|
|
if (attestation.kind !== ExtendedKind.PAYMENT_ATTESTATION) return false |
|
|
|
|
|
|
|
if (!hexPubkeysEqual(attestation.pubkey, recipientPubkey)) return false |
|
|
|
|
|
|
|
const attestedId = getPaymentAttestationTargetId(attestation) |
|
|
|
|
|
|
|
return Boolean(attestedId && attestedId.toLowerCase() === targetEventId.trim().toLowerCase()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function readAttestedFromLocalSources( |
|
|
|
function readAttestedFromLocalSources( |
|
|
|
targetEventId: string | undefined, |
|
|
|
targetEventId: string | undefined, |
|
|
|
recipientPubkey: string | null |
|
|
|
recipientPubkey: string | null |
|
|
|
@ -34,9 +43,8 @@ function readAttestedFromLocalSources( |
|
|
|
return { attested: false, attestationEvent: null } |
|
|
|
return { attested: false, attestationEvent: null } |
|
|
|
} |
|
|
|
} |
|
|
|
const hit = peekCachedPaymentAttestation(targetEventId, recipientPubkey) |
|
|
|
const hit = peekCachedPaymentAttestation(targetEventId, recipientPubkey) |
|
|
|
const locallyMarked = isLocallyMarkedAttested(recipientPubkey, targetEventId) |
|
|
|
|
|
|
|
return { |
|
|
|
return { |
|
|
|
attested: Boolean(hit) || locallyMarked, |
|
|
|
attested: Boolean(hit), |
|
|
|
attestationEvent: hit ?? null |
|
|
|
attestationEvent: hit ?? null |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -64,23 +72,25 @@ export function usePaymentAttestationStatus(targetEvent: NostrEvent | undefined) |
|
|
|
) |
|
|
|
) |
|
|
|
const [checking, setChecking] = useState(false) |
|
|
|
const [checking, setChecking] = useState(false) |
|
|
|
|
|
|
|
|
|
|
|
const applyMatch = useCallback((match: NostrEvent | undefined) => { |
|
|
|
const applyMatch = useCallback( |
|
|
|
if (!match) return |
|
|
|
(match: NostrEvent | undefined) => { |
|
|
|
setAttestationEvent(match) |
|
|
|
if (!match || !targetEvent?.id || !recipientPubkey) return |
|
|
|
setAttested(true) |
|
|
|
if (!isPaymentAttestationForTarget(match, targetEvent.id, recipientPubkey)) return |
|
|
|
|
|
|
|
setAttestationEvent(match) |
|
|
|
|
|
|
|
setAttested(true) |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
[recipientPubkey, targetEvent?.id] |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const clearAttested = useCallback(() => { |
|
|
|
|
|
|
|
setAttestationEvent(null) |
|
|
|
|
|
|
|
setAttested(false) |
|
|
|
}, []) |
|
|
|
}, []) |
|
|
|
|
|
|
|
|
|
|
|
const markAttested = useCallback( |
|
|
|
const markAttested = useCallback( |
|
|
|
(attestation: NostrEvent) => { |
|
|
|
(attestation: NostrEvent) => { |
|
|
|
if (!targetEvent?.id || !recipientPubkey) return |
|
|
|
if (!targetEvent?.id || !recipientPubkey) return |
|
|
|
markLocalAttestationTarget(recipientPubkey, targetEvent.id) |
|
|
|
if (!isPaymentAttestationForTarget(attestation, targetEvent.id, recipientPubkey)) return |
|
|
|
if (attestation.kind !== ExtendedKind.PAYMENT_ATTESTATION) { |
|
|
|
|
|
|
|
setAttested(true) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!hexPubkeysEqual(attestation.pubkey, recipientPubkey)) return |
|
|
|
|
|
|
|
const attestedId = getPaymentAttestationTargetId(attestation) |
|
|
|
|
|
|
|
if (!attestedId || attestedId.toLowerCase() !== targetEvent.id.toLowerCase()) return |
|
|
|
|
|
|
|
rememberPaymentAttestationFromPublish(attestation) |
|
|
|
rememberPaymentAttestationFromPublish(attestation) |
|
|
|
applyMatch(attestation) |
|
|
|
applyMatch(attestation) |
|
|
|
}, |
|
|
|
}, |
|
|
|
@ -101,10 +111,6 @@ export function usePaymentAttestationStatus(targetEvent: NostrEvent | undefined) |
|
|
|
useEffect(() => { |
|
|
|
useEffect(() => { |
|
|
|
if (!targetEvent?.id || !recipientPubkey || !filter) return |
|
|
|
if (!targetEvent?.id || !recipientPubkey || !filter) return |
|
|
|
|
|
|
|
|
|
|
|
if (isLocallyMarkedAttested(recipientPubkey, targetEvent.id)) { |
|
|
|
|
|
|
|
setAttested(true) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let cancelled = false |
|
|
|
let cancelled = false |
|
|
|
setChecking(true) |
|
|
|
setChecking(true) |
|
|
|
|
|
|
|
|
|
|
|
@ -116,16 +122,17 @@ export function usePaymentAttestationStatus(targetEvent: NostrEvent | undefined) |
|
|
|
applyMatch(local) |
|
|
|
applyMatch(local) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
if (isLocallyMarkedAttested(recipientPubkey, targetEvent.id)) { |
|
|
|
|
|
|
|
setAttested(true) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
const relay = await refreshPaymentAttestationFromRelays( |
|
|
|
const relay = await refreshPaymentAttestationFromRelays( |
|
|
|
targetEvent.id, |
|
|
|
targetEvent.id, |
|
|
|
recipientPubkey, |
|
|
|
recipientPubkey, |
|
|
|
filter |
|
|
|
filter |
|
|
|
) |
|
|
|
) |
|
|
|
if (!cancelled) applyMatch(relay) |
|
|
|
if (cancelled) return |
|
|
|
|
|
|
|
if (relay) { |
|
|
|
|
|
|
|
applyMatch(relay) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
clearAttested() |
|
|
|
|
|
|
|
} |
|
|
|
} catch { |
|
|
|
} catch { |
|
|
|
/* optional */ |
|
|
|
/* optional */ |
|
|
|
} finally { |
|
|
|
} finally { |
|
|
|
@ -136,13 +143,15 @@ export function usePaymentAttestationStatus(targetEvent: NostrEvent | undefined) |
|
|
|
return () => { |
|
|
|
return () => { |
|
|
|
cancelled = true |
|
|
|
cancelled = true |
|
|
|
} |
|
|
|
} |
|
|
|
}, [applyMatch, filter, recipientPubkey, targetEvent?.id, targetId]) |
|
|
|
}, [applyMatch, clearAttested, filter, recipientPubkey, targetEvent?.id, targetId]) |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
useEffect(() => { |
|
|
|
if (!targetEvent?.id || !recipientPubkey) return |
|
|
|
if (!targetEvent?.id || !recipientPubkey) return |
|
|
|
|
|
|
|
|
|
|
|
const handleAttestation = (data: globalThis.Event) => { |
|
|
|
const handleAttestation = (data: globalThis.Event) => { |
|
|
|
markAttested((data as CustomEvent<NostrEvent>).detail) |
|
|
|
const attestation = (data as CustomEvent<NostrEvent>).detail |
|
|
|
|
|
|
|
if (attestation.kind !== ExtendedKind.PAYMENT_ATTESTATION) return |
|
|
|
|
|
|
|
markAttested(attestation) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
client.addEventListener('newEvent', handleAttestation) |
|
|
|
client.addEventListener('newEvent', handleAttestation) |
|
|
|
|