From 5c24c5bde03a7dc8c69ddbf2a4dc0bb0f97ddff6 Mon Sep 17 00:00:00 2001 From: daniyal Date: Fri, 20 Dec 2024 21:58:45 +0500 Subject: [PATCH] chore(refactor): use getNDKRelayList function from NDKContext instead of findRelayListMetadata function of metadata controller --- src/contexts/NDKContext.tsx | 18 ++++++ src/controllers/MetadataController.ts | 56 ----------------- src/controllers/index.ts | 2 - src/layouts/Main.tsx | 8 +-- src/pages/create/index.tsx | 18 +++--- src/pages/sign/index.tsx | 4 +- src/pages/verify/index.tsx | 5 +- src/utils/nostr.ts | 87 +++++++++------------------ 8 files changed, 64 insertions(+), 134 deletions(-) delete mode 100644 src/controllers/MetadataController.ts diff --git a/src/contexts/NDKContext.tsx b/src/contexts/NDKContext.tsx index c44252b..efc47e9 100644 --- a/src/contexts/NDKContext.tsx +++ b/src/contexts/NDKContext.tsx @@ -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 + getNDKRelayList: (pubkey: Hexpubkey) => Promise publish: (event: NDKEvent, explicitRelayUrls?: string[]) => Promise } @@ -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 }} > diff --git a/src/controllers/MetadataController.ts b/src/controllers/MetadataController.ts deleted file mode 100644 index 1f7cf8e..0000000 --- a/src/controllers/MetadataController.ts +++ /dev/null @@ -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 => { - 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 - } - } -} diff --git a/src/controllers/index.ts b/src/controllers/index.ts index dc1f76f..63c9671 100644 --- a/src/controllers/index.ts +++ b/src/controllers/index.ts @@ -1,4 +1,2 @@ -export * from './AuthController' -export * from './MetadataController' export * from './NostrController' export * from './RelayController' diff --git a/src/layouts/Main.tsx b/src/layouts/Main.tsx index b373bf5..4409224 100644 --- a/src/layouts/Main.tsx +++ b/src/layouts/Main.tsx @@ -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)) diff --git a/src/pages/create/index.tsx b/src/pages/create/index.tsx index e861545..b2d6f5d 100644 --- a/src/pages/create/index.tsx +++ b/src/pages/create/index.tsx @@ -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() @@ -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 => { diff --git a/src/pages/sign/index.tsx b/src/pages/sign/index.tsx index f30ecdd..f874122 100644 --- a/src/pages/sign/index.tsx +++ b/src/pages/sign/index.tsx @@ -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(() => { diff --git a/src/pages/verify/index.tsx b/src/pages/verify/index.tsx index 515a257..282390e 100644 --- a/src/pages/verify/index.tsx +++ b/src/pages/verify/index.tsx @@ -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) diff --git a/src/utils/nostr.ts b/src/utils/nostr.ts index 3775837..ed82513 100644 --- a/src/utils/nostr.ts +++ b/src/utils/nostr.ts @@ -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 => { +export const getUsersAppData = async ( + getNDKRelayList: (pubkey: Hexpubkey) => Promise +): Promise => { // Initialize an array to hold relay URLs const relays: string[] = [] @@ -344,27 +342,17 @@ export const getUsersAppData = async (): Promise => { // 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 +) => { + 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 +) => { // 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