Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ceremony): fixes #3035

Merged
merged 10 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 22 additions & 21 deletions ceremony/src/lib/components/Terminal/Activity.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,26 @@ function formatTimestamp(timestamp: string): string {
</script>

{#if activity.data}
{#each activity.data as item, i (item)}
{@const type = item.message.type}
{@const user = item.message.user}
<Print>
{formatTimestamp(item.created_at)} -
{#if type === "join_waitlist"}
{user} joined the waitlist
{:else if type === "redeem"}
{user} have redeemed a code
{:else if type === "join_queue"}
{user} joined the queue
{:else if type === "contribution_started"}
{user} have started their contribution
{:else if type === "contribution_submitted"}
{user} has submitted their contribution
{:else if type === "contribution_verified"}
{user} contribution just verified
{/if}
</Print>

{/each}
<div class="flex flex-col-reverse">
{#each activity.data as item, i (item)}
{@const type = item.message.type}
{@const user = item.message.user}
<Print>
{formatTimestamp(item.created_at)} -
{#if type === "join_waitlist"}
{user} joined the waitlist
{:else if type === "redeem"}
{user} has redeemed a code
{:else if type === "join_queue"}
{user} joined the queue
{:else if type === "contribution_started"}
{user} has started their contribution
{:else if type === "contribution_submitted"}
{user} has submitted their contribution
{:else if type === "contribution_verified"}
{user}'s contribution has just been verified
{/if}
</Print>
{/each}
</div>
{/if}
81 changes: 22 additions & 59 deletions ceremony/src/lib/components/Terminal/Authenticate.svelte
Original file line number Diff line number Diff line change
@@ -1,86 +1,49 @@
<script lang="ts">
import { type AuthProviders, Terminal } from "$lib/state/terminal.svelte.ts"
import { supabase } from "$lib/supabase/client.ts"
import { onDestroy, onMount } from "svelte"
import Button from "$lib/components/Terminal/Button.svelte"
import { cn } from "$lib/utils/utils.ts"
import { on } from "svelte/events"
import { sleep } from "$lib/utils/utils.ts"
import Print from "$lib/components/Terminal/Print.svelte"
import Buttons from "$lib/components/Terminal/Install/Buttons.svelte"
import { getState } from "$lib/state/index.svelte.ts"

type Props = {
terminal: Terminal
}

let { terminal }: Props = $props()

const providers: Array<AuthProviders> = ["GitHub", "Google"]

let focusedIndex = $state(0)
let redirecting = $state(false)
const { terminal } = getState()

async function logIn(provider: AuthProviders) {
//@ts-ignore
const thisProvider: "github" | "google" = provider.toLowerCase()
onMount(() => {
terminal.updateHistory({ text: "Unauthenticated user", replace: true })
terminal.updateHistory({ text: "Please authenticate with one of the following", replace: true })
})

async function logIn(provider: "github" | "google") {
terminal.updateHistory({ text: `Signing in with ${provider}`, replace: true })
await sleep(2000)
const { data, error } = await supabase.auth.signInWithOAuth({
provider: thisProvider,
provider: provider,
options: {
redirectTo: `/`
}
})
if (error || !data) {
terminal.updateHistory(`Error signing in using ${provider}`)
terminal.updateHistory({ text: `Error signing in using ${provider}`, type: "warning" })
} else {
redirecting = true
terminal.updateHistory(`Redirecting to ${provider}`)
terminal.updateHistory({ text: `Redirecting to ${provider}` })
}
}

let unsubscribe: (() => void) | undefined
let subscriptionTimeout: NodeJS.Timeout | undefined
onMount(() => {
terminal.setStep(1)
terminal.updateHistory("Please authenticate using one of the following")
subscriptionTimeout = setTimeout(() => {
unsubscribe = terminal.keys.subscribe(event => {
if (event) {
if (event.type !== "keydown") return
if (event.key === "ArrowUp") {
focusedIndex = (focusedIndex - 1 + providers.length) % providers.length
} else if (event.key === "ArrowDown") {
focusedIndex = (focusedIndex + 1) % providers.length
} else if (event.key === "Enter") {
logIn(providers[focusedIndex])
}
}
})
}, 200)
return () => {
if (subscriptionTimeout) {
clearTimeout(subscriptionTimeout)
}
if (unsubscribe) {
unsubscribe()
}
}
})
function trigger(value: "github" | "google") {
logIn(value)
}

onDestroy(() => {
terminal.clearHistory()
})
</script>

{#if !redirecting}

{#each providers as provider, index}
<Button
onmouseenter={() => focusedIndex = index}
class={cn(index === focusedIndex ? "bg-union-accent-500 text-black" : "", "capitalize")}
onclick={() => logIn(provider)}
>
&gt {provider}
</Button>
{/each}
<Buttons
data={[{text: "GitHub", action: "github"}, {text: "Google", action: "google"}]}
trigger={(value: 'github' | 'google') => trigger(value)} />
<Print><br></Print>
<Print class="uppercase !text-[#FD6363]">By logging in, I acknowledge that my name, email address, and optional wallet address will be part of the publicly viewable MPC ceremony data. I agree that this data will never be deleted as it is encoded in my contribution.</Print>

<Print class="uppercase !text-[#FD6363]">By signing in, I acknowledge that my public GPG key and signature will be permanently publicly available as it is cryptographically part of the MPC ceremony data. I am aware that my GPG key contains the email address I use to sign in.</Print>
{/if}
18 changes: 16 additions & 2 deletions ceremony/src/lib/components/Terminal/Button.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
<script lang="ts">
let { children, class: className = "", value = $bindable(), ...rest } = $props()
let { children, class: className = "", focus = undefined, value = $bindable(), ...rest } = $props()
</script>

<button
bind:this={value}
class="px-2 focus:blink block outline-none focus:ring-transparent focus:border-none text-sm sm:text-base {className}"
class="px-2 block outline-none focus:ring-transparent focus:border-none text-sm sm:text-base {className}"
class:terminal-blink={focus}
{...rest}>
{@render children()}
</button>

<style>
.terminal-blink {
animation: blink 1.35s step-end infinite;
}

@keyframes blink {
0%, 100% {
background-color: #A0ECFD;
color: black;
}
50% {
background-color: transparent;
color: white;
}
}
</style>
6 changes: 3 additions & 3 deletions ceremony/src/lib/components/Terminal/Ceremony.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ onDestroy(() => {

{:else if contributor.state === "verifying"}
{terminal.setStep(9)}
{terminal.updateHistory("Verifying your contribution...", {replace: true})}
{terminal.updateHistory({text:"Verifying your contribution...", replace: true})}

{:else if contributor.clientState === "offline" || contributor.clientState === undefined}
{terminal.setStep(5)}
Expand All @@ -41,11 +41,11 @@ onDestroy(() => {

{:else if contributor.state === 'contribute'}
{terminal.setStep(8)}
{terminal.updateHistory("Starting contribution...", {replace: true})}
{terminal.updateHistory({text: "Starting contribution...", replace: true})}

{:else if contributor.state === "contributing"}
{terminal.setStep(9)}
{terminal.updateHistory("Contributing...", {replace: true})}
{terminal.updateHistory({text: "Contributing...", replace: true})}

{:else}
<Print>Not able to contribute at this time</Print>
Expand Down
77 changes: 65 additions & 12 deletions ceremony/src/lib/components/Terminal/Code.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,69 @@
import { getState } from "$lib/state/index.svelte.ts"
import { onDestroy, onMount } from "svelte"
import Print from "$lib/components/Terminal/Print.svelte"
import Confirm from "$lib/components/Terminal/Confirm.svelte"
import Buttons from "$lib/components/Terminal/Install/Buttons.svelte"
import { sleep } from "$lib/utils/utils.ts"
import { callJoinQueue } from "$lib/supabase"

const { terminal } = getState()
const { terminal, contributor } = getState()

let inputCode: string = $state("")
let normalizedCode = $derived(normalizeString(inputCode))
let inputElement: HTMLInputElement
let showConfirm = $state(false)
let showInput = $state(true)

function normalizeString(input: string): string {
return input.toLowerCase().replace(/[^a-z0-9]/gi, "")
}

function handleKeyDown(event: KeyboardEvent) {
if (event.key === "Enter") {
console.log("XX keydown")
event.preventDefault()
showConfirm = true
terminal.updateHistory({ text: `Entered code: ${inputCode}`, duplicate: true })
terminal.updateHistory({
text: "If you enter the queue then you must have your browser and terminal open when it is your turn. you cannot leave the queue, and when it is your turn you need to contribute",
type: "warning",
duplicate: true
})
terminal.updateHistory({ text: "", lineBreak: true })
showInput = false
showConfirm = true
}
}

onMount(() => {
if (inputElement) {
inputElement.focus()
}
})

onDestroy(() => {
if (inputElement) {
inputElement.blur()
}
terminal.clearHistory()
})

function normalizeString(input: string): string {
return input.toLowerCase().replace(/[^a-z0-9]/gi, "")
}

async function handleCodeJoin() {
try {
terminal.updateHistory({ text: "Checking code...", duplicate: true })
console.log("code: ", normalizedCode)
await sleep(1000)
const codeOk = await callJoinQueue(normalizedCode)
if (codeOk) {
contributor.setAllowanceState("hasRedeemed")
terminal.updateHistory({ text: "Code successfully redeemed" })
} else {
terminal.updateHistory({ text: "The code is not valid", duplicate: true })
terminal.updateHistory({ text: "", lineBreak: true, duplicate: true })
onCancel()
}
} catch (error) {
console.error("Error redeeming code:", error)
terminal.updateHistory({ text: "An error occurred while redeeming the code" })
onCancel()
}
}

Expand All @@ -29,9 +73,14 @@ function onCancel() {
showConfirm = false
}

onDestroy(() => {
terminal.clearHistory()
})
function trigger(value: "enter" | "cancel") {
console.log("XX trigger 2")
if (value === "enter") {
handleCodeJoin()
} else if (value === "cancel") {
onCancel()
}
}
</script>

{#if showInput}
Expand All @@ -50,6 +99,10 @@ onDestroy(() => {
</div>
{/if}

{#if showConfirm}
<Confirm normalized={normalizedCode} code={inputCode} {onCancel}/>
{#if showConfirm && !showInput}
<Buttons
index={1}
data={[{text: "Enter the queue", action: "enter"}, {text: "Cancel", action: "cancel"}]}
trigger={(value: 'enter' | 'cancel') => trigger(value)}
/>
{/if}
Loading
Loading