diff --git a/ceremony/src/lib/client/index.ts b/ceremony/src/lib/client/index.ts index b299f579f1..927eda7901 100644 --- a/ceremony/src/lib/client/index.ts +++ b/ceremony/src/lib/client/index.ts @@ -1,11 +1,18 @@ import { get, post } from "$lib/client/http.ts" -import { user } from "$lib/stores/user.svelte.ts" import { getQueuePayloadId } from "$lib/supabase/queries.ts" import type { ClientState, ContributeBody } from "$lib/client/types.ts" +import { supabase } from "$lib/supabase/client.ts" export const start = async (): Promise => { - const userId = user?.session?.user.id - const email = user?.session?.user?.email + const { data: session, error: sessionError } = await supabase.auth.refreshSession() + + if (sessionError) { + console.error("Error refreshing session:", sessionError) + return + } + + const userId = session.session?.user.id + const email = session.session?.user?.email if (!userId) { console.log("User not logged in") @@ -27,7 +34,7 @@ export const start = async (): Promise => { const contributeBody: Partial = { payloadId: data.payload_id, contributorId: userId, - jwt: user?.session?.access_token, + jwt: session.session?.access_token, supabaseProject: import.meta.env.VITE_SUPABASE_URL, apiKey: import.meta.env.VITE_SUPABASE_ANON_KEY, bucket: import.meta.env.VITE_BUCKET_ID, diff --git a/ceremony/src/lib/components/Blink.svelte b/ceremony/src/lib/components/Blink.svelte index 057d7355dc..b3202b4057 100644 --- a/ceremony/src/lib/components/Blink.svelte +++ b/ceremony/src/lib/components/Blink.svelte @@ -28,7 +28,7 @@ function startRandomBlinking() { $effect(() => { if (sleep) { - eye = "-" + eye = "×" clearInterval(blinkInterval) } else { eye = "0" diff --git a/ceremony/src/lib/components/Ceremony.svelte b/ceremony/src/lib/components/Ceremony.svelte index cbb36ab2e4..7f49f7d71a 100644 --- a/ceremony/src/lib/components/Ceremony.svelte +++ b/ceremony/src/lib/components/Ceremony.svelte @@ -5,12 +5,13 @@ import H3 from "$lib/components/typography/H3.svelte" import H2 from "$lib/components/typography/H2.svelte" import Install from "$lib/components/Install.svelte" import { start } from "$lib/client" -import H4 from "$lib/components/typography/H4.svelte" import { AddressForm, type ValidState } from "$lib/components/address" import Blink from "$lib/components/Blink.svelte" import Tweet from "$lib/components/Tweet.svelte" import SwimLoad from "$lib/components/SwimLoad.svelte" import { getNumberSuffix } from "$lib/utils/utils.ts" +import Text from "$lib/components/typography/Text.svelte" +import Status from "$lib/components/Status.svelte" type Props = { contributor: ContributorState @@ -31,52 +32,60 @@ let addressValidState: ValidState = $state("PENDING")
{#if contributor.state === 'inQueue'} -

You are {contributor.queueState.position}{getNumberSuffix(contributor.queueState.position)} in queue

- -

Queue length: {contributor.queueState.count}

-

Waiting time: {contributor.queueState.estimatedTime} minutes (est.). -

- - {#if contributor.clientState === 'offline'} - - {/if} + + + +
+

You are {contributor.queueState.position}{getNumberSuffix(contributor.queueState.position)} in queue

+ + + +
+

Queue length: {contributor.queueState.count}

+

Waiting time: {contributor.queueState.estimatedTime} minutes + (est.). +

+
+ +
+

Get your nft

+ (addressValidState = result)}/> +
+
+ {:else if contributor.state === 'contribute'} +

Starting contribution...

{:else if contributor.state === 'contributing'} +

Contributing...

{:else if contributor.state === 'verifying'} +

Verifying your contribution...

{:else if contributor.state === 'contributed'}

Thank you! Your contribution is completed.

-

Get your nft

- (addressValidState = result)}/> - +
- {:else if contributor.state === 'noClient'} + +

No client. Cannot start contribution.

- + {:else}

Not able to contribute at this time

+ {/if}
-

- -

-

{contributor.clientState}

\ No newline at end of file diff --git a/ceremony/src/lib/components/Code.svelte b/ceremony/src/lib/components/Code.svelte new file mode 100644 index 0000000000..3ebb5b31a6 --- /dev/null +++ b/ceremony/src/lib/components/Code.svelte @@ -0,0 +1,68 @@ + + + +
+ {#each words as word, index} + + {#if index !== words.length - 1} +

-

+ {/if} + {/each} +
+ \ No newline at end of file diff --git a/ceremony/src/lib/components/Contribution.svelte b/ceremony/src/lib/components/Contribution.svelte new file mode 100644 index 0000000000..65c2fcc3c5 --- /dev/null +++ b/ceremony/src/lib/components/Contribution.svelte @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + +{#await getUserContribution(hash)} + +{:then contribution} + {#if contribution} +
+
+

Contributor: {contribution.user_name}

+
+ +
+
+

Public key

+
{decodeHexString(contribution.public_key)}
+ +
+ +
+

Signature

+
{decodeHexString(contribution.signature)}
+ +
+
+
+ {/if} +{/await} \ No newline at end of file diff --git a/ceremony/src/lib/components/Contributions.svelte b/ceremony/src/lib/components/Contributions.svelte new file mode 100644 index 0000000000..bc23543ad1 --- /dev/null +++ b/ceremony/src/lib/components/Contributions.svelte @@ -0,0 +1,46 @@ + +{#if contributions} + +
+
+
+
+
+ {#each contributions as contribution, index } + + + {(index + 1) * 10}M +
+ + {contribution.user_name} +
+
+ {#if index !== contributions.length - 1} +
+ {/if} + {/each} +
+
+{:else} + +{/if} \ No newline at end of file diff --git a/ceremony/src/lib/components/Install.svelte b/ceremony/src/lib/components/Install.svelte index 5cb33e3f8a..6823ad83ac 100644 --- a/ceremony/src/lib/components/Install.svelte +++ b/ceremony/src/lib/components/Install.svelte @@ -3,32 +3,46 @@ import { toast } from "svelte-sonner" import H1 from "$lib/components/typography/H1.svelte" import Button from "$lib/components/Button.svelte" +let open = $state(false) + let command = "docker run -p 4919:4919 -it haitlahcen/union-mpc-cli:latest" + const copy = () => { navigator.clipboard.writeText(command) toast.success("Copied to clipboard", { position: "bottom-right" }) } - - - - $ - - - - {command} - - - - - +{#if open} +
+
+

How to

+ + + + $ + + + + {command} + + + + + + +
+
+{/if} + + + diff --git a/ceremony/src/lib/components/Join.svelte b/ceremony/src/lib/components/Join.svelte index 84329cabcc..3c890e76e4 100644 --- a/ceremony/src/lib/components/Join.svelte +++ b/ceremony/src/lib/components/Join.svelte @@ -5,6 +5,7 @@ import Text from "$lib/components/typography/Text.svelte" import { callJoinQueue, checkIfOpen } from "$lib/supabase" import type { ContributorState } from "$lib/stores/state.svelte.ts" import { toast } from "svelte-sonner" +import Code from "$lib/components/Code.svelte" type Props = { contributor: ContributorState @@ -13,46 +14,8 @@ type Props = { let { contributor }: Props = $props() let isOpenToPublic = $state(false) -let codeLoading = $state(false) let waitlistLoading = $state(false) -let words: Array = $state(new Array(6).fill("")) -let code = $derived(normalizeString(words)) - -function handlePaste(e: ClipboardEvent): void { - e.preventDefault() - const pastedText: string = e.clipboardData?.getData("text") || "" - const pastedWords: Array = pastedText.split(/\s+/).slice(0, 6) - words = [...pastedWords, ...new Array(6 - pastedWords.length).fill("")] -} - -function normalizeString(words: Array): string { - return words - .map(word => word.trim().toLowerCase()) - .join("") - .replace(/[^a-z0-9]/gi, "") -} - -async function handleCodeJoin() { - codeLoading = true - try { - console.log(code) - const codeOk = await callJoinQueue(code) - if (codeOk) { - contributor.setAllowanceState("hasRedeemed") - toast.success("Code successfully redeemed") - } else { - toast.error("The code is not valid") - } - } catch (error) { - console.error("Error redeeming code:", error) - toast.error("An error occurred while redeeming the code") - } finally { - codeLoading = false - words = new Array(6).fill("") - } -} - async function handleWaitlistJoin() { waitlistLoading = true try { @@ -83,30 +46,12 @@ $effect(() => {

Join the ceremony

-
-
- {#each words as word, index} - - {#if index !== words.length - 1} -

-

- {/if} - {/each} -
+ + Or + -
- - Or - -
diff --git a/ceremony/src/lib/components/Status.svelte b/ceremony/src/lib/components/Status.svelte new file mode 100644 index 0000000000..09bdae8793 --- /dev/null +++ b/ceremony/src/lib/components/Status.svelte @@ -0,0 +1,25 @@ + + +{#if contributor} +
+

+ +

+

{contributor.clientState}

+ {#if contributor.clientState === 'offline'} + + *You must be running the Ceremony Client to be able to contribute. + {/if} +
+{/if} \ No newline at end of file diff --git a/ceremony/src/lib/components/SwimLoad.svelte b/ceremony/src/lib/components/SwimLoad.svelte index 9525ac07fc..874d93451f 100644 --- a/ceremony/src/lib/components/SwimLoad.svelte +++ b/ceremony/src/lib/components/SwimLoad.svelte @@ -7,7 +7,7 @@ type Props = { current: number | null } -let { min = 0, max, current }: Props = $props() +let { min = 1, max, current }: Props = $props() let progress = $derived(current != null && max != null ? ((current - min) / (max - min)) * 100 : 0) let clampedProgress = $derived(Math.max(0, Math.min(100, progress))) diff --git a/ceremony/src/lib/components/Tweet.svelte b/ceremony/src/lib/components/Tweet.svelte index 73f34caed1..5511ad75fd 100644 --- a/ceremony/src/lib/components/Tweet.svelte +++ b/ceremony/src/lib/components/Tweet.svelte @@ -1,17 +1,22 @@ diff --git a/ceremony/src/lib/components/address/AddressForm.svelte b/ceremony/src/lib/components/address/AddressForm.svelte index 675c4da080..7fe1dbebcd 100644 --- a/ceremony/src/lib/components/address/AddressForm.svelte +++ b/ceremony/src/lib/components/address/AddressForm.svelte @@ -5,6 +5,8 @@ import { watch, Debounced } from "runed" import type { ValidState } from "./index.ts" import { isValidBech32Address } from "./validator.ts" import type { HTMLInputAttributes } from "svelte/elements" +import { insertWalletData } from "$lib/supabase" +import { user } from "$lib/stores/user.svelte.ts" interface Props extends HTMLInputAttributes { class?: string @@ -28,12 +30,31 @@ $effect(() => { if (validState === "INVALID") toast.error(`Address is not valid`) }) -const onAddressSubmit = (event: Event) => { +const onAddressSubmit = async (event: Event) => { event.preventDefault() if (!debouncedInputText.current) return const addressValidation = isValidBech32Address(debouncedInputText.current) validState = addressValidation ? "VALID" : "INVALID" onValidation(validState) + + const userId = user.session?.user.id + if (validState === "VALID") { + try { + if (!userId) return + const result = await insertWalletData({ + id: userId, + wallet: debouncedInputText.current + }) + if (result) { + toast.success("Wallet address saved successfully") + } else { + toast.error("Failed to save wallet address") + } + } catch (error) { + console.error("Error saving wallet address:", error) + toast.error("An error occurred while saving the wallet address") + } + } } diff --git a/ceremony/src/lib/layout/Navbar/index.svelte b/ceremony/src/lib/layout/Navbar/index.svelte index 19dd503b55..0d468bf5c1 100644 --- a/ceremony/src/lib/layout/Navbar/index.svelte +++ b/ceremony/src/lib/layout/Navbar/index.svelte @@ -27,7 +27,7 @@ async function logout() { let loggedIn = $derived(!!user.session?.user.id) -
+