chore(refactor): use getNDKRelayList function from NDKContext instead of findRelayListMetadata function of metadata controller

This commit is contained in:
daniyal 2024-12-20 21:58:45 +05:00
parent 458de18f12
commit 5c24c5bde0
8 changed files with 64 additions and 134 deletions

View File

@ -1,7 +1,9 @@
import NDK, {
getRelayListForUser,
Hexpubkey,
NDKEvent,
NDKFilter,
NDKRelayList,
NDKRelaySet,
NDKSubscriptionCacheUsage,
NDKSubscriptionOptions,
@ -19,6 +21,7 @@ import {
DEFAULT_LOOK_UP_RELAY_LIST,
hexToNpub,
orderEventsChronologically,
SIGIT_RELAY,
timeout
} from '../utils'
@ -41,6 +44,7 @@ export interface NDKContextType {
opts?: NDKSubscriptionOptions,
storeProfileEvent?: boolean
) => Promise<NDKUserProfile | null>
getNDKRelayList: (pubkey: Hexpubkey) => Promise<NDKRelayList>
publish: (event: NDKEvent, explicitRelayUrls?: string[]) => Promise<string[]>
}
@ -214,6 +218,19 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
)
}
const getNDKRelayList = async (pubkey: Hexpubkey) => {
const ndkRelayList = await Promise.race([
getRelayListForUser(pubkey, ndk),
timeout(10000)
]).catch(() => {
const relayList = new NDKRelayList(ndk)
relayList.bothRelayUrls = [SIGIT_RELAY]
return relayList
})
return ndkRelayList
}
const publish = async (
event: NDKEvent,
explicitRelayUrls?: string[]
@ -247,6 +264,7 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
fetchEventsFromUserRelays,
fetchEventFromUserRelays,
findMetadata,
getNDKRelayList,
publish
}}
>

View File

@ -1,56 +0,0 @@
import { Event } from 'nostr-tools'
import { EventEmitter } from 'tseep'
import { ProfileMetadata, RelaySet } from '../types'
import {
findRelayListAndUpdateCache,
findRelayListInCache,
getDefaultRelaySet,
getUserRelaySet
} from '../utils'
import { DEFAULT_LOOK_UP_RELAY_LIST } from '../utils/const'
export class MetadataController extends EventEmitter {
private static instance: MetadataController
constructor() {
super()
}
public static getInstance(): MetadataController {
if (!MetadataController.instance) {
MetadataController.instance = new MetadataController()
}
return MetadataController.instance
}
/**
* Based on the hexKey of the current user, this method attempts to retrieve a relay set.
* @func findRelayListInCache first checks if there is already an up-to-date
* relay list available in cache; if not -
* @func findRelayListAndUpdateCache checks if the relevant relay event is available from
* the purple pages relay;
* @func findRelayListAndUpdateCache will run again if the previous two calls return null and
* check if the relevant relay event can be obtained from 'most popular relays'
* If relay event is found, it will be saved in cache for future use
* @param hexKey of the current user
* @return RelaySet which will contain either relays extracted from the user Relay Event
* or a fallback RelaySet with Sigit's Relay
*/
public findRelayListMetadata = async (hexKey: string): Promise<RelaySet> => {
const relayEvent =
(await findRelayListInCache(hexKey)) ||
(await findRelayListAndUpdateCache(DEFAULT_LOOK_UP_RELAY_LIST, hexKey))
return relayEvent ? getUserRelaySet(relayEvent.tags) : getDefaultRelaySet()
}
public extractProfileMetadataContent = (event: Event) => {
try {
if (!event.content) return {}
return JSON.parse(event.content) as ProfileMetadata
} catch (error) {
console.log('error in parsing metadata event content :>> ', error)
return null
}
}
}

View File

@ -1,4 +1,2 @@
export * from './AuthController'
export * from './MetadataController'
export * from './NostrController'
export * from './RelayController'

View File

@ -44,7 +44,7 @@ export const MainLayout = () => {
const navigate = useNavigate()
const dispatch = useAppDispatch()
const logout = useLogout()
const { findMetadata } = useNDKContext()
const { findMetadata, getNDKRelayList } = useNDKContext()
const { authAndGetMetadataAndRelaysMap } = useAuth()
const [isLoading, setIsLoading] = useState(true)
@ -191,13 +191,13 @@ export const MainLayout = () => {
if (pubkey && !hasSubscribed.current) {
// Call `subscribeForSigits` only if it hasn't been called before
// #193 disabled websocket subscribtion, until #194 is done
subscribeForSigits(pubkey)
subscribeForSigits(pubkey, getNDKRelayList)
// Mark `subscribeForSigits` as called
hasSubscribed.current = true
}
}
}, [authState, isLoggedIn, usersAppData])
}, [authState, isLoggedIn, usersAppData, getNDKRelayList])
/**
* When authState change user logged in / or app reloaded
@ -214,7 +214,7 @@ export const MainLayout = () => {
setIsLoading(true)
setLoadingSpinnerDesc(`Loading SIGit history...`)
getUsersAppData()
getUsersAppData(getNDKRelayList)
.then((appData) => {
if (appData) {
dispatch(updateUserAppData(appData))

View File

@ -20,11 +20,7 @@ import { useLocation, useNavigate } from 'react-router-dom'
import { toast } from 'react-toastify'
import { LoadingSpinner } from '../../components/LoadingSpinner'
import { UserAvatar } from '../../components/UserAvatar'
import {
MetadataController,
NostrController,
RelayController
} from '../../controllers'
import { NostrController, RelayController } from '../../controllers'
import { appPrivateRoutes } from '../../routes'
import {
CreateSignatureEventContent,
@ -87,7 +83,7 @@ type FoundUser = Event & { npub: string }
export const CreatePage = () => {
const navigate = useNavigate()
const location = useLocation()
const { findMetadata } = useNDKContext()
const { findMetadata, getNDKRelayList } = useNDKContext()
const { uploadedFiles } = location.state || {}
const [currentFile, setCurrentFile] = useState<File>()
@ -160,18 +156,18 @@ export const CreatePage = () => {
setSearchUsersLoading(true)
const relayController = RelayController.getInstance()
const metadataController = MetadataController.getInstance()
const relaySet = await metadataController.findRelayListMetadata(usersPubkey)
const searchTerm = searchString.trim()
const ndkRelayList = await getNDKRelayList(usersPubkey)
relayController
.fetchEvents(
{
kinds: [0],
search: searchTerm
},
[...relaySet.write]
[...ndkRelayList.writeRelayUrls]
)
.then((events) => {
console.log('events', events)
@ -777,7 +773,9 @@ export const CreatePage = () => {
: viewers.map((viewer) => viewer.pubkey)
).filter((receiver) => receiver !== usersPubkey)
return receivers.map((receiver) => sendNotification(receiver, meta))
return receivers.map((receiver) =>
sendNotification(receiver, meta, getNDKRelayList)
)
}
const extractNostrId = (stringifiedEvent: string): string => {

View File

@ -56,6 +56,7 @@ import {
import { ARRAY_BUFFER, DEFLATE } from '../../utils/const.ts'
import { generateTimestamp } from '../../utils/opentimestamps.ts'
import { MARK_TYPE_CONFIG } from '../../components/MarkTypeStrategy/MarkStrategy.tsx'
import { useNDKContext } from '../../hooks/useNDKContext.ts'
enum SignedStatus {
Fully_Signed,
@ -67,6 +68,7 @@ export const SignPage = () => {
const navigate = useNavigate()
const location = useLocation()
const params = useParams()
const { getNDKRelayList } = useNDKContext()
const usersAppData = useAppSelector((state) => state.userAppData)
@ -781,7 +783,7 @@ export const SignPage = () => {
setLoadingSpinnerDesc('Sending notifications')
const users = Array.from(userSet)
const promises = users.map((user) =>
sendNotification(npubToHex(user)!, meta)
sendNotification(npubToHex(user)!, meta, getNDKRelayList)
)
await Promise.all(promises)
.then(() => {

View File

@ -29,7 +29,7 @@ import styles from './style.module.scss'
import { useLocation, useParams } from 'react-router-dom'
import axios from 'axios'
import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf.ts'
import { useAppSelector } from '../../hooks'
import { useAppSelector, useNDKContext } from '../../hooks'
import { getLastSignersSig } from '../../utils/sign.ts'
import { saveAs } from 'file-saver'
import { Container } from '../../components/Container'
@ -166,6 +166,7 @@ const SlimPdfView = ({
export const VerifyPage = () => {
const location = useLocation()
const params = useParams()
const { getNDKRelayList } = useNDKContext()
const usersAppData = useAppSelector((state) => state.userAppData)
const usersPubkey = useAppSelector((state) => state.auth.usersPubkey)
@ -364,7 +365,7 @@ export const VerifyPage = () => {
const users = Array.from(userSet)
const promises = users.map((user) =>
sendNotification(npubToHex(user)!, updatedMeta)
sendNotification(npubToHex(user)!, updatedMeta, getNDKRelayList)
)
await Promise.all(promises)

View File

@ -18,11 +18,7 @@ import {
} from 'nostr-tools'
import { toast } from 'react-toastify'
import { NIP05_REGEX } from '../constants'
import {
MetadataController,
NostrController,
relayController
} from '../controllers'
import { NostrController, relayController } from '../controllers'
import {
updateProcessedGiftWraps,
updateUserAppData as updateUserAppDataAction
@ -35,7 +31,7 @@ import { parseJson, removeLeadingSlash } from './string'
import { timeout } from './utils'
import { getHash } from './hash'
import { SIGIT_BLOSSOM } from './const.ts'
import { NDKEvent } from '@nostr-dev-kit/ndk'
import { Hexpubkey, NDKEvent, NDKRelayList } from '@nostr-dev-kit/ndk'
/**
* Generates a `d` tag for userAppData
@ -334,7 +330,9 @@ export const createWrap = (unsignedEvent: UnsignedEvent, receiver: string) => {
*
* @returns The user application data or null if an error occurs or no data is found.
*/
export const getUsersAppData = async (): Promise<UserAppData | null> => {
export const getUsersAppData = async (
getNDKRelayList: (pubkey: Hexpubkey) => Promise<NDKRelayList>
): Promise<UserAppData | null> => {
// Initialize an array to hold relay URLs
const relays: string[] = []
@ -344,27 +342,17 @@ export const getUsersAppData = async (): Promise<UserAppData | null> => {
// Check if relayMap is undefined in the Redux store
if (!relayMap) {
// If relayMap is not present, fetch relay list metadata
const metadataController = MetadataController.getInstance()
const relaySet = await metadataController
.findRelayListMetadata(usersPubkey)
.catch((err) => {
// Log error and return null if fetching metadata fails
console.log(
`An error occurred while finding relay list metadata for ${hexToNpub(usersPubkey)}`,
err
)
return null
})
// If relayMap is not present, get relay list using NDKContext
// Return null if metadata retrieval failed
if (!relaySet) return null
const ndkRelayList = await getNDKRelayList(usersPubkey)
// Ensure that the relay list is not empty
if (relaySet.write.length === 0) return null
if (ndkRelayList.writeRelayUrls.length === 0) return null
// Add write relays to the relays array
relays.push(...relaySet.write)
relays.push(...ndkRelayList.writeRelayUrls)
// // Ensure that the relay list is not empty
} else {
// If relayMap exists, filter and add write relays from the stored map
const writeRelays = Object.keys(relayMap).filter(
@ -816,25 +804,14 @@ const getUserAppDataFromBlossom = async (url: string, privateKey: string) => {
* @param pubkey - The public key to subscribe to.
* @returns A promise that resolves when the subscription is successful.
*/
export const subscribeForSigits = async (pubkey: string) => {
// Instantiate the MetadataController to retrieve relay list metadata
const metadataController = MetadataController.getInstance()
const relaySet = await metadataController
.findRelayListMetadata(pubkey)
.catch((err) => {
// Log an error if retrieving relay list metadata fails
console.log(
`An error occurred while finding relay list metadata for ${hexToNpub(pubkey)}`,
err
)
return null
})
// Return if metadata retrieval failed
if (!relaySet) return
export const subscribeForSigits = async (
pubkey: string,
getNDKRelayList: (pubkey: Hexpubkey) => Promise<NDKRelayList>
) => {
const ndkRelayList = await getNDKRelayList(pubkey)
// Ensure relay list is not empty
if (relaySet.read.length === 0) return
if (ndkRelayList.readRelayUrls.length === 0) return
// Define the filter for the subscription
const filter: Filter = {
@ -843,7 +820,9 @@ export const subscribeForSigits = async (pubkey: string) => {
}
// Process the received event synchronously
const events = await relayController.fetchEvents(filter, relaySet.read)
const events = await relayController.fetchEvents(filter, [
...ndkRelayList.readRelayUrls
])
for (const e of events) {
await processReceivedEvent(e)
}
@ -908,7 +887,11 @@ const processReceivedEvent = async (event: Event, difficulty: number = 5) => {
* @param receiver - The recipient's public key.
* @param meta - Metadata associated with the notification.
*/
export const sendNotification = async (receiver: string, meta: Meta) => {
export const sendNotification = async (
receiver: string,
meta: Meta,
getNDKRelayList: (pubkey: Hexpubkey) => Promise<NDKRelayList>
) => {
// Retrieve the user's public key from the state
const usersPubkey = store.getState().auth.usersPubkey!
@ -924,28 +907,14 @@ export const sendNotification = async (receiver: string, meta: Meta) => {
// Wrap the unsigned event with the receiver's information
const wrappedEvent = createWrap(unsignedEvent, receiver)
// Instantiate the MetadataController to retrieve relay list metadata
const metadataController = MetadataController.getInstance()
const relaySet = await metadataController
.findRelayListMetadata(receiver)
.catch((err) => {
// Log an error if retrieving relay list metadata fails
console.log(
`An error occurred while finding relay list metadata for ${hexToNpub(receiver)}`,
err
)
return null
})
// Return if metadata retrieval failed
if (!relaySet) return
const ndkRelayList = await getNDKRelayList(receiver)
// Ensure relay list is not empty
if (relaySet.read.length === 0) return
if (ndkRelayList.readRelayUrls.length === 0) return
// Publish the notification event to the recipient's read relays
await Promise.race([
relayController.publish(wrappedEvent, relaySet.read),
relayController.publish(wrappedEvent, [...ndkRelayList.readRelayUrls]),
timeout(40 * 1000)
]).catch((err) => {
// Log an error if publishing the notification event fails