fix: move getTotalZapAmount from relay controller to ndkContext
This commit is contained in:
parent
59f4fd6b29
commit
82b87b3e32
@ -5,8 +5,7 @@ import { handleModImageError } from '../utils'
|
||||
import { ModDetails } from 'types'
|
||||
import { getModPageRoute } from 'routes'
|
||||
import { kinds, nip19 } from 'nostr-tools'
|
||||
import { useDidMount, useReactions } from 'hooks'
|
||||
import { RelayController } from 'controllers'
|
||||
import { useDidMount, useNDKContext, useReactions } from 'hooks'
|
||||
import { toast } from 'react-toastify'
|
||||
import { useComments } from 'hooks/useComments'
|
||||
|
||||
@ -19,10 +18,10 @@ export const ModCard = React.memo((props: ModDetails) => {
|
||||
eTag: props.id,
|
||||
aTag: props.aTag
|
||||
})
|
||||
const { getTotalZapAmount } = useNDKContext()
|
||||
|
||||
useDidMount(() => {
|
||||
RelayController.getInstance()
|
||||
.getTotalZapAmount(props.author, props.id, props.aTag)
|
||||
getTotalZapAmount(props.author, props.id, props.aTag)
|
||||
.then((res) => {
|
||||
setTotalZappedAmount(res.accumulatedZapAmount)
|
||||
})
|
||||
|
@ -5,7 +5,8 @@ import NDK, {
|
||||
NDKKind,
|
||||
NDKRelaySet,
|
||||
NDKSubscriptionCacheUsage,
|
||||
NDKUser
|
||||
NDKUser,
|
||||
zapInvoiceFromEvent
|
||||
} from '@nostr-dev-kit/ndk'
|
||||
import NDKCacheAdapterDexie from '@nostr-dev-kit/ndk-cache-dexie'
|
||||
import { MOD_FILTER_LIMIT, T_TAG_VALUE } from 'constants.ts'
|
||||
@ -36,16 +37,25 @@ interface NDKContextType {
|
||||
fetchEvents: (filter: NDKFilter) => Promise<NDKEvent[]>
|
||||
fetchEvent: (filter: NDKFilter) => Promise<NDKEvent | null>
|
||||
fetchEventsFromUserRelays: (
|
||||
filter: NDKFilter,
|
||||
filter: NDKFilter | NDKFilter[],
|
||||
hexKey: string,
|
||||
userRelaysType: UserRelaysType
|
||||
) => Promise<NDKEvent[]>
|
||||
fetchEventFromUserRelays: (
|
||||
filter: NDKFilter,
|
||||
filter: NDKFilter | NDKFilter[],
|
||||
hexKey: string,
|
||||
userRelaysType: UserRelaysType
|
||||
) => Promise<NDKEvent | null>
|
||||
findMetadata: (pubkey: string) => Promise<UserProfile>
|
||||
getTotalZapAmount: (
|
||||
user: string,
|
||||
eTag: string,
|
||||
aTag?: string,
|
||||
currentLoggedInUser?: string
|
||||
) => Promise<{
|
||||
accumulatedZapAmount: number
|
||||
hasZapped: boolean
|
||||
}>
|
||||
}
|
||||
|
||||
// Create the context with an initial value of `null`
|
||||
@ -218,10 +228,10 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
||||
* @returns A promise that resolves with an array of events.
|
||||
*/
|
||||
const fetchEventsFromUserRelays = async (
|
||||
filter: NDKFilter,
|
||||
filter: NDKFilter | NDKFilter[],
|
||||
hexKey: string,
|
||||
userRelaysType: UserRelaysType
|
||||
) => {
|
||||
): Promise<NDKEvent[]> => {
|
||||
// Find the user's relays.
|
||||
const relayUrls = await getRelayListForUser(hexKey, ndk)
|
||||
.then((ndkRelayList) => {
|
||||
@ -266,7 +276,7 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
||||
* @returns A promise that resolves to the fetched event or null if the operation fails.
|
||||
*/
|
||||
const fetchEventFromUserRelays = async (
|
||||
filter: NDKFilter,
|
||||
filter: NDKFilter | NDKFilter[],
|
||||
hexKey: string,
|
||||
userRelaysType: UserRelaysType
|
||||
) => {
|
||||
@ -296,6 +306,52 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
||||
return userProfile
|
||||
}
|
||||
|
||||
const getTotalZapAmount = async (
|
||||
user: string,
|
||||
eTag: string,
|
||||
aTag?: string,
|
||||
currentLoggedInUser?: string
|
||||
) => {
|
||||
const filters: NDKFilter[] = [
|
||||
{
|
||||
kinds: [NDKKind.Zap],
|
||||
'#e': [eTag],
|
||||
'#p': [user]
|
||||
}
|
||||
]
|
||||
|
||||
if (aTag) {
|
||||
filters.push({
|
||||
kinds: [NDKKind.Zap],
|
||||
'#a': [aTag],
|
||||
'#p': [user]
|
||||
})
|
||||
}
|
||||
|
||||
const zapEvents = await fetchEventsFromUserRelays(
|
||||
filters,
|
||||
user,
|
||||
UserRelaysType.Read
|
||||
)
|
||||
|
||||
let accumulatedZapAmount = 0
|
||||
let hasZapped = false
|
||||
|
||||
zapEvents.forEach((zap) => {
|
||||
const zapInvoice = zapInvoiceFromEvent(zap)
|
||||
if (zapInvoice) {
|
||||
accumulatedZapAmount += Math.round(zapInvoice.amount / 1000)
|
||||
|
||||
if (!hasZapped) hasZapped = zapInvoice.zappee === currentLoggedInUser
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
accumulatedZapAmount,
|
||||
hasZapped
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<NDKContext.Provider
|
||||
value={{
|
||||
@ -305,7 +361,8 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
||||
fetchEvent,
|
||||
fetchEventsFromUserRelays,
|
||||
fetchEventFromUserRelays,
|
||||
findMetadata
|
||||
findMetadata,
|
||||
getTotalZapAmount
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
@ -1,11 +1,5 @@
|
||||
import { Event, Filter, kinds, nip57, Relay } from 'nostr-tools'
|
||||
import {
|
||||
extractZapAmount,
|
||||
log,
|
||||
LogType,
|
||||
normalizeWebSocketURL,
|
||||
timeout
|
||||
} from '../utils'
|
||||
import { Event, Relay } from 'nostr-tools'
|
||||
import { log, LogType, normalizeWebSocketURL, timeout } from '../utils'
|
||||
import { MetadataController, UserRelaysType } from './metadata'
|
||||
|
||||
/**
|
||||
@ -371,122 +365,4 @@ export class RelayController {
|
||||
// Return the list of relay URLs where the event was successfully published
|
||||
return publishedOnRelays
|
||||
}
|
||||
|
||||
getTotalZapAmount = async (
|
||||
user: string,
|
||||
eTag: string,
|
||||
aTag?: string,
|
||||
currentLoggedInUser?: string
|
||||
) => {
|
||||
const metadataController = await MetadataController.getInstance()
|
||||
|
||||
const relayUrls = await metadataController.findUserRelays(
|
||||
user,
|
||||
UserRelaysType.Read
|
||||
)
|
||||
|
||||
const appRelay = import.meta.env.VITE_APP_RELAY
|
||||
if (!relayUrls.includes(appRelay)) {
|
||||
relayUrls.push(appRelay)
|
||||
}
|
||||
|
||||
// Connect to all specified relays
|
||||
const relayPromises = relayUrls.map((relayUrl) =>
|
||||
this.connectRelay(relayUrl)
|
||||
)
|
||||
|
||||
// Use Promise.allSettled to wait for all promises to settle
|
||||
const results = await Promise.allSettled(relayPromises)
|
||||
|
||||
// Extract non-null values from fulfilled promises in a single pass
|
||||
const relays = results.reduce<Relay[]>((acc, result) => {
|
||||
if (result.status === 'fulfilled') {
|
||||
const value = result.value
|
||||
if (value) {
|
||||
acc.push(value)
|
||||
}
|
||||
}
|
||||
return acc
|
||||
}, [])
|
||||
|
||||
let accumulatedZapAmount = 0
|
||||
let hasZapped = false
|
||||
|
||||
const eventIds = new Set<string>() // To keep track of event IDs and avoid duplicates
|
||||
|
||||
const filters: Filter[] = [
|
||||
{
|
||||
kinds: [kinds.Zap],
|
||||
'#e': [eTag]
|
||||
}
|
||||
]
|
||||
|
||||
if (aTag) {
|
||||
filters.push({
|
||||
kinds: [kinds.Zap],
|
||||
'#a': [aTag]
|
||||
})
|
||||
}
|
||||
|
||||
// Create a promise for each relay subscription
|
||||
const subPromises = relays.map((relay) => {
|
||||
return new Promise<void>((resolve) => {
|
||||
// Subscribe to the relay with the specified filter
|
||||
const sub = relay.subscribe(filters, {
|
||||
// Handle incoming events
|
||||
onevent: (e) => {
|
||||
// Add the event to the array if it's not a duplicate
|
||||
if (!eventIds.has(e.id)) {
|
||||
eventIds.add(e.id) // Record the event ID
|
||||
|
||||
const zapRequestStr = e.tags.find(
|
||||
(t) => t[0] === 'description'
|
||||
)?.[1]
|
||||
if (!zapRequestStr) return
|
||||
|
||||
const error = nip57.validateZapRequest(zapRequestStr)
|
||||
if (error) return
|
||||
|
||||
let zapRequest: Event | null = null
|
||||
|
||||
try {
|
||||
zapRequest = JSON.parse(zapRequestStr)
|
||||
} catch (error) {
|
||||
log(
|
||||
true,
|
||||
LogType.Error,
|
||||
'Error occurred in parsing zap request',
|
||||
error
|
||||
)
|
||||
}
|
||||
|
||||
if (!zapRequest) return
|
||||
|
||||
const amount = extractZapAmount(zapRequest)
|
||||
accumulatedZapAmount += amount
|
||||
|
||||
if (amount > 0) {
|
||||
if (!hasZapped) {
|
||||
hasZapped = zapRequest.pubkey === currentLoggedInUser
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Handle the End-Of-Stream (EOSE) message
|
||||
oneose: () => {
|
||||
sub.close() // Close the subscription
|
||||
resolve() // Resolve the promise when EOSE is received
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Wait for all subscriptions to complete
|
||||
await Promise.allSettled(subPromises)
|
||||
|
||||
return {
|
||||
accumulatedZapAmount,
|
||||
hasZapped
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,23 +9,5 @@ export const useNDKContext = () => {
|
||||
'NDKContext should not be used in out component tree hierarchy'
|
||||
)
|
||||
|
||||
const {
|
||||
ndk,
|
||||
fetchEvents,
|
||||
fetchEvent,
|
||||
fetchEventsFromUserRelays,
|
||||
fetchEventFromUserRelays,
|
||||
fetchMods,
|
||||
findMetadata
|
||||
} = ndkContext
|
||||
|
||||
return {
|
||||
ndk,
|
||||
fetchEvents,
|
||||
fetchEvent,
|
||||
fetchEventsFromUserRelays,
|
||||
fetchEventFromUserRelays,
|
||||
fetchMods,
|
||||
findMetadata
|
||||
}
|
||||
return { ...ndkContext }
|
||||
}
|
||||
|
@ -496,20 +496,19 @@ const Reactions = (props: Event) => {
|
||||
|
||||
const Zap = (props: Event) => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [totalZappedAmount, setTotalZappedAmount] = useState(0)
|
||||
const [hasZapped, setHasZapped] = useState(false)
|
||||
|
||||
const userState = useAppSelector((state) => state.user)
|
||||
|
||||
const [totalZappedAmount, setTotalZappedAmount] = useState(0)
|
||||
const { getTotalZapAmount } = useNDKContext()
|
||||
|
||||
useDidMount(() => {
|
||||
RelayController.getInstance()
|
||||
.getTotalZapAmount(
|
||||
props.pubkey,
|
||||
props.id,
|
||||
undefined,
|
||||
userState.user?.pubkey as string
|
||||
)
|
||||
getTotalZapAmount(
|
||||
props.pubkey,
|
||||
props.id,
|
||||
undefined,
|
||||
userState.user?.pubkey as string
|
||||
)
|
||||
.then((res) => {
|
||||
setTotalZappedAmount(res.accumulatedZapAmount)
|
||||
setHasZapped(res.hasZapped)
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { ZapSplit } from 'components/Zap'
|
||||
import { RelayController } from 'controllers'
|
||||
import { useAppSelector, useDidMount } from 'hooks'
|
||||
import { useAppSelector, useDidMount, useNDKContext } from 'hooks'
|
||||
import { useState } from 'react'
|
||||
import { toast } from 'react-toastify'
|
||||
import { ModDetails } from 'types'
|
||||
@ -12,20 +11,19 @@ type ZapProps = {
|
||||
|
||||
export const Zap = ({ modDetails }: ZapProps) => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [totalZappedAmount, setTotalZappedAmount] = useState(0)
|
||||
const [hasZapped, setHasZapped] = useState(false)
|
||||
|
||||
const userState = useAppSelector((state) => state.user)
|
||||
|
||||
const [totalZappedAmount, setTotalZappedAmount] = useState(0)
|
||||
const { getTotalZapAmount } = useNDKContext()
|
||||
|
||||
useDidMount(() => {
|
||||
RelayController.getInstance()
|
||||
.getTotalZapAmount(
|
||||
modDetails.author,
|
||||
modDetails.id,
|
||||
modDetails.aTag,
|
||||
userState.user?.pubkey as string
|
||||
)
|
||||
getTotalZapAmount(
|
||||
modDetails.author,
|
||||
modDetails.id,
|
||||
modDetails.aTag,
|
||||
userState.user?.pubkey as string
|
||||
)
|
||||
.then((res) => {
|
||||
setTotalZappedAmount(res.accumulatedZapAmount)
|
||||
setHasZapped(res.hasZapped)
|
||||
|
Loading…
Reference in New Issue
Block a user