diff --git a/utils/nostr/fetch-service.ts b/utils/nostr/fetch-service.ts index 908f355d..d6fe44af 100644 --- a/utils/nostr/fetch-service.ts +++ b/utils/nostr/fetch-service.ts @@ -23,6 +23,13 @@ import { NostrManager } from "@/utils/nostr/nostr-manager"; import { NostrSigner } from "@/utils/nostr/signers/nostr-signer"; import { cacheEventsToDatabase } from "@/utils/db/db-client"; +interface NipProfile { + pubkey: string; + created_at: number; + content: { nip05?: string; [key: string]: any }; + nip05Verified: boolean; +} + function getUniqueProofs(proofs: Proof[]): Proof[] { const seenSecrets = new Set(); return proofs.filter((proof) => { @@ -351,17 +358,48 @@ export const fetchShopProfile = async ( }); }; +async function verifyProfilesNip05( + profileMap: Map, + concurrency = 8 +): Promise { + const profiles = Array.from(profileMap.values()).filter( + (profile): profile is NipProfile => + profile !== null && !!profile?.content?.nip05 + ); + + for (let i = 0; i < profiles.length; i += concurrency) { + await Promise.all( + profiles.slice(i, i + concurrency).map(async (profile) => { + const nip05 = profile.content.nip05!; + const pubkey: string = profile.pubkey; + const host = nip05.includes("@") ? nip05.split("@")[1] : undefined; + try { + profile.nip05Verified = await verifyNip05Identifier(nip05, pubkey); + } catch (error) { + profile.nip05Verified = false; + console.error("Failed to verify NIP-05 identifier", { + host, + pubkey, + nip05, + error, + }); + } + }) + ); + } +} + export const fetchProfile = async ( nostr: NostrManager, relays: string[], pubkeyProfilesToFetch: string[], editProfileContext: ( - productEvents: Map, + profileMap: Map, isLoading: boolean ) => void, existingProfileMap: Map = new Map() ): Promise<{ - profileMap: Map; + profileMap: Map; }> => { return new Promise(async function (resolve, reject) { try { @@ -385,7 +423,7 @@ export const fetchProfile = async ( } }; - const dbProfileMap = new Map(); + const dbProfileMap = new Map(); try { const response = await fetch("/api/db/fetch-profiles"); if (response.ok) { @@ -407,18 +445,12 @@ export const fetchProfile = async ( for (const [pubkey, event] of latestDbEvents.entries()) { try { const content = JSON.parse(event.content); - const profile = { + const profile: NipProfile = { pubkey: event.pubkey, created_at: event.created_at, - content: content, + content, nip05Verified: false, }; - if (content.nip05) { - profile.nip05Verified = await verifyNip05Identifier( - content.nip05, - event.pubkey - ); - } dbProfileMap.set(pubkey, profile); updateProfileIfNewer(profile); } catch (error) { @@ -429,7 +461,9 @@ export const fetchProfile = async ( } } - if (mergedProfileMap.size > 0) { + if (dbProfileMap.size > 0) { + editProfileContext(new Map(mergedProfileMap), false); + await verifyProfilesNip05(dbProfileMap); editProfileContext(new Map(mergedProfileMap), false); } } @@ -442,12 +476,13 @@ export const fetchProfile = async ( authors: Array.from(pubkeyProfilesToFetch), }; - const profileMap: Map = new Map( + const profileMap: Map = new Map( Array.from(pubkeyProfilesToFetch).map((pubkey) => [ pubkey, mergedProfileMap.get(pubkey) || dbProfileMap.get(pubkey) || null, ]) ); + const updatedProfiles = new Map(); const fetchedEvents = await nostr.fetch([subParams], {}, relays); @@ -461,20 +496,14 @@ export const fetchProfile = async ( ) { try { const content = JSON.parse(event.content); - const profile = { + const profile: NipProfile = { pubkey: event.pubkey, created_at: event.created_at, - content: content, + content, nip05Verified: false, }; - if (content.nip05) { - profile.nip05Verified = await verifyNip05Identifier( - content.nip05, - event.pubkey - ); - } - profileMap.set(event.pubkey, profile); + updatedProfiles.set(event.pubkey, profile); updateProfileIfNewer(profile); } catch (error) { console.error( @@ -485,6 +514,8 @@ export const fetchProfile = async ( } } + await verifyProfilesNip05(updatedProfiles); + // Cache profiles to database via API (reconstruct from fetched events) const validProfileEvents = fetchedEvents.filter( (e) => e.id && e.sig && e.pubkey && e.kind === 0