Files
grimoire/src/hooks/useRelayInfo.ts
2025-12-14 12:00:55 +01:00

66 lines
1.8 KiB
TypeScript

import { useLiveQuery } from "dexie-react-hooks";
import { useEffect, useMemo } from "react";
import { RelayInformation } from "../types/nip11";
import { fetchRelayInfo } from "../lib/nip11";
import db from "../services/db";
import { normalizeRelayURL } from "../lib/relay-url";
/**
* React hook to fetch and cache relay information (NIP-11)
* @param wsUrl - WebSocket URL of the relay (ws:// or wss://)
* @returns Relay information or undefined if not yet loaded
*/
export function useRelayInfo(
wsUrl: string | undefined,
): RelayInformation | undefined {
// Normalize URL once
const normalizedUrl = useMemo(() => {
if (!wsUrl) return undefined;
try {
return normalizeRelayURL(wsUrl);
} catch (error) {
console.warn(`useRelayInfo: Invalid relay URL ${wsUrl}:`, error);
return undefined;
}
}, [wsUrl]);
const cached = useLiveQuery(
() => (normalizedUrl ? db.relayInfo.get(normalizedUrl) : undefined),
[normalizedUrl],
);
useEffect(() => {
if (!normalizedUrl) return;
if (cached) return;
// Fetch relay info if not in cache
fetchRelayInfo(normalizedUrl).then((info) => {
if (info) {
db.relayInfo.put({
url: normalizedUrl,
info,
fetchedAt: Date.now(),
});
}
});
}, [cached, normalizedUrl]);
return cached?.info;
}
/**
* React hook to check if a relay supports a specific NIP
* @param wsUrl - WebSocket URL of the relay
* @param nipNumber - NIP number to check (e.g., 42 for NIP-42)
* @returns true if supported, false if not, undefined if not yet loaded
*/
export function useRelaySupportsNip(
wsUrl: string | undefined,
nipNumber: number,
): boolean | undefined {
const info = useRelayInfo(wsUrl);
if (!info) return undefined;
return info.supported_nips?.includes(nipNumber) ?? false;
}