mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-04-13 22:29:18 +02:00
use signing service
This commit is contained in:
parent
e4c40d4a16
commit
fd044878c5
@ -16,6 +16,7 @@ import { nostrPostAction, PostResult } from "../../classes/nostr-post-action";
|
||||
import { getReferences } from "../../helpers/nostr-event";
|
||||
import { useWriteRelayUrls } from "../../hooks/use-client-relays";
|
||||
import { useIsMobile } from "../../hooks/use-is-mobile";
|
||||
import { useSigningContext } from "../../providers/signing-provider";
|
||||
import { DraftNostrEvent, NostrEvent } from "../../types/nostr-event";
|
||||
import { NoteLink } from "../note-link";
|
||||
import { PostResults } from "./post-results";
|
||||
@ -39,6 +40,7 @@ export const PostModal = ({ isOpen, onClose, initialDraft }: PostModalProps) =>
|
||||
const isMobile = useIsMobile();
|
||||
const pad = isMobile ? "2" : "4";
|
||||
|
||||
const { requestSignature } = useSigningContext();
|
||||
const writeRelays = useWriteRelayUrls();
|
||||
const [waiting, setWaiting] = useState(false);
|
||||
const [signedEvent, setSignedEvent] = useState<NostrEvent | null>(null);
|
||||
@ -50,19 +52,17 @@ export const PostModal = ({ isOpen, onClose, initialDraft }: PostModalProps) =>
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (window.nostr) {
|
||||
setWaiting(true);
|
||||
const updatedDraft: DraftNostrEvent = { ...draft, created_at: moment().unix() };
|
||||
const event = await window.nostr.signEvent(updatedDraft);
|
||||
setWaiting(false);
|
||||
setSignedEvent(event);
|
||||
setWaiting(true);
|
||||
const updatedDraft: DraftNostrEvent = { ...draft, created_at: moment().unix() };
|
||||
const event = await requestSignature(updatedDraft);
|
||||
setWaiting(false);
|
||||
if (!event) return;
|
||||
setSignedEvent(event);
|
||||
|
||||
const { results } = nostrPostAction(writeRelays, event);
|
||||
|
||||
results.subscribe((result) => {
|
||||
resultsActions.push(result);
|
||||
});
|
||||
}
|
||||
const { results } = nostrPostAction(writeRelays, event);
|
||||
results.subscribe((result) => {
|
||||
resultsActions.push(result);
|
||||
});
|
||||
};
|
||||
|
||||
const refs = getReferences(draft);
|
||||
|
@ -1,9 +1,10 @@
|
||||
import React from "react";
|
||||
import { ChakraProvider, localStorageManager } from "@chakra-ui/react";
|
||||
import theme from "../theme";
|
||||
import { SigningProvider } from "./signing-provider";
|
||||
|
||||
export const Providers = ({ children }: { children: React.ReactNode }) => (
|
||||
<ChakraProvider theme={theme} colorModeManager={localStorageManager}>
|
||||
{children}
|
||||
<SigningProvider>{children}</SigningProvider>
|
||||
</ChakraProvider>
|
||||
);
|
||||
|
41
src/providers/signing-provider.tsx
Normal file
41
src/providers/signing-provider.tsx
Normal file
@ -0,0 +1,41 @@
|
||||
import { useToast } from "@chakra-ui/react";
|
||||
import React, { useCallback, useContext, useMemo } from "react";
|
||||
import signingService from "../services/signing";
|
||||
import { DraftNostrEvent, NostrEvent } from "../types/nostr-event";
|
||||
|
||||
export type SigningContextType = {
|
||||
requestSignature: (draft: DraftNostrEvent) => Promise<NostrEvent | undefined>;
|
||||
};
|
||||
|
||||
export const SigningContext = React.createContext<SigningContextType>({
|
||||
requestSignature: () => {
|
||||
throw new Error("not setup yet");
|
||||
},
|
||||
});
|
||||
|
||||
export function useSigningContext() {
|
||||
return useContext(SigningContext);
|
||||
}
|
||||
|
||||
export const SigningProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
const toast = useToast();
|
||||
|
||||
const requestSignature = useCallback(
|
||||
async (draft: DraftNostrEvent) => {
|
||||
try {
|
||||
return await signingService.requestSignature(draft);
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
toast({
|
||||
status: "error",
|
||||
description: e.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
[toast]
|
||||
);
|
||||
const context = useMemo(() => ({ requestSignature }), [requestSignature]);
|
||||
|
||||
return <SigningContext.Provider value={context}>{children}</SigningContext.Provider>;
|
||||
};
|
@ -5,6 +5,7 @@ import { DraftNostrEvent, PTag } from "../types/nostr-event";
|
||||
import clientRelaysService from "./client-relays";
|
||||
import accountService from "./account";
|
||||
import userContactsService, { UserContacts } from "./user-contacts";
|
||||
import signingService from "./signing";
|
||||
|
||||
export type RelayDirectory = Record<string, { read: boolean; write: boolean }>;
|
||||
|
||||
@ -73,18 +74,16 @@ async function savePending() {
|
||||
const draft = pendingDraft.value;
|
||||
if (!draft) return;
|
||||
|
||||
if (window.nostr) {
|
||||
savingDraft.next(true);
|
||||
const event = await window.nostr.signEvent(draft);
|
||||
savingDraft.next(true);
|
||||
const event = await signingService.requestSignature(draft);
|
||||
|
||||
const results = nostrPostAction(clientRelaysService.getWriteUrls(), event);
|
||||
await results.onComplete;
|
||||
const results = nostrPostAction(clientRelaysService.getWriteUrls(), event);
|
||||
await results.onComplete;
|
||||
|
||||
savingDraft.next(false);
|
||||
savingDraft.next(false);
|
||||
|
||||
// pass new event to contact list service
|
||||
userContactsService.handleEvent(event);
|
||||
}
|
||||
// pass new event to contact list service
|
||||
userContactsService.handleEvent(event);
|
||||
}
|
||||
|
||||
function addContact(pubkey: string, relay?: string) {
|
||||
|
@ -6,6 +6,7 @@ import accountService from "./account";
|
||||
import { RelayConfig, RelayMode } from "../classes/relay";
|
||||
import userRelaysService, { UserRelays } from "./user-relays";
|
||||
import { PersistentSubject, Subject } from "../classes/subject";
|
||||
import signingService from "./signing";
|
||||
|
||||
export type RelayDirectory = Record<string, { read: boolean; write: boolean }>;
|
||||
|
||||
@ -77,15 +78,13 @@ class ClientRelayService {
|
||||
const oldRelayUrls = this.relays.value.filter((r) => r.mode & RelayMode.WRITE).map((r) => r.url);
|
||||
const writeUrls = unique([...oldRelayUrls, ...newRelayUrls]);
|
||||
|
||||
if (window.nostr) {
|
||||
const event = await window.nostr.signEvent(draft);
|
||||
const event = await signingService.requestSignature(draft);
|
||||
|
||||
const results = nostrPostAction(writeUrls, event);
|
||||
await results.onComplete;
|
||||
const results = nostrPostAction(writeUrls, event);
|
||||
await results.onComplete;
|
||||
|
||||
// pass new event to the user relay service
|
||||
userRelaysService.handleEvent(event);
|
||||
}
|
||||
// pass new event to the user relay service
|
||||
userRelaysService.handleEvent(event);
|
||||
}
|
||||
|
||||
getWriteUrls() {
|
||||
|
@ -82,7 +82,7 @@ async function pruneCache() {
|
||||
const keys = await db.getAllKeysFromIndex(
|
||||
"dnsIdentifiers",
|
||||
"updated",
|
||||
IDBKeyRange.upperBound(moment().subtract(1, "hour").unix())
|
||||
IDBKeyRange.upperBound(moment().subtract(1, "day").unix())
|
||||
);
|
||||
|
||||
for (const pubkey of keys) {
|
||||
|
32
src/services/signing.tsx
Normal file
32
src/services/signing.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import { DraftNostrEvent, NostrEvent } from "../types/nostr-event";
|
||||
import accountService from "./account";
|
||||
import { signEvent, getEventHash, getPublicKey } from "nostr-tools";
|
||||
|
||||
class SigningService {
|
||||
async requestSignature(draft: DraftNostrEvent) {
|
||||
const account = accountService.current.value;
|
||||
|
||||
if (account?.readonly) throw new Error("cant sign in readonly mode");
|
||||
if (account?.useExtension) {
|
||||
if (window.nostr) {
|
||||
const signed = await window.nostr.signEvent(draft);
|
||||
if (signed.pubkey !== account.pubkey) throw new Error("signed with the wrong pubkey!");
|
||||
return signed;
|
||||
} else throw new Error("missing nostr extension");
|
||||
} else if (account?.secKey) {
|
||||
const tmpDraft = { ...draft, pubkey: getPublicKey(account.secKey) };
|
||||
const signature = signEvent(tmpDraft, account.secKey);
|
||||
const event: NostrEvent = {
|
||||
...tmpDraft,
|
||||
id: getEventHash(tmpDraft),
|
||||
sig: signature,
|
||||
};
|
||||
|
||||
return event;
|
||||
} else throw new Error("no signing method");
|
||||
}
|
||||
}
|
||||
|
||||
const signingService = new SigningService();
|
||||
|
||||
export default signingService;
|
@ -26,7 +26,7 @@ export const LoginStartView = () => {
|
||||
relays = Object.keys(extRelays).filter((url) => extRelays[url].read);
|
||||
}
|
||||
|
||||
accountService.addAccount({ pubkey, relays });
|
||||
accountService.addAccount({ pubkey, relays, useExtension: true });
|
||||
}
|
||||
|
||||
accountService.switchAccount(pubkey);
|
||||
|
@ -17,10 +17,8 @@ export const UserCard = ({ pubkey, relay }: { pubkey: string; relay?: string })
|
||||
<Box>
|
||||
<Link as={ReactRouterLink} to={`/u/${normalizeToBech32(pubkey, Bech32Prefix.Pubkey)}`}>
|
||||
<Heading size="sm">{getUserDisplayName(metadata, pubkey)}</Heading>
|
||||
<Text>
|
||||
<UserDnsIdentityIcon pubkey={pubkey} />
|
||||
</Text>
|
||||
</Link>
|
||||
<UserDnsIdentityIcon pubkey={pubkey} />
|
||||
{relay && <Text>{relay}</Text>}
|
||||
</Box>
|
||||
</Flex>
|
||||
|
@ -16,11 +16,13 @@ export const UserProfileMenu = ({ pubkey, ...props }: { pubkey: string } & Omit<
|
||||
|
||||
const loginAsUser = () => {
|
||||
const readRelays = userRelays?.relays.filter((r) => r.mode === RelayMode.READ).map((r) => r.url) ?? [];
|
||||
accountService.addAccount({
|
||||
pubkey,
|
||||
relays: readRelays,
|
||||
readonly: true,
|
||||
});
|
||||
if (!accountService.hasAccount(pubkey)) {
|
||||
accountService.addAccount({
|
||||
pubkey,
|
||||
relays: readRelays,
|
||||
readonly: true,
|
||||
});
|
||||
}
|
||||
accountService.switchAccount(pubkey);
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user