diff --git a/packages/nostr/src/crypto.ts b/packages/nostr/src/crypto.ts index fe167c6d..caee0388 100644 --- a/packages/nostr/src/crypto.ts +++ b/packages/nostr/src/crypto.ts @@ -1,7 +1,6 @@ import * as secp from "@noble/secp256k1" import base64 from "base64-js" import { bech32 } from "bech32" -import { NostrError } from "./common" // TODO Use toHex as well as toString? Might be more explicit // Or maybe replace toString with toHex diff --git a/packages/nostr/src/event/direct-message.ts b/packages/nostr/src/event/direct-message.ts index c90111d5..e08df8c6 100644 --- a/packages/nostr/src/event/direct-message.ts +++ b/packages/nostr/src/event/direct-message.ts @@ -50,8 +50,24 @@ export async function createDirectMessage( ): Promise { recipient = parsePublicKey(recipient) if (priv === undefined) { - // TODO Use NIP-07 - throw new NostrError("todo") + if ( + typeof window === "undefined" || + window.nostr?.nip04?.encrypt === undefined + ) { + throw new NostrError("private key not specified") + } + const content = await window.nostr.nip04.encrypt(recipient, message) + return await signEvent( + { + kind: EventKind.DirectMessage, + tags: [["p", recipient]], + content, + getMessage, + getRecipient, + getPrevious, + }, + priv + ) } else { priv = parsePrivateKey(priv) const { data, iv } = await aesEncryptBase64(priv, recipient, message) @@ -81,8 +97,13 @@ export async function getMessage( throw new NostrError(`invalid direct message content ${this.content}`) } if (priv === undefined) { - // TODO Try to use NIP-07 - throw new NostrError("todo") + if ( + typeof window === "undefined" || + window.nostr?.nip04?.decrypt === undefined + ) { + throw new NostrError("private key not specified") + } + return await window.nostr.nip04.decrypt(this.pubkey, this.content) } else if (getPublicKey(priv) === this.getRecipient()) { return await aesDecryptBase64(this.pubkey, priv, { data, iv }) } diff --git a/packages/nostr/src/event/index.ts b/packages/nostr/src/event/index.ts index 535e7c71..cb0aa5d4 100644 --- a/packages/nostr/src/event/index.ts +++ b/packages/nostr/src/event/index.ts @@ -22,6 +22,7 @@ import { } from "./direct-message" import { ContactList, getContacts } from "./contact-list" import { Deletion, getEvents } from "./deletion" +import "../nostr-object" // TODO Add remaining event types @@ -135,8 +136,10 @@ export async function signEvent( event.sig = await schnorrSign(id, priv) return event as T } else { - // TODO Try to use NIP-07, otherwise throw - throw new NostrError("todo") + if (typeof window === "undefined" || window.nostr === undefined) { + throw new NostrError("no private key provided") + } + return await window.nostr.signEvent(event) } } diff --git a/packages/nostr/src/nostr-object.ts b/packages/nostr/src/nostr-object.ts new file mode 100644 index 00000000..3f837f70 --- /dev/null +++ b/packages/nostr/src/nostr-object.ts @@ -0,0 +1,20 @@ +import { PublicKey } from "./crypto" +import { RawEvent, Unsigned } from "./event" + +declare global { + interface Window { + nostr?: { + getPublicKey: () => Promise + signEvent: (event: Unsigned) => Promise + + getRelays?: () => Promise<{ + [url: string]: { read: boolean; write: boolean } + }> + + nip04?: { + encrypt?: (pubkey: PublicKey, plaintext: string) => Promise + decrypt?: (pubkey: PublicKey, ciphertext: string) => Promise + } + } + } +}