fix: add admin relays to ndk explicit relays asyncronously
This commit is contained in:
parent
610801a674
commit
59f4fd6b29
@ -33,12 +33,8 @@ type FetchModsOptions = {
|
|||||||
interface NDKContextType {
|
interface NDKContextType {
|
||||||
ndk: NDK
|
ndk: NDK
|
||||||
fetchMods: (opts: FetchModsOptions) => Promise<ModDetails[]>
|
fetchMods: (opts: FetchModsOptions) => Promise<ModDetails[]>
|
||||||
fetchEvents: (filter: NDKFilter, relayUrls?: string[]) => Promise<NDKEvent[]>
|
fetchEvents: (filter: NDKFilter) => Promise<NDKEvent[]>
|
||||||
fetchEvent: (
|
fetchEvent: (filter: NDKFilter) => Promise<NDKEvent | null>
|
||||||
filter: NDKFilter,
|
|
||||||
relayUrls?: string[]
|
|
||||||
) => Promise<NDKEvent | null>
|
|
||||||
|
|
||||||
fetchEventsFromUserRelays: (
|
fetchEventsFromUserRelays: (
|
||||||
filter: NDKFilter,
|
filter: NDKFilter,
|
||||||
hexKey: string,
|
hexKey: string,
|
||||||
@ -72,6 +68,31 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const addAdminRelays = async (ndk: NDK) => {
|
||||||
|
const adminNpubs = import.meta.env.VITE_ADMIN_NPUBS.split(',')
|
||||||
|
adminNpubs.forEach((npub) => {
|
||||||
|
const hexKey = npubToHex(npub)
|
||||||
|
if (hexKey) {
|
||||||
|
getRelayListForUser(hexKey, ndk)
|
||||||
|
.then((ndkRelayList) => {
|
||||||
|
if (ndkRelayList) {
|
||||||
|
ndkRelayList.bothRelayUrls.forEach((url) =>
|
||||||
|
ndk.addExplicitRelay(url)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
log(
|
||||||
|
true,
|
||||||
|
LogType.Error,
|
||||||
|
`❌ Error occurred in getting the instance of NDKRelayList for npub: ${npub}`,
|
||||||
|
err
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const ndk = useMemo(() => {
|
const ndk = useMemo(() => {
|
||||||
localStorage.setItem('debug', '*')
|
localStorage.setItem('debug', '*')
|
||||||
const dexieAdapter = new NDKCacheAdapterDexie({ dbName: 'degmod-db' })
|
const dexieAdapter = new NDKCacheAdapterDexie({ dbName: 'degmod-db' })
|
||||||
@ -88,6 +109,7 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
],
|
],
|
||||||
cacheAdapter: dexieAdapter
|
cacheAdapter: dexieAdapter
|
||||||
})
|
})
|
||||||
|
addAdminRelays(ndk)
|
||||||
|
|
||||||
ndk.connect()
|
ndk.connect()
|
||||||
|
|
||||||
@ -110,33 +132,6 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
since,
|
since,
|
||||||
limit
|
limit
|
||||||
}: FetchModsOptions): Promise<ModDetails[]> => {
|
}: FetchModsOptions): Promise<ModDetails[]> => {
|
||||||
const relays = new Set<string>()
|
|
||||||
relays.add(import.meta.env.VITE_APP_RELAY)
|
|
||||||
|
|
||||||
const adminNpubs = import.meta.env.VITE_ADMIN_NPUBS.split(',')
|
|
||||||
|
|
||||||
const promises = adminNpubs.map((npub) => {
|
|
||||||
const hexKey = npubToHex(npub)
|
|
||||||
if (!hexKey) return null
|
|
||||||
|
|
||||||
return getRelayListForUser(hexKey, ndk)
|
|
||||||
.then((ndkRelayList) => {
|
|
||||||
if (ndkRelayList) {
|
|
||||||
ndkRelayList.writeRelayUrls.forEach((url) => relays.add(url))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
log(
|
|
||||||
true,
|
|
||||||
LogType.Error,
|
|
||||||
`❌ Error occurred in getting the instance of NDKRelayList for npub: ${npub}`,
|
|
||||||
err
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
await Promise.allSettled(promises)
|
|
||||||
|
|
||||||
// Define the filter criteria for fetching mods
|
// Define the filter criteria for fetching mods
|
||||||
const filter: NDKFilter = {
|
const filter: NDKFilter = {
|
||||||
kinds: [NDKKind.Classified], // Specify the kind of events to fetch
|
kinds: [NDKKind.Classified], // Specify the kind of events to fetch
|
||||||
@ -152,11 +147,10 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ndk
|
return ndk
|
||||||
.fetchEvents(
|
.fetchEvents(filter, {
|
||||||
filter,
|
closeOnEose: true,
|
||||||
{ closeOnEose: true, cacheUsage: NDKSubscriptionCacheUsage.PARALLEL },
|
cacheUsage: NDKSubscriptionCacheUsage.PARALLEL
|
||||||
NDKRelaySet.fromRelayUrls(Array.from(relays), ndk, true)
|
})
|
||||||
)
|
|
||||||
.then((ndkEventSet) => {
|
.then((ndkEventSet) => {
|
||||||
const ndkEvents = Array.from(ndkEventSet)
|
const ndkEvents = Array.from(ndkEventSet)
|
||||||
orderEventsChronologically(ndkEvents)
|
orderEventsChronologically(ndkEvents)
|
||||||
@ -179,56 +173,17 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously retrieves multiple event from a set of relays based on a provided filter.
|
* Asynchronously retrieves multiple event based on a provided filter.
|
||||||
* If no relays are specified, it defaults to using connected relays.
|
|
||||||
*
|
*
|
||||||
* @param filter - The filter criteria to find the event.
|
* @param filter - The filter criteria to find the event.
|
||||||
* @param relays - An optional array of relay URLs to search for the event.
|
|
||||||
* @returns Returns a promise that resolves to the found event or null if not found.
|
* @returns Returns a promise that resolves to the found event or null if not found.
|
||||||
*/
|
*/
|
||||||
const fetchEvents = async (
|
const fetchEvents = async (filter: NDKFilter): Promise<NDKEvent[]> => {
|
||||||
filter: NDKFilter,
|
|
||||||
relayUrls: string[] = []
|
|
||||||
): Promise<NDKEvent[]> => {
|
|
||||||
const relays = new Set<string>()
|
|
||||||
|
|
||||||
// add all the relays passed to relay set
|
|
||||||
relayUrls.forEach((relayUrl) => {
|
|
||||||
relays.add(relayUrl)
|
|
||||||
})
|
|
||||||
|
|
||||||
relays.add(import.meta.env.VITE_APP_RELAY)
|
|
||||||
|
|
||||||
const adminNpubs = import.meta.env.VITE_ADMIN_NPUBS.split(',')
|
|
||||||
|
|
||||||
const promises = adminNpubs.map((npub) => {
|
|
||||||
const hexKey = npubToHex(npub)
|
|
||||||
if (!hexKey) return null
|
|
||||||
|
|
||||||
return getRelayListForUser(hexKey, ndk)
|
|
||||||
.then((ndkRelayList) => {
|
|
||||||
if (ndkRelayList) {
|
|
||||||
ndkRelayList.writeRelayUrls.forEach((url) => relays.add(url))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
log(
|
|
||||||
true,
|
|
||||||
LogType.Error,
|
|
||||||
`❌ Error occurred in getting the instance of NDKRelayList for npub: ${npub}`,
|
|
||||||
err
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
await Promise.allSettled(promises)
|
|
||||||
|
|
||||||
return ndk
|
return ndk
|
||||||
.fetchEvents(
|
.fetchEvents(filter, {
|
||||||
filter,
|
closeOnEose: true,
|
||||||
{ closeOnEose: true, cacheUsage: NDKSubscriptionCacheUsage.PARALLEL },
|
cacheUsage: NDKSubscriptionCacheUsage.PARALLEL
|
||||||
NDKRelaySet.fromRelayUrls(Array.from(relays), ndk, true)
|
})
|
||||||
)
|
|
||||||
.then((ndkEventSet) => {
|
.then((ndkEventSet) => {
|
||||||
const ndkEvents = Array.from(ndkEventSet)
|
const ndkEvents = Array.from(ndkEventSet)
|
||||||
return orderEventsChronologically(ndkEvents)
|
return orderEventsChronologically(ndkEvents)
|
||||||
@ -242,15 +197,13 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously retrieves an event from a set of relays based on a provided filter.
|
* Asynchronously retrieves an event based on a provided filter.
|
||||||
* If no relays are specified, it defaults to using connected relays.
|
|
||||||
*
|
*
|
||||||
* @param filter - The filter criteria to find the event.
|
* @param filter - The filter criteria to find the event.
|
||||||
* @param relaysUrls - An optional array of relay URLs to search for the event.
|
|
||||||
* @returns Returns a promise that resolves to the found event or null if not found.
|
* @returns Returns a promise that resolves to the found event or null if not found.
|
||||||
*/
|
*/
|
||||||
const fetchEvent = async (filter: NDKFilter, relayUrls: string[] = []) => {
|
const fetchEvent = async (filter: NDKFilter) => {
|
||||||
const events = await fetchEvents(filter, relayUrls)
|
const events = await fetchEvents(filter)
|
||||||
if (events.length === 0) return null
|
if (events.length === 0) return null
|
||||||
return events[0]
|
return events[0]
|
||||||
}
|
}
|
||||||
@ -285,8 +238,22 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
return [] as string[]
|
return [] as string[]
|
||||||
})
|
})
|
||||||
|
|
||||||
// Fetch the event from the user's relays using the provided filter and relay URLs
|
return ndk
|
||||||
return fetchEvents(filter, relayUrls)
|
.fetchEvents(
|
||||||
|
filter,
|
||||||
|
{ closeOnEose: true, cacheUsage: NDKSubscriptionCacheUsage.PARALLEL },
|
||||||
|
NDKRelaySet.fromRelayUrls(relayUrls, ndk, true)
|
||||||
|
)
|
||||||
|
.then((ndkEventSet) => {
|
||||||
|
const ndkEvents = Array.from(ndkEventSet)
|
||||||
|
return orderEventsChronologically(ndkEvents)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
// Log the error and show a notification if fetching fails
|
||||||
|
log(true, LogType.Error, 'An error occurred in fetching events', err)
|
||||||
|
toast.error('An error occurred in fetching events') // Show error notification
|
||||||
|
return [] // Return an empty array in case of an error
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -372,75 +372,6 @@ export class RelayController {
|
|||||||
return publishedOnRelays
|
return publishedOnRelays
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Subscribes to events from multiple relays.
|
|
||||||
*
|
|
||||||
* This method connects to the specified relay URLs and subscribes to events
|
|
||||||
* using the provided filter. It handles incoming events through the given
|
|
||||||
* `eventHandler` callback and manages the subscription lifecycle.
|
|
||||||
*
|
|
||||||
* @param filter - The filter criteria to apply when subscribing to events.
|
|
||||||
* @param relayUrls - An optional array of relay URLs to connect to. The default relay URL (`APP_RELAY`) is added automatically.
|
|
||||||
* @param eventHandler - A callback function to handle incoming events. It receives an `Event` object.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
subscribeForEvents = async (
|
|
||||||
filter: Filter,
|
|
||||||
relayUrls: string[] = [],
|
|
||||||
eventHandler: (event: Event) => void
|
|
||||||
) => {
|
|
||||||
const appRelay = import.meta.env.VITE_APP_RELAY
|
|
||||||
if (!relayUrls.includes(appRelay)) {
|
|
||||||
/**
|
|
||||||
* NOTE: To avoid side-effects on external relayUrls array passed as argument
|
|
||||||
* re-assigned relayUrls with added sigit relay instead of just appending to same array
|
|
||||||
*/
|
|
||||||
relayUrls = [...relayUrls, appRelay] // Add app relay to relays array if not exists already
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
// Check if any relays are connected
|
|
||||||
if (relays.length === 0) {
|
|
||||||
throw new Error('No relay is connected to fetch events!')
|
|
||||||
}
|
|
||||||
|
|
||||||
const processedEvents: string[] = [] // To keep track of processed events
|
|
||||||
|
|
||||||
// Create a promise for each relay subscription
|
|
||||||
const subscriptions = relays.map((relay) =>
|
|
||||||
relay.subscribe([filter], {
|
|
||||||
// Handle incoming events
|
|
||||||
onevent: (e) => {
|
|
||||||
// Process event only if it hasn't been processed before
|
|
||||||
if (!processedEvents.includes(e.id)) {
|
|
||||||
processedEvents.push(e.id)
|
|
||||||
eventHandler(e) // Call the event handler with the event
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
return subscriptions
|
|
||||||
}
|
|
||||||
|
|
||||||
getTotalZapAmount = async (
|
getTotalZapAmount = async (
|
||||||
user: string,
|
user: string,
|
||||||
eTag: string,
|
eTag: string,
|
||||||
|
@ -392,7 +392,7 @@ const UsersResult = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
setIsFetching(true)
|
setIsFetching(true)
|
||||||
fetchEvents(filter, ['wss://purplepag.es', 'wss://user.kindpag.es'])
|
fetchEvents(filter)
|
||||||
.then((events) => {
|
.then((events) => {
|
||||||
const results = events.map((event) => {
|
const results = events.map((event) => {
|
||||||
const ndkEvent = new NDKEvent(undefined, event)
|
const ndkEvent = new NDKEvent(undefined, event)
|
||||||
|
Loading…
Reference in New Issue
Block a user