diff options
| author | Adam Soltys <[email protected]> | 2024-08-18 13:09:41 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2024-08-18 22:15:05 -0700 |
| commit | d66cba2d111bec3a2bd57a56233577f3fd417b18 (patch) | |
| tree | 5cf0250363d11fb33414d8cae4f583e186247123 /src/routes/(app)/send | |
| parent | 09d4867fe0ddc8cbc7bfa670911fe5c33a0a4f36 (diff) | |
| download | coinos-ui-d66cba2d111bec3a2bd57a56233577f3fd417b18.tar.gz coinos-ui-d66cba2d111bec3a2bd57a56233577f3fd417b18.zip | |
ecash
Diffstat (limited to 'src/routes/(app)/send')
| -rw-r--r-- | src/routes/(app)/send/[...text]/+page.server.js | 91 | ||||
| -rw-r--r-- | src/routes/(app)/send/[...text]/+page.svelte | 34 | ||||
| -rw-r--r-- | src/routes/(app)/send/ecash/+page.server.js | 19 | ||||
| -rw-r--r-- | src/routes/(app)/send/ecash/+page.svelte | 60 |
4 files changed, 110 insertions, 94 deletions
diff --git a/src/routes/(app)/send/[...text]/+page.server.js b/src/routes/(app)/send/[...text]/+page.server.js index 3e8623eb..c1ba5945 100644 --- a/src/routes/(app)/send/[...text]/+page.server.js +++ b/src/routes/(app)/send/[...text]/+page.server.js @@ -1,98 +1,19 @@ -import { validate } from "bitcoin-address-validation"; -import bip21 from "bip21"; -import { auth, get, isLiquid, post } from "$lib/utils"; +import { auth, get } from "$lib/utils"; import { fail, redirect } from "@sveltejs/kit"; -import { PUBLIC_DOMAIN } from "$env/static/public"; - -let parse = async (t, host) => { - if (!t) return; - - if (t.startsWith("http")) redirect(307, t); - if (t.startsWith(host)) redirect(307, `http://${t}`); - - let amount, user, id; - - t = t.trim(); - t.toLowerCase().startsWith("bitcoin:") && - ({ - address: t, - options: { amount }, - } = bip21.decode(t)); - - if (t.startsWith("lightning:")) t = t.replace("lightning:", ""); - if (t.endsWith(`@${PUBLIC_DOMAIN}`)) t = t.split("@")[0]; - if (t.includes("@") && t.includes(".")) { - try { - t = await get(`/encode?address=${t}`); - } catch (e) {} - } - - if (t.includes("/fund")) redirect(307, t.substring(t.indexOf("/fund"))); - - // lightning - if (t.toLowerCase().startsWith("lightning:")) - t = t.toLowerCase().replace("lightning:", ""); - if (t.toLowerCase().startsWith("lnurl")) redirect(307, `/ln/${t}`); - if (t.includes(":")) t = t.split(":")[1]; - - if (t.toLowerCase().startsWith("ln")) { - try { - ({ id } = await get(`/invoice/${t}`)); - } catch (e) { - redirect(307, `/send/lightning/${t}`); - } - } - - // bitcoin - if (validate(t) || isLiquid(t)) { - try { - ({ id, user } = await get(`/invoice/${t}`)); - } catch (e) { - let r = `/send/bitcoin/${t}`; - if (amount) r += "/" + amount; - redirect(307, r); - } - - if (user) redirect(307, `/pay/${user.username}`); - else if (id) redirect(307, `/send/${id}`); - } - - // user - try { - user = await get(`/users/${t.split("/")[0]}`); - if (user.anon) user = null; - } catch (e) {} - - if (user) redirect(307, `/pay/${t}`); - - let fund; - try { - fund = await get(`/fund/${t}`); - } catch (e) {} - - if (fund) redirect(307, `/send/fund/${t}`); - - // invoice - let invoice; - try { - invoice = await get(`/invoice/${t}`); - } catch (e) {} - - if (invoice) redirect(307, `/send/invoice/${invoice.id}`); -}; +import parse from "$lib/parse"; export async function load({ cookies, params, request, url }) { let { text } = params; - await parse(text, url.host); + await parse(text, url.host, cookies); let contacts = await get("/contacts", auth(cookies)); return { contacts }; } export const actions = { - default: async ({ request, url }) => { + default: async ({ cookies, request, url }) => { const form = await request.formData(); let t = form.get("text"); - await parse(t, url.host); - return fail(400, { error: true }); + let msg = await parse(t, url.host, cookies); + return fail(400, { error: msg || "default" }); }, }; diff --git a/src/routes/(app)/send/[...text]/+page.svelte b/src/routes/(app)/send/[...text]/+page.svelte index f9267105..e677760f 100644 --- a/src/routes/(app)/send/[...text]/+page.svelte +++ b/src/routes/(app)/send/[...text]/+page.svelte @@ -16,15 +16,17 @@ data.subject = data.user; let { contacts } = data; - let w; - let el, text; + let el, text, pasted, w; let keypress = (e) => e.key === "Enter" && (e.preventDefault() || el.click()); let paste = async () => { text = await navigator.clipboard.readText(); + pasted = true; }; + + $: if (browser && pasted && text) el.click() && (pasted = false); </script> <svelte:window bind:innerWidth={w} /> @@ -39,7 +41,9 @@ {#if form?.error} <div class="mb-5"> <div class="text-red-600"> - {$t("error.unrecognizedInput")} + {form.error === "default" + ? $t("error.unrecognizedInput") + : form.error} </div> </div> {/if} @@ -52,6 +56,7 @@ on:keypress={keypress} class="w-full p-4 border rounded-xl h-48 text-xl" bind:value={text} + on:paste={() => (pasted = true)} autocapitalize="none" /> </div> @@ -60,19 +65,19 @@ <a href="/scan" class="w-full"> <button type="button" - class="flex border rounded-2xl px-6 py-5 font-bold hover:opacity-80 w-full bg-primary justify-center" + class="flex border rounded-2xl px-6 py-5 font-bold hover:opacity-80 w-full bg-primary justify-center gap-2" > - <Icon icon="camera" style="mr-2 w-6 my-auto" /> + <Icon icon="camera" style="w-8 my-auto" /> <div class="my-auto">{$t("user.send.scan")}</div> </button> </a> <button type="button" - class="flex border rounded-2xl px-6 py-5 font-bold hover:opacity-80 w-full bg-primary justify-center" + class="flex border rounded-2xl px-6 py-5 font-bold hover:opacity-80 w-full bg-primary justify-center gap-2" on:click={paste} > - <Icon icon="paste" style="mr-2 w-6 my-auto" /> + <Icon icon="paste" style="w-8 my-auto" /> <div class="my-auto">{$t("user.send.paste")}</div> </button> </div> @@ -80,12 +85,23 @@ <button bind:this={el} type="submit" - class="bg-black text-white border rounded-2xl px-6 py-5 w-full font-bold" + class="flex bg-black text-white border rounded-2xl px-6 py-5 w-full font-bold gap-2 justify-center" > - {$t("user.send.next")} + <Icon icon="send" style="w-8 my-auto invert" /> + <div class="my-auto">{$t("user.send.next")}</div> </button> </form> + <a href="/send/ecash"> + <button + type="button" + class="flex border rounded-2xl px-6 py-5 w-full font-bold gap-2 justify-center text-xl" + > + <Icon icon="voucher" style="w-8 my-auto" /> + <div class="my-auto">{$t("payments.createEcash")}</div> + </button> + </a> + {#if contacts.length} <div class="space-y-5"> <h1 class="px-3 md:px-0 text-2xl font-semibold mt-10"> diff --git a/src/routes/(app)/send/ecash/+page.server.js b/src/routes/(app)/send/ecash/+page.server.js new file mode 100644 index 00000000..2fb43a2f --- /dev/null +++ b/src/routes/(app)/send/ecash/+page.server.js @@ -0,0 +1,19 @@ +import { fail, redirect } from "@sveltejs/kit"; +import { auth, post, fd } from "$lib/utils"; + +export const actions = { + default: async ({ cookies, request }) => { + let token; + try { + let body = await fd(request); + ({ token } = await post("/mint", body, auth(cookies))); + } catch (e) { + console.log("problem creating ecash", e); + return fail(400, { message: e.message }); + } + + cookies.set("ecash", token, { path: "/" }); + + redirect(307, `/${cookies.get("username")}/ecash`); + }, +}; diff --git a/src/routes/(app)/send/ecash/+page.svelte b/src/routes/(app)/send/ecash/+page.svelte new file mode 100644 index 00000000..d8e2dd46 --- /dev/null +++ b/src/routes/(app)/send/ecash/+page.svelte @@ -0,0 +1,60 @@ +<script> + import { enhance } from "$app/forms"; + import { t } from "$lib/translations"; + import Icon from "$comp/Icon.svelte"; + import Numpad from "$comp/Numpad.svelte"; + import { page } from "$app/stores"; + import { rate } from "$lib/store"; + import { fail, s } from "$lib/utils"; + + export let data; + + let { rates, user } = data; + let { balance, currency, username } = user; + + let amount = 0; + let submit, fiat; + + $: update(data); + let update = () => ($rate = data.rates[currency]); + + let setMax = () => { + fiat = false; + amount = balance; + }; +</script> + +<a href="/send"> + <button type="button" class="ml-5 md:ml-20 mt-5 md:mt-10 hover:opacity-80"> + <Icon icon="arrow-left" style="w-10" /> + </button> +</a> + +<div class="container px-4 max-w-xl mx-auto space-y-5 text-center"> + <h1 class="text-3xl md:text-4xl font-semibold mb-2"> + {$t("payments.createEcash")} + </h1> + + <form use:enhance method="POST"> + <Numpad bind:amount bind:fiat {currency} {submit} bind:rate={$rate} /> + <input type="hidden" name="amount" bind:value={amount}/> + + <div class="flex justify-center gap-2"> + <button + type="button" + class="hover:opacity-80 bg-black text-white rounded-2xl py-3 px-4 mt-2 border font-bold" + on:click|preventDefault={setMax} + on:keydown={setMax}>Max ⚡️{s(balance)}</button + > + + <button + use:focus + bind:this={submit} + type="submit" + class="opacity-100 hover:opacity-80 rounded-2xl border py-3 font-bold mt-2 bg-black text-white px-4 w-24" + > + {$t("payments.next")} + </button> + </div> + </form> +</div> |
