aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/nostr.ts
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2025-01-09 23:44:40 -0800
committerAdam Soltys <[email protected]>2025-01-09 23:44:40 -0800
commit8588de25f16486b56ef0ad533013bd8cb48ff120 (patch)
tree4c1e39704e2edb332c5fe8c58fb0d81c8154af2b /src/lib/nostr.ts
parent2358d1bf39c34a508db6c50f0f6312ee411a8a17 (diff)
downloadcoinos-ui-8588de25f16486b56ef0ad533013bd8cb48ff120.tar.gz
coinos-ui-8588de25f16486b56ef0ad533013bd8cb48ff120.zip
nostr signing
Diffstat (limited to 'src/lib/nostr.ts')
-rw-r--r--src/lib/nostr.ts95
1 files changed, 79 insertions, 16 deletions
diff --git a/src/lib/nostr.ts b/src/lib/nostr.ts
index 77c1d60a..85f1bdaa 100644
--- a/src/lib/nostr.ts
+++ b/src/lib/nostr.ts
@@ -2,18 +2,21 @@ import { Buffer } from "buffer";
import { browser } from "$app/environment";
import {
decrypted,
+ eventToSign,
password as pw,
passwordPrompt,
- signaturePrompt,
+ signer as $signer,
} from "$lib/store";
import { post, wait } from "$lib/utils";
import {
type EventTemplate,
finalizeEvent,
+ getEventHash,
getPublicKey,
nip04,
nip19,
} from "nostr-tools";
+import { Relay } from "nostr-tools/relay";
import { get } from "svelte/store";
import {
@@ -21,8 +24,6 @@ import {
encrypt as nip49encrypt,
} from "nostr-tools/nip49";
-import { bech32m } from "@scure/base";
-
type User = {
[key: string]: any;
};
@@ -101,19 +102,17 @@ export const encryptNsec = async (nsec: string) => {
return nip49encrypt(d, await getPassword());
};
-type SignParams = {
- event: EventTemplate;
- user: User;
-};
-
-export const sign = async ({ event, user }: SignParams) => {
- let sk;
- if (user.nsec) {
- sk = await getPrivateKey(user);
- event = finalizeEvent(event, sk);
- } else {
- signaturePrompt.set(event);
- }
+export const sign = async (event) => {
+ eventToSign.set(event);
+ let unsubscribe;
+ const { method, params } = await new Promise((r) => {
+ unsubscribe = $signer.subscribe((v) => v?.ready && r(v));
+ });
+ await unsubscribe();
+ const signedEvent = await signingMethods[method](event, params);
+ eventToSign.set(signedEvent);
+ setTimeout(() => eventToSign.set(null), 1000);
+ return signedEvent;
};
export const send = (event: EventTemplate) => {
@@ -125,3 +124,67 @@ const getPassword = async (): Promise<string> => {
await wait(() => !!get(pw));
return get(pw) || "";
};
+
+export const nostrConnectRelay = "wss://relay.nsec.app";
+
+const signingMethods = {
+ async connect(event, { sk, pk, pubkey }) {
+ const id = crypto.randomUUID();
+ const signEvent = {
+ id,
+ method: "sign_event",
+ params: [JSON.stringify(event)],
+ };
+
+ const content = await nip04.encrypt(sk, pk, JSON.stringify(signEvent));
+
+ const signedSignEvent = finalizeEvent(
+ {
+ created_at: Math.round(Date.now() / 1000),
+ kind: 24133,
+ pubkey,
+ content,
+ tags: [["p", pk]],
+ },
+ sk,
+ );
+
+ const relay = await Relay.connect(nostrConnectRelay);
+ relay.publish(signedSignEvent);
+
+ return new Promise((resolve) => {
+ relay.subscribe([{ kinds: [24133], "#p": [pubkey] }], {
+ async onevent(event) {
+ pk = event.pubkey;
+ try {
+ const response = JSON.parse(
+ await nip04.decrypt(sk, pk, event.content),
+ );
+
+ if (response.id === id) resolve(JSON.parse(response.result));
+ } catch (e) {
+ console.log("failed to parse nostr connect event", e);
+ }
+ },
+ });
+ });
+ },
+
+ async nsec(event, { sk }) {
+ return finalizeEvent(event, sk);
+ },
+
+ async extension(event) {
+ return window.nostr.signEvent(event);
+ },
+
+ async signer(event, { pubkey, sig }) {
+ event.pubkey = pubkey;
+ const signedEvent = {
+ ...event,
+ id: getEventHash(event),
+ sig,
+ };
+ return signedEvent;
+ },
+};