import { useNostr } from '@nostrify/react'; import { useNostrLogin, type NLoginType } from '@nostrify/react/login'; import { useQuery } from '@tanstack/react-query'; import { NSchema as n, NostrEvent, NostrMetadata } from '@nostrify/nostrify'; export interface Account { id: string; pubkey: string; event?: NostrEvent; metadata: NostrMetadata; } // Fallback relays for fetching profile data const FALLBACK_RELAYS = [ 'wss://relay.damus.io', 'wss://nos.lol', 'wss://purplepag.es', ]; export function useLoggedInAccounts() { const { nostr } = useNostr(); const { logins, setLogin, removeLogin } = useNostrLogin(); // Extract pubkey safely — works for both standard NLoginType and custom AmberLoginType const getPubkey = (login: NLoginType): string | undefined => { return (login as unknown as { pubkey?: string }).pubkey; }; const loginPubkeys = logins.map(getPubkey).filter((p): p is string => !!p); const { data: authors = [] } = useQuery({ queryKey: ['nostr', 'logins', logins.map((l) => l.id).join(';')], queryFn: async ({ signal }) => { if (logins.length === 0) return []; if (loginPubkeys.length === 0) return []; // Try primary relays first with longer timeout let events: NostrEvent[] = []; try { events = await nostr.query( [{ kinds: [0], authors: loginPubkeys }], { signal: AbortSignal.any([signal, AbortSignal.timeout(5000)]) }, ); } catch (error) { console.warn('[useLoggedInAccounts] Primary relay query failed, trying fallback relays...'); } // If no events found, try fallback relays if (events.length === 0) { try { const fallbackGroup = nostr.group(FALLBACK_RELAYS); events = await fallbackGroup.query( [{ kinds: [0], authors: loginPubkeys }], { signal: AbortSignal.any([signal, AbortSignal.timeout(8000)]) }, ); if (events.length > 0) { console.log('[useLoggedInAccounts] Found profile on fallback relays'); } } catch (error) { console.warn('[useLoggedInAccounts] Fallback relay query also failed:', error); } } return logins.map((login): Account => { const id = login.id; const pubkey = getPubkey(login) ?? ''; const event = events.find((e) => e.pubkey === pubkey); try { const metadata = n.json().pipe(n.metadata()).parse(event?.content); return { id, pubkey, metadata, event }; } catch { return { id, pubkey, metadata: {}, event }; } }); }, retry: 3, retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 10000), staleTime: 30000, // Consider data fresh for 30 seconds }); // Current user is the first login const currentUser: Account | undefined = (() => { const login = logins[0]; if (!login) return undefined; const pubkey = getPubkey(login) ?? ''; const author = authors.find((a) => a.id === login.id); return { metadata: {}, ...author, id: login.id, pubkey }; })(); // Other users are all logins except the current one const otherUsers = (authors || []).slice(1) as Account[]; return { authors, currentUser, otherUsers, setLogin, removeLogin, }; }