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.
86 lines
3.0 KiB
86 lines
3.0 KiB
import { |
|
getAlternativePaymentMethods, |
|
groupPaymentMethodsByDisplayType, |
|
mergePaymentMethods, |
|
recipientHasAnyPaymentOptions, |
|
sortMergedPaymentMethods, |
|
type PaymentMethodGroup |
|
} from '@/lib/merge-payment-methods' |
|
import { getPaymentInfoFromEvent, getProfileFromEvent } from '@/lib/event-metadata' |
|
import client, { replaceableEventService } from '@/services/client.service' |
|
import { kinds, type Event } from 'nostr-tools' |
|
import { useEffect, useMemo, useState } from 'react' |
|
import type { TPaymentInfo } from '@/types' |
|
import type { TProfile } from '@/types' |
|
|
|
export type RecipientZapPaymentData = { |
|
paymentInfo: TPaymentInfo | null |
|
profile: TProfile | null |
|
profileEvent: Event | null |
|
alternativeGroups: PaymentMethodGroup[] |
|
/** Any payto / Lightning target on kind 0 or 10133 — used to enable zap UI. */ |
|
canReceiveTip: boolean |
|
} |
|
|
|
/** Kind 10133 + profile payto targets except the Lightning address used for zapping. */ |
|
export function useRecipientZapPaymentData( |
|
recipientPubkey: string | undefined, |
|
enabled: boolean |
|
): RecipientZapPaymentData { |
|
const [paymentInfo, setPaymentInfo] = useState<TPaymentInfo | null>(null) |
|
const [profile, setProfile] = useState<TProfile | null>(null) |
|
const [profileEvent, setProfileEvent] = useState<Event | null>(null) |
|
|
|
useEffect(() => { |
|
if (!enabled || !recipientPubkey) { |
|
setPaymentInfo(null) |
|
setProfile(null) |
|
setProfileEvent(null) |
|
return |
|
} |
|
let cancelled = false |
|
void (async () => { |
|
try { |
|
const [paymentEvent, metaEvent] = await Promise.all([ |
|
client.fetchPaymentInfoEvent(recipientPubkey), |
|
replaceableEventService.fetchReplaceableEvent(recipientPubkey, kinds.Metadata) |
|
]) |
|
if (cancelled) return |
|
setPaymentInfo(paymentEvent ? getPaymentInfoFromEvent(paymentEvent) : null) |
|
setProfileEvent(metaEvent ?? null) |
|
setProfile(metaEvent ? getProfileFromEvent(metaEvent) : null) |
|
} catch { |
|
if (!cancelled) { |
|
setPaymentInfo(null) |
|
setProfile(null) |
|
setProfileEvent(null) |
|
} |
|
} |
|
})() |
|
return () => { |
|
cancelled = true |
|
} |
|
}, [recipientPubkey, enabled]) |
|
|
|
const canReceiveTip = useMemo( |
|
() => recipientHasAnyPaymentOptions(paymentInfo, profile, profileEvent), |
|
[paymentInfo, profile, profileEvent] |
|
) |
|
|
|
const alternativeGroups = useMemo(() => { |
|
if (!recipientPubkey) return [] |
|
const merged = sortMergedPaymentMethods(mergePaymentMethods(paymentInfo, profile, profileEvent)) |
|
const alts = getAlternativePaymentMethods(merged) |
|
return groupPaymentMethodsByDisplayType(alts) |
|
}, [recipientPubkey, paymentInfo, profile, profileEvent]) |
|
|
|
return { paymentInfo, profile, profileEvent, alternativeGroups, canReceiveTip } |
|
} |
|
|
|
/** @deprecated Use {@link useRecipientZapPaymentData} */ |
|
export function useRecipientAlternativePayments( |
|
recipientPubkey: string | undefined, |
|
enabled: boolean |
|
): PaymentMethodGroup[] { |
|
return useRecipientZapPaymentData(recipientPubkey, enabled).alternativeGroups |
|
}
|
|
|