aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-03-03 22:45:50 -0800
committerAdam Soltys <[email protected]>2026-03-03 22:45:50 -0800
commit1e9ed8fa128ec5ae038be14ef168cad37c1c0eb1 (patch)
tree29399a82df3f981a24ef6cc84562c8ee006738d7 /src
parente66a08d18f2bef2eccfe84042a2674141a73d1c2 (diff)
downloadcoinos-ui-1e9ed8fa128ec5ae038be14ef168cad37c1c0eb1.tar.gz
coinos-ui-1e9ed8fa128ec5ae038be14ef168cad37c1c0eb1.zip
api proxy
Diffstat (limited to 'src')
-rw-r--r--src/components/AppForm.svelte2
-rw-r--r--src/components/Event.svelte6
-rw-r--r--src/components/Numpad.svelte44
-rw-r--r--src/components/Password.svelte2
-rw-r--r--src/components/Pin.svelte2
-rw-r--r--src/lib/ark.ts8
-rw-r--r--src/lib/bitcoinSync.ts2
-rw-r--r--src/lib/keyWrapping.ts2
-rw-r--r--src/lib/nostr.ts2
-rw-r--r--src/routes/(app)/+layout.svelte4
-rw-r--r--src/routes/(app)/[username]/(profile)/+page.svelte10
-rw-r--r--src/routes/(app)/account/+server.ts21
-rw-r--r--src/routes/(app)/account/[id]/+page.svelte4
-rw-r--r--src/routes/(app)/account/ark/+page.svelte2
-rw-r--r--src/routes/(app)/account/new/+page.svelte2
-rw-r--r--src/routes/(app)/account/pass/+page.svelte10
-rw-r--r--src/routes/(app)/account/seed/+page.svelte10
-rw-r--r--src/routes/(app)/api/[...path]/+server.ts (renamed from src/routes/(app)/post/[...path]/+server.ts)17
-rw-r--r--src/routes/(app)/contacts/+server.ts12
-rw-r--r--src/routes/(app)/disable2fa/+server.ts13
-rw-r--r--src/routes/(app)/ecash/mint/+server.ts7
-rw-r--r--src/routes/(app)/email/+server.ts7
-rw-r--r--src/routes/(app)/enable2fa/+server.ts8
-rw-r--r--src/routes/(app)/events/+server.ts12
-rw-r--r--src/routes/(app)/firehose/+page.svelte2
-rw-r--r--src/routes/(app)/fund/[id]/access/+page.svelte2
-rw-r--r--src/routes/(app)/fund/[id]/withdraw/+server.ts6
-rw-r--r--src/routes/(app)/invoice/+server.ts12
-rw-r--r--src/routes/(app)/password/+server.ts7
-rw-r--r--src/routes/(app)/payment/[id]/+page.svelte10
-rw-r--r--src/routes/(app)/payment/[id]/print/+server.ts7
-rw-r--r--src/routes/(app)/pin/+server.ts7
-rw-r--r--src/routes/(app)/reset/+server.ts7
-rw-r--r--src/routes/(app)/send/[...text]/+page.svelte14
-rw-r--r--src/routes/(app)/send/ark/[address]/[amount]/[...feeRate]/+page.svelte2
-rw-r--r--src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte104
-rw-r--r--src/routes/(app)/send/invoice/[id]/+page.svelte4
-rw-r--r--src/routes/(app)/send/lightning/[payreq]/[...memo]/+page.svelte2
-rw-r--r--src/routes/(app)/send/zap/[id]/[...amount]/+page.svelte4
-rw-r--r--src/routes/(app)/settings/+layout.svelte2
-rw-r--r--src/routes/(app)/settings/account/+page.svelte2
-rw-r--r--src/routes/(app)/settings/security/+page.svelte4
-rw-r--r--src/routes/(app)/subscription/+server.ts8
-rw-r--r--src/routes/(app)/subscription/delete/+server.ts8
-rw-r--r--src/routes/(app)/tag/[tag]/+page.svelte2
-rw-r--r--src/routes/(app)/withdraw/+server.ts10
-rw-r--r--src/routes/(static)/register/auth/+page.svelte4
-rw-r--r--src/routes/(static)/support/+page.svelte4
48 files changed, 160 insertions, 283 deletions
diff --git a/src/components/AppForm.svelte b/src/components/AppForm.svelte
index 86338a11..295fd6b6 100644
--- a/src/components/AppForm.svelte
+++ b/src/components/AppForm.svelte
@@ -57,7 +57,7 @@
let del = async () => {
try {
- await post(`/post/apps/delete`, { pubkey });
+ await post(`/api/apps/delete`, { pubkey });
goto("/settings/nostr");
} catch (e: any) {
fail(e.message);
diff --git a/src/components/Event.svelte b/src/components/Event.svelte
index c08bd452..eef48868 100644
--- a/src/components/Event.svelte
+++ b/src/components/Event.svelte
@@ -21,11 +21,11 @@
const body = new FormData();
if (!user) return goto(`/register?redirect=${$page.url.pathname}`);
- let request = await post("/post/zapRequest", { amount, id });
- let { pr: payreq } = await post("/post/zap", {
+ let request = await post("/api/zapRequest", { amount, id });
+ let { pr: payreq } = await post("/api/zap", {
event: await sign(request),
});
- await post("/post/payments", { amount, payreq });
+ await post("/api/payments", { amount, payreq });
} catch (e: any) {
console.log(e);
fail(e.message);
diff --git a/src/components/Numpad.svelte b/src/components/Numpad.svelte
index eee43621..10f5d8f3 100644
--- a/src/components/Numpad.svelte
+++ b/src/components/Numpad.svelte
@@ -255,12 +255,19 @@
<div class="space-y-5 w-full">
<div class="text-center">
<div class="text-5xl md:text-6xl font-semibold tracking-widest flex justify-center">
- <div class="my-auto" class:text-5xl={!fiat}>
- <span class:hidden={!fiat}>
+ <button
+ type="button"
+ class="my-auto cursor-pointer select-none"
+ class:text-5xl={!fiat}
+ aria-label="Swap currency display"
+ onclick={(e) => { e.preventDefault(); e.stopPropagation(); swap(); }}
+ >
+ {#if fiat}
{#if position === "before"}{symbol}{/if}
- </span>
- <PhLightningFill width="48" class="text-yellow-300" />
- </div>
+ {:else}
+ <PhLightningFill width="48" class="text-yellow-300" />
+ {/if}
+ </button>
<!-- contenteditable input -->
<div
@@ -287,26 +294,15 @@
bind:this={element}
></div>
- {#if fiat && position === "after"}{symbol}{/if}
+ {#if fiat && position === "after"}
+ <button
+ type="button"
+ class="cursor-pointer select-none"
+ aria-label="Swap currency display"
+ onclick={(e) => { e.preventDefault(); e.stopPropagation(); swap(); }}
+ >{symbol}</button>
+ {/if}
</div>
-
- <!-- swap button -->
- <button
- type="button"
- class="flex items-center justify-center text-2xl cursor-pointer mx-auto select-none"
- aria-label="Swap currency display"
- onclick={(e) => {
- e.preventDefault();
- e.stopPropagation();
- swap();
- }}
- >
- <span class="flex items-center" class:hidden={!fiat}>
- <PhLightningFill width="48" class="text-yellow-300" />
- {s(amount, locale)}
- </span>
- <span class:hidden={fiat}>{f(amountFiat, currency, locale)}</span>
- </button>
</div>
<div class="grid grid-cols-3 gap-2 w-full mx-auto">
diff --git a/src/components/Password.svelte b/src/components/Password.svelte
index ab1b7d9d..7651d5a1 100644
--- a/src/components/Password.svelte
+++ b/src/components/Password.svelte
@@ -13,7 +13,7 @@
let submit = async (e) => {
e.preventDefault();
try {
- let res = await post("/password", { password });
+ let res = await post("/api/password", { password });
$passwordPrompt = false;
$pw = password;
} catch (e) {
diff --git a/src/components/Pin.svelte b/src/components/Pin.svelte
index da0c6aeb..c8ead368 100644
--- a/src/components/Pin.svelte
+++ b/src/components/Pin.svelte
@@ -27,7 +27,7 @@
if (p?.length !== 6) return;
let result;
try {
- result = await post("/pin", { pin: hashPin(p) });
+ result = await post("/api/pin", { pin: hashPin(p) });
} catch (e) {
console.log("Pin check failed", e);
}
diff --git a/src/lib/ark.ts b/src/lib/ark.ts
index 18652d1e..e223d013 100644
--- a/src/lib/ark.ts
+++ b/src/lib/ark.ts
@@ -303,7 +303,7 @@ const _syncTransactions = async (aid: string) => {
const bal = await wallet.getBalance();
const balance = (bal.available || 0) + (bal.preconfirmed || 0);
- const result = await post("/post/ark/sync", { transactions, aid, balance, arkAddress: walletAddr });
+ const result = await post("/api/ark/sync", { transactions, aid, balance, arkAddress: walletAddr });
cacheVaultSnapshot(); // fire-and-forget
return result;
};
@@ -456,14 +456,14 @@ export const sendArkViaForward = async ({
try {
const txid = await sendArk(serverArkAddress, amount);
- await post("/post/ark/vault-send", { hash: txid, amount, aid });
+ await post("/api/ark/vault-send", { hash: txid, amount, aid });
const invoice: any = { type: "ark", amount, aid };
if (forward) invoice.forward = forward;
- const inv = await post("/post/invoice", { invoice, user });
+ const inv = await post("/api/invoice", { invoice, user });
- return await post("/post/ark/receive", { amount, hash: txid, iid: inv.id });
+ return await post("/api/ark/receive", { amount, hash: txid, iid: inv.id });
} finally {
vaultForwarding = false;
}
diff --git a/src/lib/bitcoinSync.ts b/src/lib/bitcoinSync.ts
index 9061e2fc..92d3382b 100644
--- a/src/lib/bitcoinSync.ts
+++ b/src/lib/bitcoinSync.ts
@@ -6,7 +6,7 @@ export const syncBitcoinVault = async (aid: string) => {
if (syncing) return;
syncing = true;
try {
- return await post("/post/bitcoin/sync", { aid });
+ return await post("/api/bitcoin/sync", { aid });
} finally {
syncing = false;
}
diff --git a/src/lib/keyWrapping.ts b/src/lib/keyWrapping.ts
index b176e741..fb46f767 100644
--- a/src/lib/keyWrapping.ts
+++ b/src/lib/keyWrapping.ts
@@ -45,7 +45,7 @@ export async function resolveCanonicalKey(
export async function saveEncryptedKeys(
encryptedKeys: Record<string, string>,
): Promise<void> {
- await post("/post/user", { encryptedKeys });
+ await post("/api/user", { encryptedKeys });
}
export function passwordMethodId(): string {
diff --git a/src/lib/nostr.ts b/src/lib/nostr.ts
index 1bbf6bcc..4b7316e8 100644
--- a/src/lib/nostr.ts
+++ b/src/lib/nostr.ts
@@ -136,7 +136,7 @@ export const sign = async (event: any, user?: any) => {
};
export const send = (event: EventTemplate) => {
- return post("/events", { event });
+ return post("/api/event", { event });
};
const getPassword = async (): Promise<string> => {
diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte
index f4d036f2..248206fb 100644
--- a/src/routes/(app)/+layout.svelte
+++ b/src/routes/(app)/+layout.svelte
@@ -104,8 +104,8 @@
try {
const { serverArkAddress, amount, iid } = result.forward;
const txid = await sendArk(serverArkAddress, amount);
- await post("/post/ark/vault-send", { hash: txid, amount, aid });
- await post("/post/ark/receive", { amount, hash: txid, iid });
+ await post("/api/ark/vault-send", { hash: txid, amount, aid });
+ await post("/api/ark/receive", { amount, hash: txid, iid });
} catch (e) {
console.error("Ark custodial forward failed:", e);
} finally {
diff --git a/src/routes/(app)/[username]/(profile)/+page.svelte b/src/routes/(app)/[username]/(profile)/+page.svelte
index 2eb424e1..4ed8eaaf 100644
--- a/src/routes/(app)/[username]/(profile)/+page.svelte
+++ b/src/routes/(app)/[username]/(profile)/+page.svelte
@@ -46,15 +46,19 @@
const mn = entropyToMnemonic(entropy, wordlist);
const seed = await mnemonicToSeed(mn);
const master = HDKey.fromMasterSeed(seed, versions);
- const child = master.derive("m/84'/0'/0'");
+ const existing = await fetch("/api/accounts").then((r) => r.json());
+ const nextIdx = existing
+ .filter((a: any) => a.pubkey && a.fingerprint)
+ .reduce((max: number, a: any) => Math.max(max, (a.accountIndex ?? 0) + 1), 0);
+ const child = master.derive(`m/84'/0'/${nextIdx}'`);
const pubkey = child.publicExtendedKey;
const fingerprint = child.fingerprint.toString(16).padStart(8, "0");
- await post("/account", {
+ await post("/api/accounts", {
fingerprint,
pubkey,
name: $t("accounts.vault"),
type: "bitcoin",
- accountIndex: 0,
+ accountIndex: nextIdx,
});
invalidate("app:payments");
} catch (e: any) {
diff --git a/src/routes/(app)/account/+server.ts b/src/routes/(app)/account/+server.ts
deleted file mode 100644
index 4387373e..00000000
--- a/src/routes/(app)/account/+server.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { auth, get, post } from "$lib/utils";
-import { error, json } from "@sveltejs/kit";
-
-export async function GET({ cookies }) {
- try {
- return json(await get("/accounts", auth(cookies)));
- } catch (e: any) {
- console.log(e);
- error(500, e.message);
- }
-}
-
-export async function POST({ cookies, request }) {
- try {
- const body = await request.json();
- return json(await post("/accounts", body, auth(cookies)));
- } catch (e: any) {
- console.log(e);
- error(500, e.message);
- }
-}
diff --git a/src/routes/(app)/account/[id]/+page.svelte b/src/routes/(app)/account/[id]/+page.svelte
index bb0251db..582fe3ec 100644
--- a/src/routes/(app)/account/[id]/+page.svelte
+++ b/src/routes/(app)/account/[id]/+page.svelte
@@ -111,7 +111,7 @@
let pubkey = child.publicExtendedKey;
let fp = child.fingerprint.toString(16).padStart(8, "0");
- await post(`/post/account/${id}`, {
+ await post(`/api/account/${id}`, {
fingerprint: fp,
pubkey,
seed,
@@ -131,7 +131,7 @@
let del = async () => {
try {
- await post("/post/account/delete", { id });
+ await post("/api/account/delete", { id });
goto(`/${user.username}`);
} catch (e: any) {
fail(e.message);
diff --git a/src/routes/(app)/account/ark/+page.svelte b/src/routes/(app)/account/ark/+page.svelte
index 3d200070..65d03aad 100644
--- a/src/routes/(app)/account/ark/+page.svelte
+++ b/src/routes/(app)/account/ark/+page.svelte
@@ -42,7 +42,7 @@
const identity = SingleKey.fromHex(arkHex);
const wallet = await Wallet.create({ identity, arkServerUrl });
arkAddress = await wallet.getAddress();
- await post("/account", { name, type, arkAddress });
+ await post("/api/accounts", { name, type, arkAddress });
goto(`/${user.username}`);
} catch (e: any) {
console.log("Ark account creation failed", e);
diff --git a/src/routes/(app)/account/new/+page.svelte b/src/routes/(app)/account/new/+page.svelte
index da9b4c72..1761f3f6 100644
--- a/src/routes/(app)/account/new/+page.svelte
+++ b/src/routes/(app)/account/new/+page.svelte
@@ -37,7 +37,7 @@
const wallet = await Wallet.create({ identity, arkServerUrl });
const arkAddress = await wallet.getAddress();
- await post("/account", { name: $t("accounts.savings"), type: "ark", arkAddress });
+ await post("/api/accounts", { name: $t("accounts.savings"), type: "ark", arkAddress });
goto(`/${user.username}`);
} catch (e: any) {
console.log("Ark account creation failed", e);
diff --git a/src/routes/(app)/account/pass/+page.svelte b/src/routes/(app)/account/pass/+page.svelte
index c7f6c0ab..a76494c0 100644
--- a/src/routes/(app)/account/pass/+page.svelte
+++ b/src/routes/(app)/account/pass/+page.svelte
@@ -41,15 +41,19 @@
await mnemonicToSeed(mn),
versions,
);
- const child = master.derive("m/84'/0'/0'");
+ const accounts = await fetch("/api/accounts").then((r) => r.json());
+ const nextIdx = (accounts || [])
+ .filter((a: any) => a.pubkey && a.fingerprint && a.type !== "ark")
+ .reduce((max: number, a: any) => Math.max(max, (a.accountIndex ?? 0) + 1), 0);
+ const child = master.derive(`m/84'/0'/${nextIdx}'`);
const pubkey = child.publicExtendedKey;
const fingerprint = child.fingerprint.toString(16).padStart(8, "0");
- await post("/account", {
+ await post("/api/accounts", {
fingerprint,
pubkey,
name: $t("accounts.vault"),
type: "bitcoin",
- accountIndex: 0,
+ accountIndex: nextIdx,
});
$mnemonic = "";
diff --git a/src/routes/(app)/account/seed/+page.svelte b/src/routes/(app)/account/seed/+page.svelte
index 342852ca..70f3fe32 100644
--- a/src/routes/(app)/account/seed/+page.svelte
+++ b/src/routes/(app)/account/seed/+page.svelte
@@ -27,15 +27,19 @@
const mn = entropyToMnemonic(entropy, wordlist);
const seed = await mnemonicToSeed(mn);
const master = HDKey.fromMasterSeed(seed, versions);
- const child = master.derive("m/84'/0'/0'");
+ const accounts = await fetch("/api/accounts").then((r) => r.json());
+ const nextIdx = (accounts || [])
+ .filter((a: any) => a.pubkey && a.fingerprint && a.type !== "ark")
+ .reduce((max: number, a: any) => Math.max(max, (a.accountIndex ?? 0) + 1), 0);
+ const child = master.derive(`m/84'/0'/${nextIdx}'`);
const pubkey = child.publicExtendedKey;
const fingerprint = child.fingerprint.toString(16).padStart(8, "0");
- await post("/account", {
+ await post("/api/accounts", {
fingerprint,
pubkey,
name: $t("accounts.vault"),
type: "bitcoin",
- accountIndex: 0,
+ accountIndex: nextIdx,
});
await goto(`/${user.username}`);
} catch (e: any) {
diff --git a/src/routes/(app)/post/[...path]/+server.ts b/src/routes/(app)/api/[...path]/+server.ts
index 2c3e6d18..bc12494f 100644
--- a/src/routes/(app)/post/[...path]/+server.ts
+++ b/src/routes/(app)/api/[...path]/+server.ts
@@ -1,20 +1,25 @@
import { PUBLIC_COINOS_URL as base } from "$env/static/public";
import { auth } from "$lib/utils";
-export async function POST({ cookies, fetch, params, request }) {
- const { path } = params;
- const headers: Record<string, string> = { "Content-Type": "application/json" };
-
+function getHeaders(cookies, request) {
+ const headers: Record<string, string> = {};
const authHeader = request.headers.get("authorization");
if (authHeader) {
headers.authorization = authHeader;
} else {
Object.assign(headers, auth(cookies));
}
+ return headers;
+}
- return fetch(`${base}/${path}`, {
+export async function GET({ cookies, fetch, params, request }) {
+ return fetch(`${base}/${params.path}`, { headers: getHeaders(cookies, request) });
+}
+
+export async function POST({ cookies, fetch, params, request }) {
+ return fetch(`${base}/${params.path}`, {
method: "POST",
body: JSON.stringify(await request.json()),
- headers,
+ headers: { "Content-Type": "application/json", ...getHeaders(cookies, request) },
});
}
diff --git a/src/routes/(app)/contacts/+server.ts b/src/routes/(app)/contacts/+server.ts
deleted file mode 100644
index 2bc5d28e..00000000
--- a/src/routes/(app)/contacts/+server.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { auth, get } from "$lib/utils";
-import { json } from "@sveltejs/kit";
-
-export async function GET({ cookies }) {
- try {
- const contacts = await get("/contacts", auth(cookies));
- return json(contacts);
- } catch (e) {
- console.log(e);
- return json({});
- }
-}
diff --git a/src/routes/(app)/disable2fa/+server.ts b/src/routes/(app)/disable2fa/+server.ts
deleted file mode 100644
index 0d1c4573..00000000
--- a/src/routes/(app)/disable2fa/+server.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { error, json } from "@sveltejs/kit";
-import { auth, post } from "$lib/utils";
-
-export async function POST({ cookies, request }) {
- try {
- const body = await request.json();
- const res = await post("/disable2fa", body, auth(cookies));
-
- return json(res);
- } catch {
- error(500, "Problem disabling 2fa");
- }
-}
diff --git a/src/routes/(app)/ecash/mint/+server.ts b/src/routes/(app)/ecash/mint/+server.ts
deleted file mode 100644
index e933208e..00000000
--- a/src/routes/(app)/ecash/mint/+server.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { auth, post } from "$lib/utils";
-import { json } from "@sveltejs/kit";
-
-export async function POST({ cookies, request }) {
- const result = await post("/mint", await request.json(), auth(cookies));
- return json(result);
-}
diff --git a/src/routes/(app)/email/+server.ts b/src/routes/(app)/email/+server.ts
deleted file mode 100644
index 437c0ef0..00000000
--- a/src/routes/(app)/email/+server.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { auth, post } from "$lib/utils";
-import { json } from "@sveltejs/kit";
-
-export async function POST({ cookies, request }) {
- const result = await post("/request", await request.json(), auth(cookies));
- return json(result);
-}
diff --git a/src/routes/(app)/enable2fa/+server.ts b/src/routes/(app)/enable2fa/+server.ts
deleted file mode 100644
index 76737968..00000000
--- a/src/routes/(app)/enable2fa/+server.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { auth, post } from "$lib/utils";
-
-export async function POST({ cookies, request }) {
- const body = await request.json();
- const res = await post("/2fa", body, auth(cookies));
-
- return new Response(JSON.stringify(res));
-}
diff --git a/src/routes/(app)/events/+server.ts b/src/routes/(app)/events/+server.ts
deleted file mode 100644
index e2553753..00000000
--- a/src/routes/(app)/events/+server.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { auth, post } from "$lib/utils";
-import { error, json } from "@sveltejs/kit";
-
-export async function POST({ cookies, request }) {
- const body = await request.json();
- try {
- const result = await post("/event", body, auth(cookies));
- return json(result);
- } catch (e: any) {
- error(500, e.message);
- }
-}
diff --git a/src/routes/(app)/firehose/+page.svelte b/src/routes/(app)/firehose/+page.svelte
index b2a2cab4..2a5e8fa6 100644
--- a/src/routes/(app)/firehose/+page.svelte
+++ b/src/routes/(app)/firehose/+page.svelte
@@ -23,7 +23,7 @@
const subscription = relay.subscribe([{ kinds: [1], limit: 20 }], {
async onevent(event: any) {
if (paused) return;
- const { parts, names } = await post("/post/parseEvent", { event });
+ const { parts, names } = await post("/api/parseEvent", { event });
event.author = await get(`/api/users/${event.pubkey}`);
event.parts = parts;
event.names = names;
diff --git a/src/routes/(app)/fund/[id]/access/+page.svelte b/src/routes/(app)/fund/[id]/access/+page.svelte
index d2d10ff0..3c9f6410 100644
--- a/src/routes/(app)/fund/[id]/access/+page.svelte
+++ b/src/routes/(app)/fund/[id]/access/+page.svelte
@@ -15,7 +15,7 @@
let del = async (e, user) => {
e.preventDefault();
try {
- m = await post(`/post/fund/${id}/managers/delete`, {
+ m = await post(`/api/fund/${id}/managers/delete`, {
id: user.id,
});
} catch (e: any) {
diff --git a/src/routes/(app)/fund/[id]/withdraw/+server.ts b/src/routes/(app)/fund/[id]/withdraw/+server.ts
deleted file mode 100644
index 96d66413..00000000
--- a/src/routes/(app)/fund/[id]/withdraw/+server.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { json } from "@sveltejs/kit";
-import { auth, post } from "$lib/utils";
-
-export async function POST({ cookies, request }) {
- return json(await post("/take", await request.json(), auth(cookies)));
-}
diff --git a/src/routes/(app)/invoice/+server.ts b/src/routes/(app)/invoice/+server.ts
deleted file mode 100644
index b18eae15..00000000
--- a/src/routes/(app)/invoice/+server.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { auth, post } from "$lib/utils";
-import { error, json } from "@sveltejs/kit";
-
-export const POST = async ({ cookies, request }) => {
- try {
- const body = await request.json();
- return json(await post("/invoice", body, auth(cookies)));
- } catch (e) {
- const { message } = e as Error;
- error(500, message);
- }
-};
diff --git a/src/routes/(app)/password/+server.ts b/src/routes/(app)/password/+server.ts
deleted file mode 100644
index 250dcfed..00000000
--- a/src/routes/(app)/password/+server.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { json } from "@sveltejs/kit";
-import { auth, post } from "$lib/utils";
-
-export async function POST({ cookies, request }) {
- const result = await post("/password", await request.json(), auth(cookies));
- return json(result);
-}
diff --git a/src/routes/(app)/payment/[id]/+page.svelte b/src/routes/(app)/payment/[id]/+page.svelte
index 78ae22c3..15f42a75 100644
--- a/src/routes/(app)/payment/[id]/+page.svelte
+++ b/src/routes/(app)/payment/[id]/+page.svelte
@@ -146,7 +146,11 @@
<div class="flex items-center gap-2 min-w-0">
{#if !expanded.has(label)}
<span class="text-right break-all">
- {value.slice(0, 8)}...{value.slice(-8)}
+ {#if value.length > 20}
+ {value.slice(0, 8)}...{value.slice(-8)}
+ {:else}
+ {value}
+ {/if}
</span>
{/if}
<button
@@ -344,6 +348,10 @@
{@render copyable("Txid", txid, `${expl}/tx/${txid}${vout ? "#vout=" + vout : ""}`)}
{/if}
+ {#if (type === "bitcoin" || type === "liquid") && amount > 0 && hash}
+ {@render copyable("Address", hash, `${expl}/address/${hash}`)}
+ {/if}
+
{#if path}
{@render copyable("Path", path)}
{/if}
diff --git a/src/routes/(app)/payment/[id]/print/+server.ts b/src/routes/(app)/payment/[id]/print/+server.ts
deleted file mode 100644
index 19f8941e..00000000
--- a/src/routes/(app)/payment/[id]/print/+server.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { auth, post } from "$lib/utils";
-import { json } from "@sveltejs/kit";
-
-export async function POST({ cookies, request }) {
- const body = await request.json();
- return json(post("/print", body, auth(cookies)));
-}
diff --git a/src/routes/(app)/pin/+server.ts b/src/routes/(app)/pin/+server.ts
deleted file mode 100644
index b24770d5..00000000
--- a/src/routes/(app)/pin/+server.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { json } from "@sveltejs/kit";
-import { auth, post } from "$lib/utils";
-
-export async function POST({ cookies, request }) {
- const result = await post("/pin", await request.json(), auth(cookies));
- return json(result);
-}
diff --git a/src/routes/(app)/reset/+server.ts b/src/routes/(app)/reset/+server.ts
deleted file mode 100644
index 4b6692d5..00000000
--- a/src/routes/(app)/reset/+server.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { json } from "@sveltejs/kit";
-import { auth, post } from "$lib/utils";
-
-export async function POST({ cookies, request }) {
- const result = await post("/reset", await request.json(), auth(cookies));
- return json(result);
-}
diff --git a/src/routes/(app)/send/[...text]/+page.svelte b/src/routes/(app)/send/[...text]/+page.svelte
index 658864ba..49a3853e 100644
--- a/src/routes/(app)/send/[...text]/+page.svelte
+++ b/src/routes/(app)/send/[...text]/+page.svelte
@@ -27,7 +27,7 @@
let loaded = $state();
let loadMore = async () => {
loaded = true;
- all = await get("/contacts");
+ all = await fetch("/api/contacts").then((r) => r.json());
};
let el: any = $state(),
@@ -48,12 +48,12 @@
e.stopPropagation();
if (pinned) {
- await post("/post/pins/delete", { id });
+ await post("/api/pins/delete", { id });
} else {
- await post("/post/pins", { id });
+ await post("/api/pins", { id });
}
- if (all) all = await get("/contacts");
+ if (all) all = await fetch("/api/contacts").then((r) => r.json());
invalidate("app:contacts");
};
@@ -62,12 +62,12 @@
e.stopPropagation();
if (trusted) {
- await post("/post/trust/delete", { id });
+ await post("/api/trust/delete", { id });
} else {
- await post("/post/trust", { id });
+ await post("/api/trust", { id });
}
- if (all) all = await get("/contacts");
+ if (all) all = await fetch("/api/contacts").then((r) => r.json());
invalidate("app:contacts");
};
diff --git a/src/routes/(app)/send/ark/[address]/[amount]/[...feeRate]/+page.svelte b/src/routes/(app)/send/ark/[address]/[amount]/[...feeRate]/+page.svelte
index 7098628b..bb3229b9 100644
--- a/src/routes/(app)/send/ark/[address]/[amount]/[...feeRate]/+page.svelte
+++ b/src/routes/(app)/send/ark/[address]/[amount]/[...feeRate]/+page.svelte
@@ -35,7 +35,7 @@
});
} else {
const txid = await sendArk(address, parseInt(amount));
- p = await post("/post/ark/vault-send", {
+ p = await post("/api/ark/vault-send", {
hash: txid,
amount: parseInt(amount),
aid: account.id,
diff --git a/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte b/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte
index ed59b14b..d5a8f6e5 100644
--- a/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte
+++ b/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte
@@ -5,7 +5,7 @@
import Toggle from "$comp/Toggle.svelte";
import Spinner from "$comp/Spinner.svelte";
import { page } from "$app/stores";
- import { toFiat, f, fail, focus, loc, s, sat, closest, network, versions } from "$lib/utils";
+ import { toFiat, f, fail, focus, loc, s, sat, network, versions } from "$lib/utils";
import { pin } from "$lib/store";
import { goto, invalidate } from "$app/navigation";
import { rate } from "$lib/store";
@@ -17,6 +17,7 @@
import { prfDecrypt, isPrfEncrypted } from "$lib/crypto";
import Amount from "$comp/Amount.svelte";
+ import Slider from "$comp/Slider.svelte";
let { data, form }: any = $props();
@@ -141,12 +142,16 @@
let { account, amount, address, message, fee, fees, subtract, ourfee, hex, inputs, forward, bumpReserve } =
$derived(data);
- let feeRate: any = $state((() => data.feeRate)());
+ let feeRate: any = $state((() => {
+ if (data.feeRate) return data.feeRate;
+ if (data.fees) return data.fees.halfHourFee;
+ return 1;
+ })());
$effect(() => {
if (fees) {
delete fees.minimumFee;
- feeRate = feeRate ? closest(Object.values(fees), feeRate) : fees.halfHourFee;
+ feeLoading = false;
}
});
@@ -161,29 +166,46 @@
submit: any = $state(),
showSettings = $state();
- let presets = $derived(fees ? [
- { label: $t("payments.low"), rate: 0.1 },
- { label: $t("payments.medium"), rate: fees.hourFee },
- { label: $t("payments.high"), rate: fees.fastestFee },
- ] : []);
+ let lowRate = $derived(fees ? 0.1 : 0.1);
+ let midRate = $derived(fees ? fees.hourFee : 1);
+ let highRate = $derived(fees ? Math.max(fees.fastestFee, 8) : 10);
+ let maxRate = $derived(Math.max(highRate * 2, 16));
- let toggleSettings = () => (showSettings = !showSettings);
+ let sliderValue = $state(50);
- let setFee = () => goto(`/send/bitcoin/${address}/${amount}/${feeRate}`);
- let goBack = () => goto(`/send/bitcoin/${address}`);
+ // Map slider (0-100) to fee rate: 0=low, 50=mid, 100=max
+ let sliderToRate = (v: number) => {
+ if (v <= 50) return lowRate + (midRate - lowRate) * (v / 50);
+ return midRate + (maxRate - midRate) * ((v - 50) / 50);
+ };
- let pickRate = (r: number) => {
- feeRate = r;
- setFee();
+ let rateToSlider = (r: number) => {
+ if (r <= midRate) return Math.round(((r - lowRate) / (midRate - lowRate)) * 50);
+ return Math.round(50 + ((r - midRate) / (maxRate - midRate)) * 50);
};
- let applyCustom = () => {
- const r = parseFloat(String(feeRate));
- if (r >= 0.1) {
- feeRate = r;
- setFee();
+ // Init slider from feeRate
+ $effect(() => {
+ if (fees) {
+ delete fees.minimumFee;
+ sliderValue = rateToSlider(feeRate);
}
+ });
+
+ let setFee = () => goto(`/send/bitcoin/${address}/${amount}/${feeRate}`);
+
+ let slideTimer: ReturnType<typeof setTimeout> | undefined;
+ let feeLoading = $state(false);
+ let handleSlide = () => {
+ const r = Math.round(sliderToRate(sliderValue) * 10) / 10;
+ feeRate = Math.max(0.1, r);
+ feeLoading = true;
+ clearTimeout(slideTimer);
+ slideTimer = setTimeout(setFee, 500);
};
+
+ let midSlider = $derived(rateToSlider(midRate));
+ let highSlider = $derived(rateToSlider(highRate));
</script>
<div class="container px-4 max-w-xl mx-auto space-y-5 text-center no-transition">
@@ -206,38 +228,24 @@
<Amount amount={subtract ? amount - fee - ourfee : amount} rate={$rate} {currency} {locale} />
{#if fees}
- <div class="text-center">
- <h2 class="text-secondary text-lg">{$t("payments.priority")}</h2>
- <div class="flex gap-2 justify-center mb-2">
- {#each presets as preset}
- <button
- type="button"
- class="btn btn-sm !w-auto"
- class:btn-accent={feeRate == preset.rate}
- onclick={() => pickRate(preset.rate)}
- >
- {preset.label}
- </button>
- {/each}
- </div>
+ <div class="text-center space-y-2">
+ <h2 class="text-secondary text-lg">{$t("payments.networkFee")}</h2>
- <div class="flex items-center justify-center gap-2 mb-2">
- <input
- type="number"
- min="0.1"
- step="0.1"
- class="input input-bordered w-24 text-center"
- value={feeRate}
- oninput={(e) => {
- const r = parseFloat(e.currentTarget.value);
- if (r >= 0.1) { feeRate = r; setFee(); }
- }}
- onkeydown={(e) => e.key === 'Enter' && applyCustom()}
- />
- <span class="text-secondary text-sm">sat/vB</span>
+ <div class="px-2">
+ <Slider bind:value={sliderValue} handle={handleSlide} min={0} max={100} />
+ <div class="flex justify-between text-secondary mt-1 px-1">
+ <span>{lowRate} sat/vB</span>
+ <span>{midRate} sat/vB</span>
+ <span>{highRate} sat/vB</span>
+ </div>
</div>
- <Amount amount={fee} rate={$rate} {currency} {locale} />
+ <div class="text-lg">{feeRate} sat/vB</div>
+ {#if feeLoading}
+ <Spinner class="text-secondary" />
+ {:else}
+ <Amount amount={fee} rate={$rate} {currency} {locale} />
+ {/if}
</div>
{#if bumpReserve > 0}
diff --git a/src/routes/(app)/send/invoice/[id]/+page.svelte b/src/routes/(app)/send/invoice/[id]/+page.svelte
index d945ec19..a0af8482 100644
--- a/src/routes/(app)/send/invoice/[id]/+page.svelte
+++ b/src/routes/(app)/send/invoice/[id]/+page.svelte
@@ -70,9 +70,9 @@
e.stopPropagation();
if (trusted) {
- await post("/post/trust/delete", { id: recipient.id });
+ await post("/api/trust/delete", { id: recipient.id });
} else {
- await post("/post/trust", { id: recipient.id });
+ await post("/api/trust", { id: recipient.id });
}
invalidate("app:trust");
diff --git a/src/routes/(app)/send/lightning/[payreq]/[...memo]/+page.svelte b/src/routes/(app)/send/lightning/[payreq]/[...memo]/+page.svelte
index fc80e161..5669ee1e 100644
--- a/src/routes/(app)/send/lightning/[payreq]/[...memo]/+page.svelte
+++ b/src/routes/(app)/send/lightning/[payreq]/[...memo]/+page.svelte
@@ -70,7 +70,7 @@
(async () => {
try {
- const inv = await post("/post/invoice", {
+ const inv = await post("/api/invoice", {
invoice: {
type: "bitcoin",
amount: parseInt(amount),
diff --git a/src/routes/(app)/send/zap/[id]/[...amount]/+page.svelte b/src/routes/(app)/send/zap/[id]/[...amount]/+page.svelte
index 62329d7a..21090d23 100644
--- a/src/routes/(app)/send/zap/[id]/[...amount]/+page.svelte
+++ b/src/routes/(app)/send/zap/[id]/[...amount]/+page.svelte
@@ -29,8 +29,8 @@
try {
loading = false;
event = await sign(request);
- let { pr: payreq } = await post("/post/zap", { event });
- await post("/post/payments", { amount, payreq, pin: $pin });
+ let { pr: payreq } = await post("/api/zap", { event });
+ await post("/api/payments", { amount, payreq, pin: $pin });
goto(`/e/${id}`);
} catch (e: any) {
console.log(e);
diff --git a/src/routes/(app)/settings/+layout.svelte b/src/routes/(app)/settings/+layout.svelte
index 8a4b36a2..2b3de9f5 100644
--- a/src/routes/(app)/settings/+layout.svelte
+++ b/src/routes/(app)/settings/+layout.svelte
@@ -195,7 +195,7 @@
user.verified = false;
- await post("/email", { email });
+ await post("/api/request", { email });
warning($t("user.settings.verifying"), false);
} catch (e: any) {
diff --git a/src/routes/(app)/settings/account/+page.svelte b/src/routes/(app)/settings/account/+page.svelte
index 115f46c5..fb8a9538 100644
--- a/src/routes/(app)/settings/account/+page.svelte
+++ b/src/routes/(app)/settings/account/+page.svelte
@@ -58,7 +58,7 @@
}
if (subscription) {
- await post("/subscription", { subscription });
+ await post("/api/subscription", { subscription });
}
};
run(() => {
diff --git a/src/routes/(app)/settings/security/+page.svelte b/src/routes/(app)/settings/security/+page.svelte
index dbd73b1b..6ba91240 100644
--- a/src/routes/(app)/settings/security/+page.svelte
+++ b/src/routes/(app)/settings/security/+page.svelte
@@ -136,7 +136,7 @@
let enable2fa = async (twoFa?: any) => {
try {
if (setting2fa && token && token.length === 6) {
- await post("/enable2fa", { token });
+ await post("/api/2fa", { token });
success("2FA enabled");
user.twofa = 1;
cancel();
@@ -150,7 +150,7 @@
let disable2fa = async (_?: any) => {
try {
if (disabling2fa && token && token.length === 6) {
- await post("/disable2fa", { token });
+ await post("/api/disable2fa", { token });
success("2FA disabled");
delete user.twofa;
disabling2fa = false;
diff --git a/src/routes/(app)/subscription/+server.ts b/src/routes/(app)/subscription/+server.ts
deleted file mode 100644
index f25db99a..00000000
--- a/src/routes/(app)/subscription/+server.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { auth, post } from "$lib/utils";
-import { json } from "@sveltejs/kit";
-
-export async function POST({ cookies, request }) {
- const body = await request.json();
- const result = await post("/subscription", body, auth(cookies));
- return json(result);
-}
diff --git a/src/routes/(app)/subscription/delete/+server.ts b/src/routes/(app)/subscription/delete/+server.ts
deleted file mode 100644
index 1e6c1fdd..00000000
--- a/src/routes/(app)/subscription/delete/+server.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { auth, post } from "$lib/utils";
-import { json } from "@sveltejs/kit";
-
-export async function POST({ cookies, request }) {
- const body = await request.json();
- const result = await post("/subscription/delete", body, auth(cookies));
- return json(result);
-}
diff --git a/src/routes/(app)/tag/[tag]/+page.svelte b/src/routes/(app)/tag/[tag]/+page.svelte
index f2e50c6c..6446c265 100644
--- a/src/routes/(app)/tag/[tag]/+page.svelte
+++ b/src/routes/(app)/tag/[tag]/+page.svelte
@@ -27,7 +27,7 @@
async onevent(event: any) {
if (paused) return;
if (events.find((e) => e.id === event.id)) return;
- const { parts, names } = await post("/post/parseEvent", { event });
+ const { parts, names } = await post("/api/parseEvent", { event });
event.author = await get(`/api/users/${event.pubkey}`);
event.parts = parts;
event.names = names;
diff --git a/src/routes/(app)/withdraw/+server.ts b/src/routes/(app)/withdraw/+server.ts
deleted file mode 100644
index f8e093ef..00000000
--- a/src/routes/(app)/withdraw/+server.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { auth, post } from "$lib/utils";
-
-export async function POST({ cookies, request }) {
- const body = await request.json();
- await post("/payments", body, auth(cookies));
-
- return new Response(JSON.stringify("ok"), {
- headers: { "content-type": "application/json" },
- });
-}
diff --git a/src/routes/(static)/register/auth/+page.svelte b/src/routes/(static)/register/auth/+page.svelte
index aca1f30c..c45d63f6 100644
--- a/src/routes/(static)/register/auth/+page.svelte
+++ b/src/routes/(static)/register/auth/+page.svelte
@@ -174,7 +174,7 @@
console.log("Nostr key derivation failed", e);
}
- await post("/post/user", nostrPubkey ? { encryptedKeys, pubkey: nostrPubkey } : { encryptedKeys });
+ await post("/api/user", nostrPubkey ? { encryptedKeys, pubkey: nostrPubkey } : { encryptedKeys });
} catch (e) {
console.log("Canonical key generation failed", e);
}
@@ -269,7 +269,7 @@
// Clean up the account created by passkeyCreate if passkey registration failed
if (passkeyToken) {
try {
- await fetch("/post/user/delete", {
+ await fetch("/api/user/delete", {
method: "POST",
headers: {
"Content-Type": "application/json",
diff --git a/src/routes/(static)/support/+page.svelte b/src/routes/(static)/support/+page.svelte
index 3a9b011f..6af80f86 100644
--- a/src/routes/(static)/support/+page.svelte
+++ b/src/routes/(static)/support/+page.svelte
@@ -31,7 +31,7 @@
let submit = (e: any) => {
e.preventDefault();
if (isTor) {
- post("/post/email", {
+ post("/api/email", {
username: user?.username || `${username} (unverified)`,
email,
message,
@@ -43,7 +43,7 @@
}
grecaptcha.ready(() => {
grecaptcha.execute(recaptchaSiteKey, { action: "submit" }).then((token) =>
- post("/post/email", {
+ post("/api/email", {
username: user?.username || `${username} (unverified)`,
email,
message,