diff options
| -rw-r--r-- | src/components/Pin.svelte | 6 | ||||
| -rw-r--r-- | src/lib/store.js | 11 | ||||
| -rw-r--r-- | src/lib/utils.js | 2 | ||||
| -rw-r--r-- | src/routes/send/+layout.svelte | 18 | ||||
| -rw-r--r-- | src/routes/send/[uuid=uuid]/+page.server.js | 15 | ||||
| -rw-r--r-- | src/routes/send/[uuid=uuid]/+page.svelte | 15 | ||||
| -rw-r--r-- | src/routes/send/bitcoin/[address]/+page.server.js | 13 | ||||
| -rw-r--r-- | src/routes/send/bitcoin/[address]/+page.svelte | 16 | ||||
| -rw-r--r-- | src/routes/send/lightning/[payreq]/+page.server.js | 16 | ||||
| -rw-r--r-- | src/routes/send/lightning/[payreq]/+page.svelte | 14 | ||||
| -rw-r--r-- | src/routes/send/user/[username]/[...amount]/+page.server.js | 15 | ||||
| -rw-r--r-- | src/routes/send/user/[username]/[...amount]/+page.svelte | 16 |
12 files changed, 130 insertions, 27 deletions
diff --git a/src/components/Pin.svelte b/src/components/Pin.svelte index 3e5769b0..86e78ac1 100644 --- a/src/components/Pin.svelte +++ b/src/components/Pin.svelte @@ -2,11 +2,10 @@ import { tick } from "svelte"; import { pin } from '$lib/store'; import { Pincode, PincodeInput } from 'svelte-pincode'; - let complete = () => {}; let pinCode = []; let pinInput; - let submit, loading; + let loading; $: pinInput && tick().then(pinInput.focusFirstInput); $: pinCode.length > 5 && ($pin = pinCode.join('')); @@ -16,7 +15,7 @@ <div class="relative top-1/3 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white space-y-5"> <h1 class="text-center text-2xl font-semibold">Please enter your PIN</h1> <div class="text-center"> - <Pincode bind:complete bind:code={pinCode} bind:this={pinInput}> + <Pincode bind:code={pinCode} bind:this={pinInput}> <PincodeInput /> <PincodeInput /> <PincodeInput /> @@ -28,7 +27,6 @@ <div class="w-full flex"> <button - bind:this={submit} type="submit" class="border-2 border-black rounded-xl font-semibold mx-auto py-3 w-40 hover:opacity-80 mx-auto" class:bg-black={loading} diff --git a/src/lib/store.js b/src/lib/store.js index 4e5421ba..c648a657 100644 --- a/src/lib/store.js +++ b/src/lib/store.js @@ -2,13 +2,20 @@ import { get, writable } from 'svelte/store'; import { browser } from '$app/environment'; // creates a Svelte store synced to sessionStorage with the given key and default value -const persistSession = (key, defaultValue) => { +const persistSession = (key, defaultValue, expiry = 60 * 5 * 1000) => { + if (browser && new Date() - expiry > sessionStorage.getItem(key + 'time')) { + console.log('expired', sessionStorage.getItem(key + 'time')); + sessionStorage.removeItem(key); + } + let s = writable( browser && sessionStorage.getItem(key) && sessionStorage.getItem(key) !== 'undefined' ? JSON.parse(sessionStorage.getItem(key)) : defaultValue ); + browser && sessionStorage.setItem(key + 'time', Date.now()); + s.subscribe((v) => browser && sessionStorage.setItem(key, JSON.stringify(v))); return s; @@ -38,4 +45,4 @@ export const colorTheme = writable('from-primary to-gradient'); export const tempProfileFiles = writable(); export const avatarUpload = writable(); export const bannerUpload = writable(); -export const pin = writable(); +export const pin = persistSession('pin'); diff --git a/src/lib/utils.js b/src/lib/utils.js index d8a7b60c..7eeab648 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -42,6 +42,8 @@ export const post = (url, body, headers) => { throw new Error(body); } + + if (body.error) throw body.error; if (body instanceof Error) throw body; if (body.name === 'Error') throw new Error(body.message); diff --git a/src/routes/send/+layout.svelte b/src/routes/send/+layout.svelte new file mode 100644 index 00000000..c9122466 --- /dev/null +++ b/src/routes/send/+layout.svelte @@ -0,0 +1,18 @@ +<script> + import { Pin } from '$comp'; + import { pin } from '$lib/store'; + import { onMount } from 'svelte'; + + export let data; + + let loaded; + let { user } = data; + + onMount(() => setTimeout(() => (loaded = true), 50)); +</script> + +{#if loaded && user.haspin && $pin?.length !== 6} + <Pin /> +{/if} + +<slot /> diff --git a/src/routes/send/[uuid=uuid]/+page.server.js b/src/routes/send/[uuid=uuid]/+page.server.js index 661e9e7b..c9c77f70 100644 --- a/src/routes/send/[uuid=uuid]/+page.server.js +++ b/src/routes/send/[uuid=uuid]/+page.server.js @@ -10,14 +10,19 @@ export async function load({ params, parent }) { export const actions = { default: async ({ cookies, params, request }) => { - let body = Object.fromEntries(await request.formData()); - let { confirmed } = body; + try { + let body = Object.fromEntries(await request.formData()); + let { confirmed } = body; - if (!confirmed) { - return invalid(403, { amount, confirm: true }); + if (!confirmed) { + return invalid(403, { amount, confirm: true }); + } + + await post('/send', body, auth(cookies)); + } catch (e) { + return invalid(400, { message: e.message }); } - await post('/send', body, auth(cookies)); throw redirect(307, '/sent'); } }; diff --git a/src/routes/send/[uuid=uuid]/+page.svelte b/src/routes/send/[uuid=uuid]/+page.svelte index aa798bc1..73712f71 100644 --- a/src/routes/send/[uuid=uuid]/+page.svelte +++ b/src/routes/send/[uuid=uuid]/+page.svelte @@ -1,6 +1,6 @@ <script> import { goto } from '$app/navigation'; - import { selectedRate } from '$lib/store'; + import { pin, selectedRate } from '$lib/store'; import { enhance } from '$app/forms'; import { Icon, Numpad, Spinner } from '$comp'; import { page } from '$app/stores'; @@ -31,12 +31,24 @@ let loading; let submit = () => (loading = true); + + $: update(form); + let update = () => { + if (form?.message.includes('pin')) $pin = undefined; + loading = false; + }; </script> <button class="ml-5 md:ml-20 mt-5 md:mt-10 hover:opacity-80" on:click={handleBack}> <Icon icon="arrow-left" style="w-10" /> </button> +{#if form?.message} + <div class="text-red-600 text-center"> + {form.message} + </div> +{/if} + <div class="container px-4 mt-20 max-w-xl mx-auto"> {#if amount} <div class="text-center mb-8"> @@ -61,6 +73,7 @@ <input name="payreq" value={payreq} type="hidden" /> <input name="username" value={recipient.username} type="hidden" /> <input name="confirmed" value={form?.confirm} type="hidden" /> + <input name="pin" value={$pin} type="hidden" /> <div class="flex w-full"> {#if amount} diff --git a/src/routes/send/bitcoin/[address]/+page.server.js b/src/routes/send/bitcoin/[address]/+page.server.js index 9b29a6da..642593ab 100644 --- a/src/routes/send/bitcoin/[address]/+page.server.js +++ b/src/routes/send/bitcoin/[address]/+page.server.js @@ -1,11 +1,16 @@ -import { redirect } from '@sveltejs/kit'; +import { invalid, redirect } from '@sveltejs/kit'; import { auth, post } from '$lib/utils'; export const actions = { default: async ({ cookies, request }) => { - let { address, amount } = Object.fromEntries(await request.formData()); - let { tx } = await post('/bitcoin/fee', { address, amount }, auth(cookies)); - await post('/bitcoin/send', { address, tx }, auth(cookies)); + try { + let { address, amount, pin } = Object.fromEntries(await request.formData()); + let { tx } = await post('/bitcoin/fee', { address, amount }, auth(cookies)); + await post('/bitcoin/send', { address, pin, tx }, auth(cookies)); + } catch (e) { + return invalid(400, { message: e.message }); + } + throw redirect(307, '/sent'); } }; diff --git a/src/routes/send/bitcoin/[address]/+page.svelte b/src/routes/send/bitcoin/[address]/+page.svelte index 8c9e72ff..c9023180 100644 --- a/src/routes/send/bitcoin/[address]/+page.svelte +++ b/src/routes/send/bitcoin/[address]/+page.svelte @@ -3,19 +3,33 @@ import { Icon, Numpad, Spinner } from '$comp'; import { page } from '$app/stores'; import { back } from '$lib/utils'; + import { pin } from '$lib/store'; + export let data; + export let form; let { address } = $page.params; let { currency } = data.user; let amount, loading; let submit = () => (loading = true); + $: update(form); + let update = () => { + if (form?.message.includes('pin')) $pin = undefined; + loading = false; + }; </script> <button class="ml-5 md:ml-20 mt-5 md:mt-10 hover:opacity-80" on:click={back}> <Icon icon="arrow-left" style="w-10" /> </button> +{#if form?.message} + <div class="text-red-600 text-center"> + {form.message} + </div> +{/if} + <div class="container px-4 mt-20 max-w-xl mx-auto"> <div class="text-center mb-8"> <h1 class="text-3xl md:text-4xl font-semibold mb-2">Send to</h1> @@ -26,6 +40,8 @@ <form method="POST" use:enhance on:submit={submit}> <input name="address" value={address} type="hidden" /> <input name="amount" value={amount} type="hidden" /> + <input name="pin" value={$pin} type="hidden" /> + <div class="flex w-full"> <button type="submit" diff --git a/src/routes/send/lightning/[payreq]/+page.server.js b/src/routes/send/lightning/[payreq]/+page.server.js index f17d6a60..49ebac1c 100644 --- a/src/routes/send/lightning/[payreq]/+page.server.js +++ b/src/routes/send/lightning/[payreq]/+page.server.js @@ -7,14 +7,20 @@ export async function load({ params }) { export const actions = { default: async ({ cookies, request }) => { - let body = Object.fromEntries(await request.formData()); - let { amount, confirmed } = body; + try { + let body = Object.fromEntries(await request.formData()); + let { amount, confirmed } = body; - if (!confirmed) { - return invalid(403, { amount, confirm: true }); + if (!confirmed) { + return invalid(403, { amount, confirm: true }); + } + + await post('/lightning/send', body, auth(cookies)); + } catch (e) { + if (e.message.includes("unusable")) e.message = "Failed to route payment, try sending a lower amount" + return invalid(400, { message: e.message }); } - await post('/lightning/send', body, auth(cookies)); throw redirect(307, '/sent'); } }; diff --git a/src/routes/send/lightning/[payreq]/+page.svelte b/src/routes/send/lightning/[payreq]/+page.svelte index 973550f6..bda10038 100644 --- a/src/routes/send/lightning/[payreq]/+page.svelte +++ b/src/routes/send/lightning/[payreq]/+page.svelte @@ -3,6 +3,8 @@ import { Icon, Numpad, Spinner } from '$comp'; import { page } from '$app/stores'; import { back, s } from '$lib/utils'; + import { pin } from '$lib/store'; + export let data; export let form; @@ -14,12 +16,23 @@ let loading; let submit = () => (loading = true); + $: update(form); + let update = () => { + if (form?.message.includes('pin')) $pin = undefined; + loading = false; + }; </script> <button class="ml-5 md:ml-20 mt-5 md:mt-10 hover:opacity-80" on:click={back}> <Icon icon="arrow-left" style="w-10" /> </button> +{#if form?.message} + <div class="text-red-600 text-center"> + {form.message} + </div> +{/if} + <div class="container px-4 mt-20 max-w-xl mx-auto"> {#if amount} <div class="text-center mb-8"> @@ -38,6 +51,7 @@ <input name="payreq" value={payreq} type="hidden" /> <input name="amount" value={amount} type="hidden" /> <input name="confirmed" value={form?.confirm} type="hidden" /> + <input name="pin" value={$pin} type="hidden" /> <div class="flex w-full"> <button diff --git a/src/routes/send/user/[username]/[...amount]/+page.server.js b/src/routes/send/user/[username]/[...amount]/+page.server.js index 12bae186..a659eef3 100644 --- a/src/routes/send/user/[username]/[...amount]/+page.server.js +++ b/src/routes/send/user/[username]/[...amount]/+page.server.js @@ -11,14 +11,19 @@ export async function load({ params, parent }) { export const actions = { default: async ({ cookies, request }) => { - let body = Object.fromEntries(await request.formData()); - let { amount, confirmed } = body; + try { + let body = Object.fromEntries(await request.formData()); + let { amount, confirmed } = body; - if (!confirmed) { - return invalid(403, { amount, confirm: true }); + if (!confirmed) { + return invalid(403, { amount, confirm: true }); + } + + await post('/send', body, auth(cookies)); + } catch (e) { + return invalid(400, { message: e.message }); } - await post('/send', body, auth(cookies)); throw redirect(307, '/sent'); } }; diff --git a/src/routes/send/user/[username]/[...amount]/+page.svelte b/src/routes/send/user/[username]/[...amount]/+page.svelte index e50acd5b..6f4cb313 100644 --- a/src/routes/send/user/[username]/[...amount]/+page.svelte +++ b/src/routes/send/user/[username]/[...amount]/+page.svelte @@ -1,10 +1,11 @@ <script> import { goto } from '$app/navigation'; - import { selectedRate } from '$lib/store'; + import { pin, selectedRate } from '$lib/store'; import { enhance } from '$app/forms'; import { Avatar, Icon, Numpad, Spinner } from '$comp'; import { page } from '$app/stores'; import { back, f, s, sats } from '$lib/utils'; + export let data; export let form; @@ -31,12 +32,24 @@ let loading; let submit = () => (loading = true); + + $: update(form); + let update = () => { + if (form?.message.includes('pin')) $pin = undefined; + loading = false; + }; </script> <button class="ml-5 md:ml-20 mt-5 md:mt-10 hover:opacity-80" on:click={handleBack}> <Icon icon="arrow-left" style="w-10" /> </button> +{#if form?.message} + <div class="text-red-600 text-center"> + {form.message} + </div> +{/if} + <div class="container px-4 mt-20 max-w-xl mx-auto"> {#if amount} <div class="text-center mb-8"> @@ -63,6 +76,7 @@ <input name="amount" value={amount} type="hidden" /> <input name="username" value={recipient.username} type="hidden" /> <input name="confirmed" value={form?.confirm} type="hidden" /> + <input name="pin" value={$pin} type="hidden" /> <div class="flex w-full"> {#if amount} |
