@nostr-dev-kit/ndk
Version:
NDK - Nostr Development Kit. Includes AI Guardrails to catch common mistakes during development.
108 lines (92 loc) • 3.54 kB
text/typescript
import type { NDK } from "../ndk";
import type { Hexpubkey, ProfilePointer } from ".";
import { NDKUser } from ".";
export const NIP05_REGEX = /^(?:([\w.+-]+)@)?([\w.-]+)$/;
export async function getNip05For(
ndk: NDK,
fullname: string,
_fetch: typeof fetch = fetch,
fetchOpts: RequestInit = {},
) {
return await ndk.queuesNip05.add({
id: fullname,
func: async (): Promise<ProfilePointer | null> => {
// If we have a cache, try to load from cache first
if (ndk.cacheAdapter?.loadNip05) {
const profile = await ndk.cacheAdapter.loadNip05(fullname);
if (profile !== "missing") {
if (profile) {
const user = new NDKUser({
pubkey: profile.pubkey,
relayUrls: profile.relays,
nip46Urls: profile.nip46,
});
user.ndk = ndk;
return user;
}
if (fetchOpts.cache !== "no-cache") {
return null;
}
}
}
const match = fullname.match(NIP05_REGEX);
if (!match) return null;
const [_, name = "_", domain] = match;
try {
const res = await _fetch(`https://${domain}/.well-known/nostr.json?name=${name}`, fetchOpts);
const { names, relays, nip46 } = parseNIP05Result(await res.json());
const pubkey = names[name.toLowerCase()];
let profile: ProfilePointer | null = null;
if (pubkey) {
profile = { pubkey, relays: relays?.[pubkey], nip46: nip46?.[pubkey] };
}
// Save the lookup to cache
if (ndk?.cacheAdapter?.saveNip05) {
ndk.cacheAdapter.saveNip05(fullname, profile);
}
return profile;
} catch (_e) {
// Save the failed lookup to cache
if (ndk?.cacheAdapter?.saveNip05) {
ndk?.cacheAdapter.saveNip05(fullname, null);
}
console.error("Failed to fetch NIP05 for", fullname, _e);
return null;
}
},
});
}
export interface NIP05Result {
names: {
[name: string]: string;
};
relays?: { [pubkey: Hexpubkey]: string[] };
nip46?: { [pubkey: Hexpubkey]: string[] };
}
function parseNIP05Result(json: any): NIP05Result {
const result: NIP05Result = {
names: {},
};
for (const [name, pubkey] of Object.entries(json.names)) {
if (typeof name === "string" && typeof pubkey === "string") {
result.names[name.toLowerCase()] = pubkey;
}
}
if (json.relays) {
result.relays = {};
for (const [pubkey, relays] of Object.entries(json.relays)) {
if (typeof pubkey === "string" && Array.isArray(relays)) {
result.relays[pubkey] = relays.filter((relay: unknown) => typeof relay === "string");
}
}
}
if (json.nip46) {
result.nip46 = {};
for (const [pubkey, nip46] of Object.entries(json.nip46)) {
if (typeof pubkey === "string" && Array.isArray(nip46)) {
result.nip46[pubkey] = nip46.filter((relay: unknown) => typeof relay === "string");
}
}
}
return result;
}