diff options
| author | Adam Soltys <[email protected]> | 2025-01-09 23:44:40 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2025-01-09 23:44:40 -0800 |
| commit | 8588de25f16486b56ef0ad533013bd8cb48ff120 (patch) | |
| tree | 4c1e39704e2edb332c5fe8c58fb0d81c8154af2b /src/routes/(app) | |
| parent | 2358d1bf39c34a508db6c50f0f6312ee411a8a17 (diff) | |
| download | coinos-ui-8588de25f16486b56ef0ad533013bd8cb48ff120.tar.gz coinos-ui-8588de25f16486b56ef0ad533013bd8cb48ff120.zip | |
nostr signing
Diffstat (limited to 'src/routes/(app)')
| -rw-r--r-- | src/routes/(app)/+layout.svelte | 6 | ||||
| -rw-r--r-- | src/routes/(app)/[username]/(profile)/+layout.svelte | 22 | ||||
| -rw-r--r-- | src/routes/(app)/messages/[recipient]/+page.svelte | 2 | ||||
| -rw-r--r-- | src/routes/(app)/settings/+layout.svelte | 28 | ||||
| -rw-r--r-- | src/routes/(app)/settings/nostr/+page.server.ts | 6 | ||||
| -rw-r--r-- | src/routes/(app)/settings/nostr/+page.svelte | 114 |
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} |
