aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/socket.js13
-rw-r--r--src/lib/store.js1
-rw-r--r--src/routes/(app)/[username]/address/+page.server.js13
-rw-r--r--src/routes/(app)/[username]/address/+page.svelte (renamed from src/routes/(app)/[username]/bitcoin/+page.svelte)0
-rw-r--r--src/routes/(app)/[username]/bitcoin/+page.server.js4
-rw-r--r--src/routes/(app)/[username]/dashboard/+page.svelte28
-rw-r--r--src/routes/(app)/[username]/receive/[...recipient]/+page.svelte2
-rw-r--r--src/routes/(app)/[username]/transactions/[...page]/+page.svelte96
-rw-r--r--src/routes/(app)/invoice/[id]/+page.svelte37
-rw-r--r--src/routes/(app)/invoice/[id]/pending/+page.svelte56
10 files changed, 166 insertions, 84 deletions
diff --git a/src/lib/socket.js b/src/lib/socket.js
index 079c8f96..6678b979 100644
--- a/src/lib/socket.js
+++ b/src/lib/socket.js
@@ -1,7 +1,8 @@
import { get } from 'svelte/store';
-import { invoices, invoice, request, newPayment, last, rate, user } from '$lib/store';
+import { invoices, invoice, request, newPayment, last, rate, txns, user } from '$lib/store';
import { success, sat } from '$lib/utils';
import { env } from '$env/dynamic/public';
+import { invalidate } from '$app/navigation';
const socketUrl = env.PUBLIC_SOCKET;
const btc = env.PUBLIC_BTC;
@@ -41,9 +42,15 @@ export const messages = (data) => ({
if (get(user).account_id !== data.account_id) return;
- newPayment.set(true);
+ let payments = get(txns);
+ let i = payments.findIndex((p) => p.id === data.id);
+ if (~i) (payments[i] = data), txns.set(payments);
+ else newPayment.set(true);
+
+ invalidate((url) => url.pathname === '/payments');
+
if (amount > 0) {
- success(`Received ${sat(amount)}!`);
+ success(`${data.confirmed ? 'Received' : 'Detected'} ${sat(amount)}!`);
} else {
success(`Sent ${sat(amount)}!`);
}
diff --git a/src/lib/store.js b/src/lib/store.js
index 3faa234b..3105419c 100644
--- a/src/lib/store.js
+++ b/src/lib/store.js
@@ -46,3 +46,4 @@ export const pin = persistSession('pin', undefined, 5 * 60 * 1000);
export const last = writable();
export const request = writable();
export const invoice = writable();
+export const txns = persistLocal('transactions', []);
diff --git a/src/routes/(app)/[username]/address/+page.server.js b/src/routes/(app)/[username]/address/+page.server.js
new file mode 100644
index 00000000..c18bcdba
--- /dev/null
+++ b/src/routes/(app)/[username]/address/+page.server.js
@@ -0,0 +1,13 @@
+import { auth, get, post } from '$lib/utils';
+import { redirect } from '@sveltejs/kit';
+
+export async function load({ cookies, params, parent }) {
+ let user = (await parent()).subject;
+ let rates = await get('/rates');
+ let invoice = {
+ network: 'bitcoin',
+ rate: rates[user.currency]
+ };
+ let { uuid } = await post('/invoice', { invoice, user }, auth(cookies));
+ throw redirect(307, `/invoice/${uuid}`);
+}
diff --git a/src/routes/(app)/[username]/bitcoin/+page.svelte b/src/routes/(app)/[username]/address/+page.svelte
index e69de29b..e69de29b 100644
--- a/src/routes/(app)/[username]/bitcoin/+page.svelte
+++ b/src/routes/(app)/[username]/address/+page.svelte
diff --git a/src/routes/(app)/[username]/bitcoin/+page.server.js b/src/routes/(app)/[username]/bitcoin/+page.server.js
deleted file mode 100644
index 7ef65346..00000000
--- a/src/routes/(app)/[username]/bitcoin/+page.server.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import { redirect } from '@sveltejs/kit';
-export async function load({ params }) {
- throw redirect(303, `/${params.username}`);
-}
diff --git a/src/routes/(app)/[username]/dashboard/+page.svelte b/src/routes/(app)/[username]/dashboard/+page.svelte
index 93fac986..0ea0e0a8 100644
--- a/src/routes/(app)/[username]/dashboard/+page.svelte
+++ b/src/routes/(app)/[username]/dashboard/+page.svelte
@@ -52,23 +52,25 @@
</div>
<div class="grid sm:grid-cols-2 gap-2 mt-8">
+ <a href="/send">
+ <button class="rounded-full border py-2 px-5 font-bold hover:opacity-80 w-full mb-2"
+ >{$t('user.dashboard.withdraw')}</button
+ >
+ </a>
<a href={`/${user.username}/receive`}>
<button class="rounded-full border py-2 px-5 font-bold hover:opacity-80 w-full mb-2"
>{$t('user.dashboard.receive')}</button
>
</a>
- {#if user.account.balance > 0}
- <a href="/send">
- <button class="rounded-full border py-2 px-5 font-bold hover:opacity-80 w-full mb-2"
- >{$t('user.dashboard.withdraw')}</button
- >
- </a>
- {:else}
- <a href={`/${user.username}/settings`}>
- <button class="rounded-full border py-2 px-5 font-bold hover:opacity-80 w-full mb-2"
- >Setup Account</button
- >
- </a>
- {/if}
+ <a href={`/${user.username}/settings`}>
+ <button class="rounded-full border py-2 px-5 font-bold hover:opacity-80 w-full mb-2"
+ >Setup Account</button
+ >
+ </a>
+ <a href={`/${user.username}/address`}>
+ <button class="rounded-full border py-2 px-5 font-bold hover:opacity-80 w-full mb-2"
+ >Deposit</button
+ >
+ </a>
</div>
</div>
diff --git a/src/routes/(app)/[username]/receive/[...recipient]/+page.svelte b/src/routes/(app)/[username]/receive/[...recipient]/+page.svelte
index 634b091a..41958cd0 100644
--- a/src/routes/(app)/[username]/receive/[...recipient]/+page.svelte
+++ b/src/routes/(app)/[username]/receive/[...recipient]/+page.svelte
@@ -56,7 +56,7 @@
<input type="hidden" name="amount" value={amount} />
<input type="hidden" name="currency" value={currency} />
<input type="hidden" name="username" value={username} />
- <input type="hidden" name="network" value={network} />
+ <input type="hidden" name="network" value={network} />
{#if req}
<input type="hidden" name="requester" value={req.requester.username} />
diff --git a/src/routes/(app)/[username]/transactions/[...page]/+page.svelte b/src/routes/(app)/[username]/transactions/[...page]/+page.svelte
index f5fae1d9..c7007af4 100644
--- a/src/routes/(app)/[username]/transactions/[...page]/+page.svelte
+++ b/src/routes/(app)/[username]/transactions/[...page]/+page.svelte
@@ -2,7 +2,7 @@
import { Avatar, Icon } from '$comp';
import { onMount } from 'svelte';
import { format, parseISO } from 'date-fns';
- import { newPayment } from '$lib/store';
+ import { newPayment, txns } from '$lib/store';
import { t } from '$lib/translations';
import { f, s, sat, sats } from '$lib/utils';
import { page } from '$app/stores';
@@ -31,17 +31,21 @@
pages = [];
$: data && ({ page: p, pages, start, end, total, transactions } = data);
+ $: console.log($txns.length), ($txns = transactions);
+
$: $page && ($newPayment = false);
$: $newPayment && invalidate(`/users/${user.username}`);
- $: path = $page.url.pathname.substring(0, $page.url.pathname.lastIndexOf('/'));
+ $: path = $page.params.page
+ ? $page.url.pathname.substring(0, $page.url.pathname.lastIndexOf('/'))
+ : $page.url.pathname;
let csv = () => {
const keys = ['hash', 'updatedAt', 'rate', 'currency', 'amount', 'fee', 'tip'];
const csv =
keys.map((k) => `"${k}"`).join(',') +
'\n' +
- transactions.map((r) => keys.map((k) => `"${r[k]}"`).join(',')).join('\n');
+ $txns.map((r) => keys.map((k) => `"${r[k]}"`).join(',')).join('\n');
const filename = 'transactions.csv';
let blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
@@ -108,61 +112,59 @@
</div>
<div class="space-y-10">
- {#if transactions.length}
- {#each transactions as tx}
- <div class="grid grid-cols-3 border-b pb-5">
- <div class="whitespace-nowrap">
- <div class="mb-1 font-bold">
- {f(tx.amount * (tx.rate / sats), tx.currency)}
+ {#each $txns as tx}
+ <div class="grid grid-cols-3 border-b pb-5">
+ <div class="whitespace-nowrap">
+ <div class="mb-1 font-bold">
+ {f(tx.amount * (tx.rate / sats), tx.currency)}
- {#if tx.tip}
- <span class="text-sm">
- +{f(tx.tip * (tx.rate / sats), tx.currency)}
- </span>
- {/if}
- </div>
+ {#if tx.tip}
+ <span class="text-sm">
+ +{f(tx.tip * (tx.rate / sats), tx.currency)}
+ </span>
+ {/if}
+ </div>
- <span class="text-secondary"
- >{sat(tx.amount)}
+ <span class="text-secondary"
+ >{sat(tx.amount)}
- {#if tx.tip}
- <span class="text-sm">
- +{sat(tx.tip)}
- </span>
- {/if}
- </span>
- </div>
+ {#if tx.tip}
+ <span class="text-sm">
+ +{sat(tx.tip)}
+ </span>
+ {/if}
+ </span>
+ </div>
- <div class="flex">
- {#if tx.with}
- <a href={`/${tx.with.username}`} class="mx-auto">
- <div class="flex">
- <div class="my-auto">
- <Avatar user={tx.with} size={12} />
- </div>
- <div class="my-auto ml-1 text-secondary">{tx.with.username}</div>
+ <div class="flex">
+ {#if tx.with}
+ <a href={`/${tx.with.username}`} class="mx-auto">
+ <div class="flex">
+ <div class="my-auto">
+ <Avatar user={tx.with} size={12} />
</div>
- </a>
- {:else}
- <div class="mx-auto text-secondary">
- {tx.amount > 0 ? 'Received' : 'Sent'}
+ <div class="my-auto ml-1 text-secondary">{tx.with.username}</div>
</div>
- {/if}
- </div>
-
- <div class="text-secondary text-right">
- <div>
- {format(parseISO(tx.createdAt), 'h:mm aaa')}
- </div>
- <div>
- {format(parseISO(tx.createdAt), 'MMM d')}
+ </a>
+ {:else}
+ <div class="mx-auto text-secondary">
+ {tx.amount > 0 ? (tx.confirmed ? 'Received' : 'Pending') : 'Sent'}
</div>
+ {/if}
+ </div>
+
+ <div class="text-secondary text-right">
+ <div>
+ {format(parseISO(tx.createdAt), 'h:mm aaa')}
+ </div>
+ <div>
+ {format(parseISO(tx.createdAt), 'MMM d')}
</div>
</div>
- {/each}
+ </div>
{:else}
<p class="text-secondary text-lg text-center">{$t('user.transactions.empty')}</p>
- {/if}
+ {/each}
</div>
</div>
</div>
diff --git a/src/routes/(app)/invoice/[id]/+page.svelte b/src/routes/(app)/invoice/[id]/+page.svelte
index 463cf31f..dec33b62 100644
--- a/src/routes/(app)/invoice/[id]/+page.svelte
+++ b/src/routes/(app)/invoice/[id]/+page.svelte
@@ -27,7 +27,7 @@
user: { username, currency }
} = invoice;
-let src = sm;
+ let src = sm;
let qr;
let tipPercent = 0;
@@ -51,9 +51,12 @@ let src = sm;
$invoices[id] = { amount, id, rate, received, text, tip, username };
$: browser &&
+ $invoices[id].amount > 0 &&
$invoices[id]?.received >= $invoices[id]?.amount &&
goto(($invoices[id].memo === 'launch' && '/launch/purchase') || `/invoice/${id}/paid`);
+ $: browser && $invoices[id].pending > 0 && goto(`/invoice/${id}/pending`);
+
$: amountFiat = parseFloat(((amount * rate) / sats).toFixed(2));
$: tipAmount = ((tip * rate) / sats).toFixed(2);
@@ -69,13 +72,13 @@ let src = sm;
$: link = address ? text : `lightning:${text}`;
- let full;
- let toggle = () => {
- screenfull.toggle(qr);
- full = !full;
- if (full) src = lg;
- else src = sm;
- }
+ let full;
+ let toggle = () => {
+ screenfull.toggle(qr);
+ full = !full;
+ if (full) src = lg;
+ else src = sm;
+ };
</script>
<button class="ml-5 md:ml-20 mt-5 md:mt-10 hover:opacity-80" on:click={back}>
@@ -101,7 +104,7 @@ let src = sm;
<div class="text-center space-y-5">
{#if !user || user.username === username || showQr}
<div class="mx-auto">
- <img {src} class:p-4={full} class="w-[300px] mx-auto" bind:this={qr} on:click={toggle} />
+ <img {src} class:p-4={full} class="w-[300px] mx-auto" bind:this={qr} on:click={toggle} />
</div>
<div class="mb-10 flex gap-2 justify-center">
@@ -133,13 +136,15 @@ let src = sm;
</div>
{/if}
- <div class="flex flex-wrap justify-between font-bold text-2xl !my-8">
- <span class="mr-1">{$t('invoice.total')}</span>
- <span
- >{f(amountFiat + parseFloat(tipAmount), currency)}
- <span class="text-secondary font-normal">{`${sat(tip + amount)}`}</span></span
- >
- </div>
+ {#if amount > 0}
+ <div class="flex flex-wrap justify-between font-bold text-2xl !my-8">
+ <span class="mr-1">{$t('invoice.total')}</span>
+ <span
+ >{f(amountFiat + parseFloat(tipAmount), currency)}
+ <span class="text-secondary font-normal">{`${sat(tip + amount)}`}</span></span
+ >
+ </div>
+ {/if}
</div>
{#if user && user.username !== username}
diff --git a/src/routes/(app)/invoice/[id]/pending/+page.svelte b/src/routes/(app)/invoice/[id]/pending/+page.svelte
new file mode 100644
index 00000000..d3970dab
--- /dev/null
+++ b/src/routes/(app)/invoice/[id]/pending/+page.svelte
@@ -0,0 +1,56 @@
+<script>
+ import { scale } from 'svelte/transition';
+ import { Icon } from '$comp';
+ import { toast } from '@zerodevx/svelte-toast';
+ import { browser } from '$app/environment';
+ import { t } from '$lib/translations';
+ import { f, s, sat, sats } from '$lib/utils';
+ import { goto } from '$app/navigation';
+ import { invoices } from '$lib/store';
+
+ export let data;
+ let { invoice } = data;
+ let { pending, currency, rate, tip } = invoice;
+
+ toast.pop(0);
+
+ $: pendingFiat = parseFloat(((pending * rate) / sats).toFixed(2));
+ $: tipFiat = parseFloat(((tip * rate) / sats).toFixed(2));
+
+ const handleDoneClick = () => {
+ delete $invoices[invoice.uuid];
+ goto(`/${invoice.user.username}/receive`);
+ };
+</script>
+
+<div class="container px-4 text-center mx-auto space-y-5">
+ <div class="flex w-full py-20 max-w-[200px] mx-auto" in:scale={{ start: 0.5 }}>
+ <Icon icon="check" style="mx-auto" />
+ </div>
+
+ <h1 class="text-3xl md:text-4xl font-bold">Payment detected</h1>
+
+ <div>
+ <h2 class="text-2xl md:text-3xl font-semibold">
+ {f(pendingFiat, currency)}
+ {#if tip}
+ + {f(tipFiat, currency)}
+ {/if}
+ </h2>
+ <h3 class="text-secondary md:text-lg mt-1">
+ {sat(pending)}
+ {#if tip}
+ +{sat(tip)}
+ {/if}
+ </h3>
+ </div>
+
+ <p class="text-xl text-red-600">Pending confirmation</p>
+
+ <button
+ class="bg-black text-white rounded-2xl w-20 py-3 font-bold hover:opacity-80"
+ on:click={handleDoneClick}
+ >
+ {$t('invoice.done')}
+ </button>
+</div>