aboutsummaryrefslogtreecommitdiffstats
path: root/src/routes/launch/purchase
diff options
context:
space:
mode:
Diffstat (limited to 'src/routes/launch/purchase')
-rw-r--r--src/routes/launch/purchase/+page.server.js45
-rw-r--r--src/routes/launch/purchase/+page.svelte91
-rw-r--r--src/routes/launch/purchase/card/+page.server.js44
-rw-r--r--src/routes/launch/purchase/card/+page.svelte77
4 files changed, 200 insertions, 57 deletions
diff --git a/src/routes/launch/purchase/+page.server.js b/src/routes/launch/purchase/+page.server.js
index f6314f7f..2ecce695 100644
--- a/src/routes/launch/purchase/+page.server.js
+++ b/src/routes/launch/purchase/+page.server.js
@@ -1,8 +1,45 @@
-export const load = ({ parent }) => parent();
+import { auth, get, post } from '$lib/utils';
+import tickets from '$lib/tickets';
+import { redirect } from '@sveltejs/kit';
+import { env } from '$env/dynamic/private';
+import { invalidateAll } from '$app/navigation';
+import { browser } from '$app/environment';
+import { createTicket } from '$lib/ticket';
+
+export const load = async ({ parent }) => {
+ let tickets = await get('/tickets');
+ let { user } = await parent();
+ let hasTicket = !!user?.accounts.find((a) => tickets.includes(a.asset));
+ if (hasTicket) throw redirect(307, '/launch/ticket');
+ return { tickets };
+};
export const actions = {
- default: async ({ cookies, request }) => {
- let form = Object.fromEntries(await request.formData());
- console.log(form);
+ internal: async ({ cookies, request }) => {
+ let form = await request.formData();
+ let asset = await createTicket(cookies, form.get('username'));
+ await post('/send', { amount: 22000, username: 'launch' }, auth(cookies));
+
+ throw redirect(307, `/launch/thanks/${asset}`);
+ },
+
+ lightning: async ({ cookies, request }) => {
+ let form = await request.formData();
+
+ let rates = await get('/rates');
+
+ let invoice = {
+ amount: 22000,
+ memo: 'launch',
+ network: 'lightning',
+ prompt: false,
+ rate: rates[form.get('currency')]
+ };
+
+ let user = { username: form.get('username') };
+
+ let { uuid } = await post('/invoice', { invoice, user }, auth(cookies));
+
+ throw redirect(307, `/invoice/${uuid}`);
}
};
diff --git a/src/routes/launch/purchase/+page.svelte b/src/routes/launch/purchase/+page.svelte
index df3048f3..3273752a 100644
--- a/src/routes/launch/purchase/+page.svelte
+++ b/src/routes/launch/purchase/+page.svelte
@@ -1,4 +1,5 @@
<script>
+ import { onMount } from 'svelte';
import { enhance } from '$app/forms';
import { selectedRate } from '$lib/store';
import { post } from '$lib/utils';
@@ -6,77 +7,61 @@
export let data;
- let amount = 35000;
+ let amount = 22000;
let {
+ currency,
account: { balance },
username
} = data.user;
- let invoice;
- let get = async (network) => {
- let { uuid } = await post('/invoice', {
- amount,
- rate: $selectedRate,
- network,
- username
- });
-
- goto(`/invoice/${uuid}`);
- };
-
- let lightning = () => get('lightning');
- let bitcoin = () => get('bitcoin');
-
- // if (balance < amount) throw redirect(307, `/${username}/fund/${amount - balance}`);
+ let { tickets } = data;
+ let ticket = tickets.length;
</script>
-<div class="mx-auto h-screen flex items-center justify-center px-8">
- <div class="p-4 font-normal text-gray-800 mx-auto mb-8">
- {#if balance > amount}
- <h1 class="mb-4 text-4xl font-bold leading-none tracking-tight text-gray-800 text-center">
- Buy Your Launch Party Ticket?
- </h1>
+<div class="mx-auto h-screen flex items-center justify-center px-4">
+ <div class="font-normal text-gray-800 mx-auto mb-8 space-y-8">
+ <h1 class="mb-4 text-4xl font-bold leading-none tracking-tight text-gray-800 text-center">
+ Purchase Ticket
+ </h1>
- <div class="text-center text-4xl mb-12">{amount} sats</div>
+ <img
+ src={`/tickets/${(ticket + 1).toString().padStart(2, '0')}.png`}
+ class="w-full max-w-[800px]"
+ alt="Ticket"
+ />
- <div class="w-full flex">
- <form method="POST" use:enhance>
+ {#if balance >= amount}
+ <form action="?/internal" method="POST" use:enhance>
+ <input type="hidden" name="username" value={username} />
+
+ <div class="w-full flex">
<button
class="bg-black text-white border rounded-full px-8 py-4 font-bold hover:opacity-80 mx-auto text-2xl"
>
Count me in
</button>
- </form>
- </div>
+ </div>
+ </form>
{:else}
- <h1 class="mb-4 text-4xl font-bold leading-none tracking-tight text-gray-800 text-center">
- Ticket Price
- </h1>
- <div class="text-center text-4xl mb-12">{amount} sats</div>
-
- <h1 class="mb-4 text-4xl font-bold leading-none tracking-tight text-gray-800 text-center">
- Your Balance
- </h1>
-
- <div class="text-center text-4xl mb-12">{balance} sats</div>
-
- <h1 class="mb-4 text-4xl font-bold leading-none tracking-tight text-gray-800 text-center">
- Funding Options
+ <h1 class="mb-4 text-xl font-bold leading-none tracking-tight text-gray-800 text-center">
+ Payment Options
</h1>
- <button
- class="bg-black text-white border rounded-full px-8 py-4 font-bold hover:opacity-80 mx-auto text-2xl"
- on:click={lightning}
- >
- Lightning
- </button>
+ <div class="flex justify-center gap-4">
+ <form action="?/lightning" method="POST">
+ <input type="hidden" name="currency" value={currency} />
+ <input type="hidden" name="username" value={username} />
+ <button class="border rounded-full px-8 py-4 font-bold hover:opacity-80 mx-auto text-2xl">
+ Lightning
+ </button>
+ </form>
- <button
- class="bg-black text-white border rounded-full px-8 py-4 font-bold hover:opacity-80 mx-auto text-2xl"
- on:click={bitcoin}
- >
- Bitcoin
- </button>
+ <a href={`purchase/card`}>
+ <button class="border rounded-full px-8 py-4 font-bold hover:opacity-80 mx-auto text-2xl">
+ Credit Card
+ </button>
+ </a>
+ </div>
{/if}
</div>
</div>
diff --git a/src/routes/launch/purchase/card/+page.server.js b/src/routes/launch/purchase/card/+page.server.js
new file mode 100644
index 00000000..1f564f78
--- /dev/null
+++ b/src/routes/launch/purchase/card/+page.server.js
@@ -0,0 +1,44 @@
+import { env } from '$env/dynamic/private';
+import { error, redirect } from '@sveltejs/kit';
+import { post, auth } from '$lib/utils';
+import { createTicket } from '$lib/ticket';
+
+let stripe = 'https://api.stripe.com/v1';
+
+export const actions = {
+ default: async ({ cookies, request }) => {
+ let form = await request.formData();
+
+ let headers = new Headers();
+ headers.set('Authorization', 'Basic ' + new Buffer(env.STRIPE + ':').toString('base64'));
+
+ let body = new URLSearchParams({
+ 'card[number]': form.get('number').replace(/\s+/g, ''),
+ 'card[exp_month]': form.get('expiry').slice(0, 2),
+ 'card[exp_year]': form.get('expiry').slice(-2),
+ 'card[cvc]': form.get('cvc')
+ });
+
+ let method = 'POST';
+
+ let { id: source } = await fetch(`${stripe}/tokens`, { body, headers, method }).then((r) =>
+ r.json()
+ );
+
+ body = new URLSearchParams({
+ amount: 600,
+ currency: 'cad',
+ source,
+ description: 'launch ticket'
+ });
+
+ let { status } = await fetch(`${stripe}/charges`, { body, headers, method }).then((r) =>
+ r.json()
+ );
+
+ if (status !== 'succeeded') throw error(500, { message: 'Card payment failed' });
+ let asset = await createTicket(cookies, form.get('username'));
+
+ throw redirect(307, `/launch/thanks/${asset}`);
+ }
+};
diff --git a/src/routes/launch/purchase/card/+page.svelte b/src/routes/launch/purchase/card/+page.svelte
new file mode 100644
index 00000000..05d09025
--- /dev/null
+++ b/src/routes/launch/purchase/card/+page.svelte
@@ -0,0 +1,77 @@
+<script>
+ import { enhance } from '$app/forms';
+ import { Lock, Card, Calendar, Spinner } from '$comp';
+
+ export let data;
+
+ let { username } = data.user;
+ let loading;
+</script>
+
+<div class="container max-w-lg px-4 mx-auto space-y-5">
+ <form
+ method="POST"
+ class="flex flex-wrap gap-5 w-full p-5 mt-20"
+ use:enhance={() => {
+ loading = true;
+ return ({ update }) => update() && (loading = false);
+ }}
+ >
+ <input type="hidden" name="username" value={username} />
+ <label class="relative w-full flex flex-col">
+ <span class="font-bold mb-3">Card number</span>
+ <input
+ class="rounded-md peer pl-12 pr-2 py-2 border-2 border-gray-200 placeholder-gray-300"
+ type="text"
+ name="number"
+ placeholder="0000 0000 0000 0000"
+ />
+ <Card />
+ </label>
+
+ <label class="relative flex-1 flex flex-col">
+ <span class="font-bold mb-3">Expire date</span>
+ <input
+ class="rounded-md peer pl-12 pr-2 py-2 border-2 border-gray-200 placeholder-gray-300"
+ type="text"
+ name="expiry"
+ placeholder="MM/YY"
+ />
+ <Calendar />
+ </label>
+
+ <label class="relative flex-1 flex flex-col">
+ <span class="font-bold flex items-center gap-3 mb-3">
+ CVC/CVV
+ <span class="relative group">
+ <span
+ class="hidden group-hover:flex justify-center items-center px-2 py-1 text-xs absolute -right-2 transform translate-x-full -translate-y-1/2 w-max top-1/2 bg-black text-white"
+ >
+ 3-digit number on the back of your card</span
+ >
+ </span>
+ </span>
+ <input
+ class="rounded-md peer pl-12 pr-2 py-2 border-2 border-gray-200 placeholder-gray-300"
+ type="text"
+ name="cvc"
+ placeholder="&bull;&bull;&bull;"
+ />
+ <Lock />
+ </label>
+
+ <div class="w-full flex mt-8">
+ <button
+ class="bg-black text-white border rounded-full px-8 py-4 font-bold hover:opacity-80 mx-auto text-xl"
+ type="submit"
+ disabled={loading}
+ >
+ {#if loading}
+ <Spinner />
+ {:else}
+ Submit
+ {/if}
+ </button>
+ </div>
+ </form>
+</div>