diff --git a/ceremony/src/lib/client/http.ts b/ceremony/src/lib/client/http.ts index b772c84398..926cd85035 100644 --- a/ceremony/src/lib/client/http.ts +++ b/ceremony/src/lib/client/http.ts @@ -29,7 +29,7 @@ export const get = async ( export const post = async ( resource: string, params: Params, - body: Record, + body: Record | string, _fetch: Fetch = fetch ): Promise => { try { diff --git a/ceremony/src/lib/client/index.ts b/ceremony/src/lib/client/index.ts index 927eda7901..dbb3249ca7 100644 --- a/ceremony/src/lib/client/index.ts +++ b/ceremony/src/lib/client/index.ts @@ -54,3 +54,16 @@ export const checkState = async (): Promise => { return "offline" } } + +export const generateSecret = async (email: string | undefined) => { + if (!email) { + console.log("No email") + return + } + try { + return await post("secret_key", {}, email) + } catch (error) { + console.log("Error fetching secret:", error) + return undefined + } +} diff --git a/ceremony/src/lib/components/Button.svelte b/ceremony/src/lib/components/Button.svelte index 5403b5840e..be4517e179 100644 --- a/ceremony/src/lib/components/Button.svelte +++ b/ceremony/src/lib/components/Button.svelte @@ -1,14 +1,46 @@ - \ No newline at end of file +{#if href} + + {@render children()} + {#if loading} + + {/if} + +{:else} + +{/if} \ No newline at end of file diff --git a/ceremony/src/lib/components/Ceremony.svelte b/ceremony/src/lib/components/Ceremony.svelte index 7f49f7d71a..a1b1ebb05d 100644 --- a/ceremony/src/lib/components/Ceremony.svelte +++ b/ceremony/src/lib/components/Ceremony.svelte @@ -1,17 +1,13 @@
- {#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.). -

-
- -
-

Get your nft

- (addressValidState = result)}/> -
-
- - + {#if !contributor.userWallet} + + {:else if contributor.clientState === 'offline'} + + {:else if !contributor.downloadedSecret} + + {:else if contributor.state === "inQueue"} + {:else if contributor.state === 'contribute'} - -

Starting contribution...

- +

Starting contribution...

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

Contributing...

- +

Contributing...

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

Verifying your contribution...

- +

Verifying your contribution...

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

Thank you! Your contribution is completed.

- -
- - {:else if contributor.state === 'noClient'} - - -

No client. Cannot start contribution.

- + {:else} -

Not able to contribute at this time

- +

Not able to contribute at this time

{/if}
- -
-
\ No newline at end of file +
\ No newline at end of file diff --git a/ceremony/src/lib/components/Code.svelte b/ceremony/src/lib/components/Code.svelte index 3ebb5b31a6..3cc439907c 100644 --- a/ceremony/src/lib/components/Code.svelte +++ b/ceremony/src/lib/components/Code.svelte @@ -6,9 +6,10 @@ import Button from "$lib/components/Button.svelte" type Props = { contributor: ContributorState + secondary?: boolean } -let { contributor }: Props = $props() +let { contributor, secondary = false }: Props = $props() let words: Array = $state(new Array(6).fill("")) let code = $derived(normalizeString(words)) @@ -44,17 +45,39 @@ async function handleCodeJoin() { toast.error("An error occurred while redeeming the code") } finally { codeLoading = false - words = new Array(6).fill("") } } - +function handleKeyDown(event: KeyboardEvent, index: number) { + if (event.key === "Enter" || event.key === " ") { + event.preventDefault() + if (index < words.length - 1) { + // Move to next input + const nextInput = document.querySelector( + `input:nth-child(${2 * index + 3})` + ) as HTMLInputElement + nextInput?.focus() + } else if (event.key === "Enter") { + // On last input, trigger the USE CODE button only for Enter key + handleCodeJoin() + } + } else if (event.key === "Backspace" && words[index] === "" && index > 0) { + event.preventDefault() + // Move to previous input + const prevInput = document.querySelector( + `input:nth-child(${2 * index - 1})` + ) as HTMLInputElement + prevInput?.focus() + } +} +
{#each words as word, index} handleKeyDown(e, index)} class="bg-transparent border-b border-white w-20 text-center text-union-accent-500 outline-none focus:ring-0 focus:border-union-accent-500" style="--tw-ring-color: transparent;" /> @@ -63,6 +86,13 @@ async function handleCodeJoin() { {/if} {/each}
- \ No newline at end of file + +{#if secondary} + +{:else} + +{/if} diff --git a/ceremony/src/lib/components/Counter/index.svelte b/ceremony/src/lib/components/Counter/index.svelte index c51667e4b5..931f7b0f0a 100644 --- a/ceremony/src/lib/components/Counter/index.svelte +++ b/ceremony/src/lib/components/Counter/index.svelte @@ -1,17 +1,4 @@ + +{#if !download} +

Generate your PGP secret

+ + The MPC client automatically uses this secret to sign your contribution.
+ Your secret is locally generated through the MPC client. +
+ +{:else} +

Store your PGP secret

+ + Please store your secret somewhere safe, such as in your password manager. +
Never share your secret. +
This secret key is the only way to prove that you have contributed. +
+
+ + +
+{/if} \ No newline at end of file diff --git a/ceremony/src/lib/components/Install.svelte b/ceremony/src/lib/components/Install.svelte index 6823ad83ac..92619403f0 100644 --- a/ceremony/src/lib/components/Install.svelte +++ b/ceremony/src/lib/components/Install.svelte @@ -1,11 +1,18 @@ -{#if open} -
+{#if contributor} +
+ +

Run the mpc client

+ You need to have docker running to contribute.
+ For macOS you need to install + OrbStack + because docker desktop is too slow.
+ If you use docker desktop it is extremely likely that you lose your contribution slot. +
+ Once you have OrbStack/Docker running you should paste this in your terminal.
-

How to

- + - + $ @@ -38,11 +55,7 @@ const copy = () => { -
-
-{/if} - - - - + Is it running but still see this page? We support Chrome, FireFox and Brave.
For Brave disable the shields in the address bar.
+ +{/if} \ No newline at end of file diff --git a/ceremony/src/lib/components/Join.svelte b/ceremony/src/lib/components/Join.svelte index 3c890e76e4..224f02bb6c 100644 --- a/ceremony/src/lib/components/Join.svelte +++ b/ceremony/src/lib/components/Join.svelte @@ -6,6 +6,7 @@ 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" +import H2 from "$lib/components/typography/H2.svelte" type Props = { contributor: ContributorState @@ -45,13 +46,16 @@ $effect(() => {
+

Join the ceremony

+ Have an invite? Enter your code below.
- Or - -
diff --git a/ceremony/src/lib/components/Queue.svelte b/ceremony/src/lib/components/Queue.svelte new file mode 100644 index 0000000000..c0865a8376 --- /dev/null +++ b/ceremony/src/lib/components/Queue.svelte @@ -0,0 +1,32 @@ + + +

+ +

+
+

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

+ + +
+

Queue length: {contributor.queueState.count}

+

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

+
+
\ No newline at end of file diff --git a/ceremony/src/lib/components/Reward.svelte b/ceremony/src/lib/components/Reward.svelte new file mode 100644 index 0000000000..8c1f37af9b --- /dev/null +++ b/ceremony/src/lib/components/Reward.svelte @@ -0,0 +1,50 @@ + + + +
+

Add an address

+ You may receive rewards for successful contributions. + (addressValidState = result)} {contributor} /> + Or +

I don't want rewards

+ You can contribute without adding an address + +
\ No newline at end of file diff --git a/ceremony/src/lib/components/Status.svelte b/ceremony/src/lib/components/Status.svelte deleted file mode 100644 index 09bdae8793..0000000000 --- a/ceremony/src/lib/components/Status.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - -{#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 874d93451f..48c6f10854 100644 --- a/ceremony/src/lib/components/SwimLoad.svelte +++ b/ceremony/src/lib/components/SwimLoad.svelte @@ -16,11 +16,14 @@ let clampedProgress = $derived(Math.max(0, Math.min(100, progress))) {#if current && max}
- - + + + +
diff --git a/ceremony/src/lib/components/Thanks.svelte b/ceremony/src/lib/components/Thanks.svelte new file mode 100644 index 0000000000..146c13e7cf --- /dev/null +++ b/ceremony/src/lib/components/Thanks.svelte @@ -0,0 +1,22 @@ + +
+

Thank you!

+ Your contribution is completed. Thank you for securing the Union proving system! + You can tweet the cryptographic attestation of your contribution for extra transparency. + + + View contributions + +
\ No newline at end of file diff --git a/ceremony/src/lib/components/Tweet.svelte b/ceremony/src/lib/components/Tweet.svelte index 5511ad75fd..7d559d4ed2 100644 --- a/ceremony/src/lib/components/Tweet.svelte +++ b/ceremony/src/lib/components/Tweet.svelte @@ -22,5 +22,5 @@ function shareOnTwitter() { \ No newline at end of file diff --git a/ceremony/src/lib/components/Waitlist.svelte b/ceremony/src/lib/components/Waitlist.svelte new file mode 100644 index 0000000000..39a8959988 --- /dev/null +++ b/ceremony/src/lib/components/Waitlist.svelte @@ -0,0 +1,21 @@ + + +

You're on the waitlist

+When the ceremony opens to the public you will have position {contributor.waitListPosition} of public queue. +

Received an invite?

+You can skip the waitlist and join now. +
+ + \ No newline at end of file diff --git a/ceremony/src/lib/components/address/AddressForm.svelte b/ceremony/src/lib/components/address/AddressForm.svelte index 7fe1dbebcd..79e0a767ff 100644 --- a/ceremony/src/lib/components/address/AddressForm.svelte +++ b/ceremony/src/lib/components/address/AddressForm.svelte @@ -7,13 +7,15 @@ import { isValidBech32Address } from "./validator.ts" import type { HTMLInputAttributes } from "svelte/elements" import { insertWalletData } from "$lib/supabase" import { user } from "$lib/stores/user.svelte.ts" +import type { ContributorState } from "$lib/stores/state.svelte.ts" interface Props extends HTMLInputAttributes { class?: string onValidation: (valid: ValidState) => ValidState + contributor: ContributorState } -let { onValidation, class: className = "", ...props }: Props = $props() +let { onValidation, class: className = "", contributor, ...props }: Props = $props() let inputText = $state("") const debouncedInputText = new Debounced( @@ -47,6 +49,7 @@ const onAddressSubmit = async (event: Event) => { }) if (result) { toast.success("Wallet address saved successfully") + contributor.checkUserWallet(user.session?.user.id) } else { toast.error("Failed to save wallet address") } diff --git a/ceremony/src/lib/layout/Navbar/index.svelte b/ceremony/src/lib/layout/Navbar/index.svelte index 0d468bf5c1..e77e1061b7 100644 --- a/ceremony/src/lib/layout/Navbar/index.svelte +++ b/ceremony/src/lib/layout/Navbar/index.svelte @@ -2,11 +2,9 @@ import { supabase } from "$lib/supabase/client.ts" import { user } from "$lib/stores/user.svelte.ts" import { invalidateAll } from "$app/navigation" -import Link from "$lib/components/typography/Link.svelte" import Button from "$lib/components/Button.svelte" import NavLink from "$lib/layout/Navbar/NavLink.svelte" import Badge from "$lib/components/Badge.svelte" -import { ContributorState, getContributorState } from "$lib/stores/state.svelte.ts" let isOpen = $state(false) @@ -27,7 +25,7 @@ async function logout() { let loggedIn = $derived(!!user.session?.user.id) -
+