aboutsummaryrefslogtreecommitdiffstats
path: root/src/routes/(app)
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/routes/(app)
parent2358d1bf39c34a508db6c50f0f6312ee411a8a17 (diff)
downloadcoinos-ui-8588de25f16486b56ef0ad533013bd8cb48ff120.tar.gz
coinos-ui-8588de25f16486b56ef0ad533013bd8cb48ff120.zip
nostr signing
Diffstat (limited to 'src/routes/(app)')
-rw-r--r--src/routes/(app)/+layout.svelte6
-rw-r--r--src/routes/(app)/[username]/(profile)/+layout.svelte22
-rw-r--r--src/routes/(app)/messages/[recipient]/+page.svelte2
-rw-r--r--src/routes/(app)/settings/+layout.svelte28
-rw-r--r--src/routes/(app)/settings/nostr/+page.server.ts6
-rw-r--r--src/routes/(app)/settings/nostr/+page.svelte114
6 files changed, 101 insertions, 77 deletions
diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte
index e179005f..d037e5be 100644
--- a/src/routes/(app)/+layout.svelte
+++ b/src/routes/(app)/+layout.svelte
@@ -8,7 +8,7 @@
request,
ndef,
passwordPrompt,
- signaturePrompt,
+ selectSigner,
password,
pin,
theme as themeStore,
@@ -91,8 +91,8 @@
<Password {user} />
{/if}
-{#if browser && $signaturePrompt}
- <Nostr event={$signaturePrompt} />
+{#if browser}
+ <Nostr />
{/if}
<svelte:head>
diff --git a/src/routes/(app)/[username]/(profile)/+layout.svelte b/src/routes/(app)/[username]/(profile)/+layout.svelte
index a83ed8d0..a5f336e7 100644
--- a/src/routes/(app)/[username]/(profile)/+layout.svelte
+++ b/src/routes/(app)/[username]/(profile)/+layout.svelte
@@ -77,7 +77,7 @@
};
try {
- await sign({ event, user });
+ await sign(event);
await send(event);
} catch (e) {
console.log(e);
@@ -205,7 +205,8 @@
)}`}
class="my-auto"
>
- <iconify-icon noobserver icon="ph:qr-code-bold" width="32"></iconify-icon>
+ <iconify-icon noobserver icon="ph:qr-code-bold" width="32"
+ ></iconify-icon>
</a>
</div>
</div>
@@ -222,7 +223,8 @@
></iconify-icon></button
>
<a href={`/qr/${encodeURIComponent(npub)}`} class="my-auto">
- <iconify-icon noobserver icon="ph:qr-code-bold" width="32"></iconify-icon>
+ <iconify-icon noobserver icon="ph:qr-code-bold" width="32"
+ ></iconify-icon>
</a>
</div>
</div>
@@ -234,12 +236,14 @@
{#if user && user.username !== subject.username && subject.pubkey}
{#if following}
<button class="btn" onclick={unfollow}>
- <iconify-icon noobserver icon="ph:user-bold" width="32"></iconify-icon>
+ <iconify-icon noobserver icon="ph:user-bold" width="32"
+ ></iconify-icon>
<div class="my-auto">{$t("user.unfollow")}</div>
</button>
{:else}
<button class="btn" onclick={follow}>
- <iconify-icon noobserver icon="ph:user-bold" width="32"></iconify-icon>
+ <iconify-icon noobserver icon="ph:user-bold" width="32"
+ ></iconify-icon>
<div class="my-auto">{$t("user.follow")}</div>
</button>
{/if}
@@ -266,7 +270,8 @@
class="rounded-2xl border py-5 px-6 font-bold hover:opacity-80 flex w-60"
>
<div class="mx-auto flex">
- <iconify-icon noobserver icon="ph:clock" width="32"></iconify-icon>
+ <iconify-icon noobserver icon="ph:clock" width="32"
+ ></iconify-icon>
</div>
</button>
</form>
@@ -296,7 +301,10 @@
</div>
<div class="text-secondary flex ml-auto">
<div class="flex items-center">
- <iconify-icon noobserver icon="ph:lightning-fill" class="text-yellow-300"
+ <iconify-icon
+ noobserver
+ icon="ph:lightning-fill"
+ class="text-yellow-300"
></iconify-icon>
{s((1 * sats) / rate)} =
{f(1, currency, locale, 0, 0)}
diff --git a/src/routes/(app)/messages/[recipient]/+page.svelte b/src/routes/(app)/messages/[recipient]/+page.svelte
index bc1a6383..d1cf6f94 100644
--- a/src/routes/(app)/messages/[recipient]/+page.svelte
+++ b/src/routes/(app)/messages/[recipient]/+page.svelte
@@ -91,7 +91,7 @@
user,
});
event.id = getEventHash(event);
- await sign({ event, user });
+ await sign(event);
await send(event);
sent = true;
diff --git a/src/routes/(app)/settings/+layout.svelte b/src/routes/(app)/settings/+layout.svelte
index 85e5b0e6..c6cc81c4 100644
--- a/src/routes/(app)/settings/+layout.svelte
+++ b/src/routes/(app)/settings/+layout.svelte
@@ -9,7 +9,7 @@
import Pin from "$comp/Pin.svelte";
import { loading, t } from "$lib/translations";
import { fd, fail, auth, post, sleep, warning, success } from "$lib/utils";
- import { avatar, banner, password, pin, save } from "$lib/store";
+ import { avatar, banner, signer, password, pin, save } from "$lib/store";
import { upload } from "$lib/upload";
import { page } from "$app/stores";
import { sign, send, setNsec } from "$lib/nostr";
@@ -53,10 +53,21 @@
},
});
- if (data.get("newNsec")) {
- await setNsec(user, data.get("newNsec"));
- data.set("nsec", user.nsec);
- data.set("pubkey", user.pubkey);
+ if (!user.pubkey || user.pubkey === prev.pubkey) {
+ data.delete("pubkey");
+ } else {
+ signer.set(
+ user.extension ? { method: "extension", ready: true } : null,
+ );
+ let event = {
+ kind: 1,
+ created_at: Date.now(),
+ content: user.challenge,
+ tags: [],
+ };
+
+ let signedEvent = await sign(event);
+ data.set("event", JSON.stringify(signedEvent));
}
if ($avatar) {
@@ -89,7 +100,7 @@
}
if (
- ["username", "about", "picture"].some(
+ ["username", "about", "picture", "display", "banner"].some(
(a) => user[a] && user[a] !== prev[a],
)
) {
@@ -101,14 +112,17 @@
name: user.username,
about: user.about,
picture: user.picture,
+ banner: user.banner,
+ displayName: user.display,
}),
tags: [],
};
try {
- await sign({ event, user });
+ await sign(event);
await send(event);
} catch (e) {
+ console.log(e);
warning("Nostr profile could not be updated");
}
}
diff --git a/src/routes/(app)/settings/nostr/+page.server.ts b/src/routes/(app)/settings/nostr/+page.server.ts
index 4145935e..b4bb124b 100644
--- a/src/routes/(app)/settings/nostr/+page.server.ts
+++ b/src/routes/(app)/settings/nostr/+page.server.ts
@@ -1,5 +1,11 @@
+import { get } from "$lib/utils";
import updateUser from "$lib/settings";
+export const load = async () => {
+ const { challenge } = await get("/challenge");
+ return { challenge };
+};
+
export const actions = {
default: updateUser,
};
diff --git a/src/routes/(app)/settings/nostr/+page.svelte b/src/routes/(app)/settings/nostr/+page.svelte
index 3757f96f..cfcfaf39 100644
--- a/src/routes/(app)/settings/nostr/+page.svelte
+++ b/src/routes/(app)/settings/nostr/+page.svelte
@@ -3,35 +3,29 @@
import { page } from "$app/stores";
import { tick } from "svelte";
import { t } from "$lib/translations";
- import { copy } from "$lib/utils";
+ import { copy, fail } from "$lib/utils";
import {
PUBLIC_COINOS_PUBKEY as pk,
PUBLIC_COINOS_RELAY as relay,
} from "$env/static/public";
+ import { signer, save } from "$lib/store";
let { data } = $props();
- let { user } = $derived(data);
- let { id, npub } = $derived(user);
+ let { challenge, user } = $derived(data);
+ let { npub } = $state(user);
- let importing = $state(),
- newNsec = $state(),
+ let newNsec = $state(),
nsec = $state(),
pin = $state(""),
revealNsec = $state(),
revealNwc = $state();
- let toggleImporting = () => {
- revealNsec = false;
- importing = !importing;
- };
-
let toggleNsec = async () => {
try {
nsec = await getNsec(user);
revealNsec = !revealNsec;
- importing = false;
} catch (e) {
- console.log(e);
+ fail("Failed to decrypt nsec");
}
};
@@ -42,9 +36,19 @@
)}&secret=${user.nwc}&lud16=${lud16}`,
);
let toggleNwc = () => (revealNwc = !revealNwc);
+
+ let extension = $state();
+ let getPubkey = async () => {
+ extension = true;
+ npub = await window.nostr.getPublicKey();
+ await tick();
+ $save.click();
+ };
</script>
<div>
+ <input type="hidden" name="challenge" value={challenge} />
+ <input type="hidden" name="extension" value={extension} />
<label for="nwc" class="font-bold">{$t("user.settings.nwc")}</label>
<p class="text-secondary mb-1">
@@ -83,12 +87,10 @@
</div>
{/if}
-<div>
+<div class="space-y-2">
<div class="font-bold">{$t("user.nostrPubkey")}</div>
<div class="flex gap-4">
- <div class="break-all grow">
- {npub}
- </div>
+ <textarea name="pubkey" bind:value={npub}> </textarea>
<div class="flex my-auto gap-1">
<button type="button" class="my-auto" onclick={() => copy(npub)}
><iconify-icon noobserver icon="ph:copy-bold" width="32"
@@ -100,54 +102,48 @@
</a>
</div>
</div>
-</div>
-<div class="space-y-2">
- <label for="seedphrase" class="font-bold"
- >{$t("user.settings.nostrKeys")}</label
+ <button class="btn" type="button" onclick={getPubkey}>
+ <iconify-icon icon="lucide-lab:bee" width="32" class="text-yellow-400"
+ ></iconify-icon>
+ {$t("user.settings.syncWithExtension")}</button
>
+</div>
- <p class="text-secondary mb-1">
- {$t("user.settings.nostrDescription")}
- </p>
-
- <div class="flex flex-wrap sm:flex-nowrap gap-2">
- <button
- type="button"
- class="btn !w-auto flex-grow"
- onclick={toggleImporting}
+{#if user.nsec}
+ <div class="space-y-2">
+ <label for="seedphrase" class="font-bold"
+ >{$t("user.settings.nostrKeys")}</label
>
- <iconify-icon noobserver icon="ph:arrow-down-left-bold" width="32"
- ></iconify-icon>
- {$t("user.settings.import")}
- </button>
- <button type="button" class="btn !w-auto flex-grow" onclick={toggleNsec}>
- {#if revealNsec}
- <iconify-icon noobserver icon="ph:eye-slash-bold" width="32"
- ></iconify-icon>
- {$t("user.settings.hideNsec")}
- {:else}
- <iconify-icon noobserver icon="ph:warning-bold" width="32"
- ></iconify-icon>
- {$t("user.settings.revealNsec")}
- {/if}
- </button>
- </div>
+ <p class="text-secondary mb-1">
+ {$t("user.settings.nostrDescription")}
+ </p>
- {#if importing}
- <input name="newNsec" bind:value={newNsec} placeholder="nsec..." />
- {/if}
+ <div class="flex flex-wrap sm:flex-nowrap gap-2">
+ <button type="button" class="btn !w-auto flex-grow" onclick={toggleNsec}>
+ {#if revealNsec}
+ <iconify-icon noobserver icon="ph:eye-slash-bold" width="32"
+ ></iconify-icon>
+ {$t("user.settings.hideNsec")}
+ {:else}
+ <iconify-icon noobserver icon="ph:warning-bold" width="32"
+ ></iconify-icon>
+ {$t("user.settings.revealNsec")}
+ {/if}
+ </button>
+ </div>
- {#if revealNsec}
- <button
- type="button"
- class="btn break-all !h-auto font-normal leading-normal flex-nowrap"
- onclick={() => copy(nsec)}
- >
- <div>{nsec}</div>
+ {#if revealNsec}
+ <button
+ type="button"
+ class="btn break-all !h-auto font-normal leading-normal flex-nowrap"
+ onclick={() => copy(nsec)}
+ >
+ <div>{nsec}</div>
- <iconify-icon noobserver icon="ph:copy-bold" width="32"></iconify-icon>
- </button>
- {/if}
-</div>
+ <iconify-icon noobserver icon="ph:copy-bold" width="32"></iconify-icon>
+ </button>
+ {/if}
+ </div>
+{/if}