aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/nostr.ts95
-rw-r--r--src/lib/settings.ts14
-rw-r--r--src/lib/store.ts13
-rw-r--r--src/lib/utils.ts20
4 files changed, 96 insertions, 46 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;
+ },
+};
diff --git a/src/lib/settings.ts b/src/lib/settings.ts
index 3ce1edd5..53a25e18 100644
--- a/src/lib/settings.ts
+++ b/src/lib/settings.ts
@@ -1,4 +1,4 @@
-import { auth, fd, get, post } from "$lib/utils";
+import { auth, fd, post } from "$lib/utils";
import { fail } from "@sveltejs/kit";
type Error = {
@@ -16,16 +16,14 @@ export default async ({ cookies, request }) => {
form.autowithdraw = form.autowithdraw === "on";
}
- let user = { ...(await get("/me", auth(cookies))), ...form };
-
try {
- ({ user } = await post("/user", user, auth(cookies)));
+ const { user } = await post("/user", form, auth(cookies));
+
+ if (user.language) cookies.set("lang", user.language, { path: "/" });
+
+ return { user, success: true };
} catch (e) {
const { message } = e as Error;
return fail(400, { message });
}
-
- if (user.language) cookies.set("lang", user.language, { path: "/" });
-
- return { user, success: true };
};
diff --git a/src/lib/store.ts b/src/lib/store.ts
index 0aba3d46..23b38ace 100644
--- a/src/lib/store.ts
+++ b/src/lib/store.ts
@@ -28,7 +28,13 @@ const persistLocal = (key, defaultValue: any = undefined) => {
s.subscribe((v) => {
try {
- browser && localStorage.setItem(key, JSON.stringify(v));
+ if (browser) {
+ if (v) {
+ localStorage.setItem(key, JSON.stringify(v));
+ } else {
+ localStorage.removeItem(key);
+ }
+ }
} catch (e) {
console.log("problem setting key", v);
console.log(e);
@@ -54,7 +60,10 @@ export const mnemonic = persistSession("mnemonic");
export const newPayment = persistLocal("newPayment");
export const password = writable<string | undefined>();
export const passwordPrompt = writable();
-export const signaturePrompt = writable();
+export const eventToSign = writable();
+export const pubkey = persistLocal("pubkey");
+export const signer = persistLocal("signer");
+export const selectSigner = writable();
export const pin = persistLocal("pin");
export const rate = writable();
export const request = writable();
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index b21ce176..e39c2adc 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -338,26 +338,6 @@ export const wait = async (
return f();
};
-export const stretch = async (password: string, salt: Uint8Array) =>
- crypto.subtle.deriveKey(
- {
- name: "PBKDF2",
- salt,
- iterations: 100000,
- hash: "SHA-256",
- },
- await crypto.subtle.importKey(
- "raw",
- new TextEncoder().encode(password),
- { name: "PBKDF2" },
- false,
- ["deriveBits", "deriveKey"],
- ),
- { name: "AES-GCM", length: 256 },
- true,
- ["encrypt", "decrypt"],
- );
-
export const types = {
bitcoin: "bitcoin",
liquid: "liquid",