From fd137d961392ebd8f6da9f86e57a1d7dfe07eef1 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 20 Dec 2023 14:41:19 -0800 Subject: new on-chain send ui --- bun.lockb | Bin 0 -> 119377 bytes package.json | 26 +--- src/components/Numpad.svelte | 5 +- src/components/Toggle.svelte | 2 +- src/lib/utils.js | 5 + src/locales/en.json | 2 + src/routes/(app)/+layout.svelte | 6 +- .../[username]/payments/[...page]/+page.svelte | 2 +- src/routes/(app)/payment/[id]/+page.svelte | 27 ++-- .../(app)/send/bitcoin/[address]/+page.svelte | 56 +++++++ .../bitcoin/[address]/[...amount]/+page.server.js | 40 ----- .../bitcoin/[address]/[...amount]/+page.svelte | 162 --------------------- .../[amount]/[...feeRate]/+page.server.js | 36 +++++ .../[address]/[amount]/[...feeRate]/+page.svelte | 134 +++++++++++++++++ src/routes/+page.svelte | 2 +- 15 files changed, 269 insertions(+), 236 deletions(-) create mode 100755 bun.lockb create mode 100644 src/routes/(app)/send/bitcoin/[address]/+page.svelte delete mode 100644 src/routes/(app)/send/bitcoin/[address]/[...amount]/+page.server.js delete mode 100644 src/routes/(app)/send/bitcoin/[address]/[...amount]/+page.svelte create mode 100644 src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.server.js create mode 100644 src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 00000000..3216c9fd Binary files /dev/null and b/bun.lockb differ diff --git a/package.json b/package.json index 96741f0a..1a3f9638 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,10 @@ }, "devDependencies": { "@scure/base": "^1.1.1", + "@scure/bip39": "^1.2.1", "@sveltejs/adapter-node": "^2.0.0", "@sveltejs/kit": "^2.0.0", + "@sveltejs/vite-plugin-svelte": "^3.0.0", "@tailwindcss/line-clamp": "^0.4.2", "@zerodevx/svelte-toast": "^0.7.2", "autoprefixer": "^10.4.13", @@ -24,6 +26,7 @@ "html5-qrcode": "^2.3.8", "leaflet": "^1.9.3", "leaflet.markercluster": "^1.5.3", + "maplibre-gl": "^3.3.1", "nostr-tools": "^1.14.2", "postcss": "^8.4.20", "prettier": "2", @@ -34,30 +37,17 @@ "rollup": "^2.79.1", "screenfull": "^6.0.2", "svelte": "^4.0.0", + "svelte-adapter-bun": "^0.5.1", "svelte-outclick": "^3.3.3", "svelte-preprocess": "^5.0.3", "svelte-virtual-scroll-list": "^1.1.0", "sveltekit-i18n": "^2.2.2", "tailwind-scrollbar": "^2.1.0", "tailwindcss": "^3.2.4", + "uint8array-extras": "^1.0.0", + "unique-names-generator": "^4.7.1", "uuid": "^9.0.0", - "vite": "^5.0.0", - "@sveltejs/vite-plugin-svelte": "^3.0.0" - }, - "pnpm": { - "peerDependencyRules": { - "allowedVersions": { - "vite": "4" - } - } + "vite": "^5.0.0" }, - "type": "module", - "dependencies": { - "@faker-js/faker": "^8.2.0", - "@scure/bip39": "^1.2.1", - "maplibre-gl": "^3.3.1", - "svelte-adapter-bun": "^0.5.1", - "uint8array-extras": "^0.5.0", - "unique-names-generator": "^4.7.1" - } + "type": "module" } diff --git a/src/components/Numpad.svelte b/src/components/Numpad.svelte index 7006d7aa..72dad375 100644 --- a/src/components/Numpad.svelte +++ b/src/components/Numpad.svelte @@ -118,6 +118,8 @@ .replace(/\./g, "") .replace("F", "."); + if (!clean) clean = " "; + if (fiat) clean = clean.replace(",", ""); if (clean !== html) { html = clean; @@ -171,8 +173,9 @@ } }; - let keydown = (e) => + let keydown = (e) => { e.key === "Enter" && (e.preventDefault() || submit.click()); + };
diff --git a/src/components/Toggle.svelte b/src/components/Toggle.svelte index 1e4cf4c4..2f92837d 100644 --- a/src/components/Toggle.svelte +++ b/src/components/Toggle.svelte @@ -12,6 +12,6 @@ class="sr-only peer" />
diff --git a/src/lib/utils.js b/src/lib/utils.js index f55b47b6..5303ec35 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -281,3 +281,8 @@ export function shuffleArray(array) { [array[i], array[j]] = [array[j], array[i]]; } } + + export let closest = (a, n) => + a.reduce((prev, curr) => + Math.abs(curr - n) < Math.abs(prev - n) ? curr : prev + ); diff --git a/src/locales/en.json b/src/locales/en.json index ac8b0075..cb42fa78 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -272,6 +272,8 @@ } }, "payments": { + "networkFee": "Network fee", + "ourFee": "Our fee", "create": "Create", "fund": "Fund", "addFunds": "Add Funds", diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index e439d43e..0480fd79 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -18,7 +18,7 @@ import Password from "$comp/Password.svelte"; import Request from "$comp/Request.svelte"; import { warning, protectedRoutes } from "$lib/utils"; - import { t, locale } from "$lib/translations"; + import { t, locale, loading } from "$lib/translations"; import { goto, onNavigate } from "$app/navigation"; export let data; @@ -129,7 +129,9 @@
- + {#if !$loading} + + {/if}
{#if $invoice} diff --git a/src/routes/(app)/[username]/payments/[...page]/+page.svelte b/src/routes/(app)/[username]/payments/[...page]/+page.svelte index 317f776b..1f20ea5c 100644 --- a/src/routes/(app)/[username]/payments/[...page]/+page.svelte +++ b/src/routes/(app)/[username]/payments/[...page]/+page.svelte @@ -238,7 +238,7 @@ {format(new Date(p.created), "h:mm aaa")}
- {format(new Date(p.created), "MMM d")} + {format(new Date(p.created), "MMM d, yyyy")}
diff --git a/src/routes/(app)/payment/[id]/+page.svelte b/src/routes/(app)/payment/[id]/+page.svelte index a1c7bbed..15c17a00 100644 --- a/src/routes/(app)/payment/[id]/+page.svelte +++ b/src/routes/(app)/payment/[id]/+page.svelte @@ -1,5 +1,7 @@ @@ -124,8 +131,8 @@
Date
- {format(new Date(created), "MMMM d")}, - {format(new Date(created), "h:mm aaa")} + {format(new Date(created), "h:mmaaa")} + {format(new Date(created), "MMM d, yyyy")}
@@ -140,8 +147,6 @@ class="flex font-bold hover:opacity-80 mb-auto my-auto" on:click={() => copy(id)} > - - @@ -151,7 +156,8 @@
+ +
+

{$t("payments.send")}

+ +
{address}
+ + + +
+ + +
+ +
+
+
diff --git a/src/routes/(app)/send/bitcoin/[address]/[...amount]/+page.server.js b/src/routes/(app)/send/bitcoin/[address]/[...amount]/+page.server.js deleted file mode 100644 index 2998f22a..00000000 --- a/src/routes/(app)/send/bitcoin/[address]/[...amount]/+page.server.js +++ /dev/null @@ -1,40 +0,0 @@ -import { fail, redirect } from "@sveltejs/kit"; -import { auth, post, fd } from "$lib/utils"; - -let seen = {}; -export const actions = { - default: async ({ cookies, request }) => { - try { - let { - address, - amount, - confirmed, - feeRate, - subtract, - pin, - stale, - ts, - } = await await fd(request); - if (seen[ts]) return fail(400, { message: "Duplicate form submission" }); - - let estimate = await post( - "/bitcoin/fee", - { address, amount, feeRate, subtract }, - auth(cookies) - ); - - let { tx } = estimate; - - if (stale || !confirmed) return fail(400, estimate); - - seen[ts] = 1; - setTimeout(() => delete seen[ts], 30000); - - await post("/bitcoin/send", { pin, subtract, tx }, auth(cookies)); - } catch (e) { - return fail(400, { message: e.message }); - } - - redirect(307, "/sent"); - }, -}; diff --git a/src/routes/(app)/send/bitcoin/[address]/[...amount]/+page.svelte b/src/routes/(app)/send/bitcoin/[address]/[...amount]/+page.svelte deleted file mode 100644 index a8b86718..00000000 --- a/src/routes/(app)/send/bitcoin/[address]/[...amount]/+page.svelte +++ /dev/null @@ -1,162 +0,0 @@ - - - - -{#if form?.message} -
- {form.message} -
-{/if} - -
-

{$t("payments.send")}

- -
{address}
- - {#if confirmed} -
-

- {f(toFiat(amount, rate), currency)} -

-

⚡️{s(amount)}

-
- -
-

with fee

- -
-

- {f(toFiat(fee + ourfee, rate), currency)} -

-

⚡️{s(fee + ourfee)}

- -
-
- {:else} - - {/if} - -
- - - - - - - - - - {#if confirmed && adjusting} -
-
- Slower (~40 blocks) -
-
- Faster (~1 block) -
- -
-
-
- -
- -
- {/if} - -
- {#if !confirmed} - - {/if} - - -
-
-
diff --git a/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.server.js b/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.server.js new file mode 100644 index 00000000..08741296 --- /dev/null +++ b/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.server.js @@ -0,0 +1,36 @@ +import { fail, redirect } from "@sveltejs/kit"; +import { auth, post, fd } from "$lib/utils"; + +let seen = {}; + +export async function load({ params: { address, amount, feeRate }, cookies }) { + try { + let fees = await fetch( + `https://mempool.space/api/v1/fees/recommended` + ).then((r) => r.json()); + + if (!feeRate) feeRate = fees.halfHourFee; + + let { fee, ourfee, hex } = await post( + "/bitcoin/fee", + { address, amount, feeRate: feeRate }, + auth(cookies) + ); + + return { amount, address, fee, fees, feeRate, ourfee, hex }; + } catch (e) { + throw redirect(307, `/send/bitcoin/${address}`); + } +} + +export const actions = { + default: async ({ cookies, request }) => { + try { + let r = await post("/bitcoin/send", await fd(request), auth(cookies)); + } catch (e) { + return fail(400, { message: e.message }); + } + + redirect(307, "/sent"); + }, +}; diff --git a/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte b/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte new file mode 100644 index 00000000..d583024c --- /dev/null +++ b/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte @@ -0,0 +1,134 @@ + + + + +
+ {#if form?.message} +
+
{form.message}
+
+ {/if} + +

{$t("payments.send")}

+ +
{address}
+ +
+

+ {f(toFiat(amount, $rate), currency)} +

+

⚡️{s(amount)}

+
+ +
+

{$t("payments.networkFee")}

+ +
+ +
+

+ {f(toFiat(fee, $rate), currency)} +

+

⚡️{s(fee)}

+
+
+
+ +
+

{$t("payments.ourFee")}

+ +
+
+

+ {f(toFiat(ourfee, $rate), currency)} +

+

⚡️{s(ourfee)}

+
+
+
+ +
(submitting = true)}> + + + + +
+ +
+
+
+ + diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 3cffea21..23aaacfa 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,4 +1,4 @@ -