124 lines
3.1 KiB
TypeScript
124 lines
3.1 KiB
TypeScript
"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<string, SignerStoreItem>;
|
|
|
|
type SignerContextProps = {
|
|
npubSigners: Map<string, NDKSigner>;
|
|
signers: SignerItems;
|
|
getSigner: (list: NDKList) => Promise<SignerStoreItem>;
|
|
};
|
|
const SignerContext = createContext<SignerContextProps | undefined>(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<string, NDKSigner>();
|
|
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<SignerStoreItem> {
|
|
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 (
|
|
<SignerContext.Provider value={{ signers, npubSigners, getSigner }}>
|
|
{children}
|
|
</SignerContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useSigner() {
|
|
return useContext(SignerContext);
|
|
}
|