"use client"; import { createContext, useContext, useState, useMemo, type ReactNode, } from "react"; import useCurrentUser from "@/lib/hooks/useCurrentUser"; import { findEphemeralSigner } from "@/lib/actions/ephemeral"; import { NDKPrivateKeySigner, NDKUser, type NDKSigner, type NDKList, } from "@nostr-dev-kit/ndk"; import { useNDK } from "../ndk"; import { log } from "@/lib/utils"; import { getTagValues } from "@/lib/nostr/utils"; export type SignerStoreItem = { signer: NDKPrivateKeySigner; user: NDKUser; saved: boolean; title?: string; id: string; }; type SignerItems = Map; type SignerContextProps = { npubSigners: Map; signers: SignerItems; getSigner: (list: NDKList) => Promise; }; const SignerContext = createContext(undefined); export default function SignerProvider({ children, }: { children?: ReactNode | undefined; }) { const { currentUser } = useCurrentUser(); const { ndk } = useNDK(); const [signers, setSigners] = useState(new Map()); const npubSigners = useMemo(() => { const npubs = new Map(); for (const entry of signers) { const { user, signer } = entry[1]; npubs.set(user.npub, signer); } return npubs; }, [signers]); async function getDelegatedSignerName(list: NDKList) { let name = ""; console.log("getDelegatedSignerName", JSON.stringify(list)); if (list.kind === 30044) { return list.title; } if (!currentUser?.profile) { console.log("fetching user profile"); await currentUser?.fetchProfile(); } name = `${ currentUser?.profile?.displayName ?? currentUser?.profile?.name ?? currentUser?.profile?.nip05 ?? `${currentUser?.npub.slice(0, 9)}...` }'s `; const suffix = list.kind === 30044 ? "Subscription" : "List"; return name + list.title ?? suffix; } async function getSigner(list: NDKList): Promise { log("func", "getSigner"); const id = list.encode(); log("info", "list ID", id.toString()); let item = signers.get(id); if (item) return item; log("info", "NO local signer"); let signer = await findEphemeralSigner(ndk!, ndk!.signer!, { associatedEventNip19: list.encode(), }); if (signer) { log("info", `found a signer for ${list.title}`, JSON.stringify(signer)); item = { signer: signer!, user: await signer.user(), saved: true, id, }; } else { log("info", `no signer found for ${list.title}`); signer = NDKPrivateKeySigner.generate(); log("info", "generated signer", JSON.stringify(signer)); item = { signer, user: await signer.user(), saved: false, title: await getDelegatedSignerName(list), id, }; } item.user.ndk = ndk; setSigners((prev) => new Map(prev.set(id, item))); return item; } return ( {children} ); } export function useSigner() { return useContext(SignerContext); }