Skip to content

Commit

Permalink
Merge branch 'develop' into feat/admin
Browse files Browse the repository at this point in the history
  • Loading branch information
frimoldi authored Jan 14, 2023
2 parents 309ed28 + 5ba1192 commit bd58fbd
Show file tree
Hide file tree
Showing 19 changed files with 467 additions and 101 deletions.
62 changes: 55 additions & 7 deletions src/components/AuditorForm/AuditorForm.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import React, { useEffect, useMemo, useState } from "react"
import { useDebounce } from "use-debounce"
import axios, { AxiosError } from "axios"
import { FaGithub } from "react-icons/fa"
import { FaDiscord, FaGithub } from "react-icons/fa"

import { Button } from "../../components/Button"
import { Input } from "../../components/Input"
import { Column, Row } from "../../components/Layout"
import { Field } from "../../pages/Claim/Field"

import { hasSpaces, onlyAscii } from "../../utils/strings"
import { useValidateDiscordHandle } from "../../hooks/api/auditors/useValidateDiscordHandle"
import { Text } from "../Text"
import config from "../../config"

export type AuditorFormValues = {
handle: string
githubHandle: string
discordHandle: string
discordHandle?: string
twitterHandle?: string
telegramHandle?: string
}
Expand Down Expand Up @@ -48,9 +51,17 @@ export const AuditorForm: React.FC<Props> = ({
const [githubVerificationError, setGithubVerificationError] = useState(false)

const [discordHandle, setDiscordHandle] = useState(initialValues?.discordHandle ?? "")
const [debouncedDiscordHandle] = useDebounce(discordHandle, 300)

const [twitterHandle, setTwitterHandle] = useState(initialValues?.twitterHandle ?? "")
const [telegramHandle, setTelegramHandle] = useState(initialValues?.telegramHandle ?? "")

const {
data: discordValidation,
isError: discordHandleValidationError,
isLoading: isValidatingDiscordHandle,
} = useValidateDiscordHandle(debouncedDiscordHandle)

/**
* Verify Handle
*/
Expand Down Expand Up @@ -139,10 +150,18 @@ export const AuditorForm: React.FC<Props> = ({
!!verifiedGithubHandle &&
!isVerifyingGithubHandle &&
verifiedGithubHandle === githubHandle &&
!!discordHandle,
[handle, verifiedGithubHandle, githubHandle, isVerifyingGithubHandle, discordHandle, verifiedHandle, isDirty]
(discordHandle === "" || discordValidation),
[
handle,
verifiedGithubHandle,
githubHandle,
isVerifyingGithubHandle,
discordHandle,
verifiedHandle,
discordValidation,
isDirty,
]
)

return (
<Column spacing="l">
<Row>
Expand Down Expand Up @@ -172,7 +191,36 @@ export const AuditorForm: React.FC<Props> = ({
</Field>
</Row>
<Row>
<Field label="DISCORD *">
<Field
label="DISCORD (optional)"
error={discordHandleValidationError}
errorMessage={"Handle must join Sherlock's Discord server"}
detail={
<Row spacing="xs">
{isValidatingDiscordHandle && <Text>Validtating...</Text>}
{discordValidation && (
<>
<FaDiscord />
<Text>{discordValidation.handle}</Text>
<Text variant="secondary">{`#${discordValidation.discriminator}`}</Text>
</>
)}
{!isValidatingDiscordHandle && !discordValidation && (
<Row spacing="xs" alignment={["start", "center"]}>
<Text variant="secondary">You must join Sherlock's Discord server first.</Text>
<Button
size="small"
variant="secondary"
onClick={() => window.open(config.discordServerLink, "blank")}
>
<FaDiscord />
&nbsp; Join Discord
</Button>
</Row>
)}
</Row>
}
>
<Input
value={discordHandle}
onChange={setDiscordHandle}
Expand Down Expand Up @@ -205,7 +253,7 @@ export const AuditorForm: React.FC<Props> = ({
onSubmit({
handle,
githubHandle,
discordHandle,
discordHandle: discordValidation?.handle,
telegramHandle,
twitterHandle,
})
Expand Down
5 changes: 5 additions & 0 deletions src/config/ConfigType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,9 @@ export type Config = {
* Airdrop claimable date
*/
airdropClaimableTimestamp: number

/**
* Link to Sherlock's Discord server
*/
discordServerLink: string
}
1 change: 1 addition & 0 deletions src/config/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ export const config: Config = {
nexusMutualStartTimestamp: parseInt(process.env.REACT_APP_NEXUS_MUTUAL_START_TIMESTAMP as string),
airdropAdress: process.env.REACT_APP_AIRDROP_ADDRESS as string,
airdropClaimableTimestamp: parseInt(process.env.REACT_APP_AIRDROP_CLAIMABLE_TIMESTAMP as string),
discordServerLink: process.env.REACT_APP_DISCORD_SERVER_LINK as string,
}
5 changes: 3 additions & 2 deletions src/config/mainnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ export const config: Config = {
networkId: 1,
sherBuyEntryDeadline: 1647100800,
alchemyApiUrl: "wss://eth-mainnet.alchemyapi.io/v2/H7GQZq65vKCHEh5cnz_luQmYM8HWWcr-",
indexerBaseUrl: "https://mainnet.indexer.sherlock.xyz/",
contestsApiBaseUrl: "https://mainnet.contest.sherlock.xyz/",
indexerBaseUrl: "https://mainnet-indexer.sherlock.xyz/",
contestsApiBaseUrl: "https://mainnet-contest.sherlock.xyz/",
sherlockAddress: "0x0865a889183039689034dA55c1Fd12aF5083eabF",
sherlockProtocolManagerAddress: "0x3d0b8A0A10835Ab9b0f0BeB54C5400B8aAcaa1D3",
sherlockClaimManagerAddress: "0xFeEDD254ae4B7c44A0472Bb836b813Ce4625Eb84",
Expand All @@ -22,4 +22,5 @@ export const config: Config = {
nexusMutualStartTimestamp: 1666137600,
airdropAdress: "0x731751e3C0B67014b560F98b26601A5587F954B0",
airdropClaimableTimestamp: 1682848801,
discordServerLink: "discord.gg/MABEWyASkp",
}
9 changes: 7 additions & 2 deletions src/hooks/api/auditors/useJoinContest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,22 @@ import { useMutation, useQueryClient } from "react-query"
import { useAccount } from "wagmi"
import { joinContest as joinContestUrl } from "../urls"
import { contests as contestsAPI } from "../axios"
import { contestantQueryKey } from "../contests"
import { AxiosError } from "axios"
import { FormError } from "../../../utils/Error"
import { contestantQueryKey } from "../contests/useContestant"

type JoinContestResponseData = {
repo_name: string
}

type JoinContest = {
repoName: string
judging: boolean
}

type JoinContestParams = {
handle: string
judging: boolean
}

export const useJoinContest = (contestId: number) => {
Expand All @@ -29,10 +31,12 @@ export const useJoinContest = (contestId: number) => {
const { data } = await contestsAPI.post<JoinContestResponseData>(joinContestUrl(), {
handle: params.handle,
contest_id: contestId,
judging: params.judging,
})

return {
repoName: data.repo_name,
judging: params.judging,
}
} catch (error) {
const axiosError = error as AxiosError
Expand All @@ -47,10 +51,11 @@ export const useJoinContest = (contestId: number) => {
)

const joinContest = useCallback(
async (handle: string) => {
async (handle: string, judging: boolean = false) => {
try {
mutate({
handle,
judging,
})
} catch (error) {
console.error(error)
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/api/auditors/useSignUp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type SignUpResponseData = {
type SignUpParams = {
handle: string
githubHandle: string
discordHandle: string
discordHandle?: string
twitterHandle?: string
telegramHandle?: string
address: string
Expand Down
30 changes: 30 additions & 0 deletions src/hooks/api/auditors/useValidateDiscordHandle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useQuery } from "react-query"
import { contests as contestsAPI } from "../axios"
import { validateDiscordHandle as validateDiscordHandleUrl } from "../urls"

type ValidateDiscordHandleResponse = {
handle: string
discriminator: number
}

type DiscordHandleValidation = {
handle: string
discriminator: number
}

export const validateDiscordHandleKey = (handle: string) => ["validate-discord", handle]
export const useValidateDiscordHandle = (handle?: string) =>
useQuery<DiscordHandleValidation, Error>(
validateDiscordHandleKey(handle ?? ""),
async () => {
const { data } = await contestsAPI.get<ValidateDiscordHandleResponse>(validateDiscordHandleUrl(handle ?? ""))

return {
handle: data.handle,
discriminator: data.discriminator,
}
},
{
enabled: !!handle,
}
)
50 changes: 12 additions & 38 deletions src/hooks/api/contests.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useCallback, useEffect, useMemo } from "react"
import { useMutation, useQuery, useQueryClient, UseQueryOptions } from "react-query"
import { useMutation, useQuery, useQueryClient } from "react-query"
import { useAccount, useSignTypedData } from "wagmi"
import { contests as contestsAPI } from "./axios"
import { contestantQueryKey } from "./contests/useContestant"
import {
getContests as getContestsUrl,
getContest as getContestUrl,
contestOptIn as contestOptInUrl,
getContestant as getContestantUrl,
getScoreboard as getScoreboardUrl,
} from "./urls"

Expand All @@ -27,13 +27,8 @@ export type Contest = {
leadSeniorAuditorHandle: string
private: boolean
fullPayment: number
}

export type Contestant = {
repo: string
countsTowardsRanking: boolean
handle: string
isTeam: boolean
judgingPrizePool?: number
jugdingEndDate?: number // Timestamp in seconds.
}

export type Scoreboard = {
Expand All @@ -58,6 +53,8 @@ type GetContestsResponseData = {
lead_senior_auditor_handle: string
private: boolean
full_payment: number
judging_ends_at?: number
judging_prize_pool: number | null
}[]

export const contestsQueryKey = "contests"
Expand All @@ -78,6 +75,8 @@ export const useContests = () =>
leadSeniorAuditorHandle: d.lead_senior_auditor_handle,
private: d.private,
fullPayment: d.full_payment,
judgingPrizePool: d.judging_prize_pool ?? undefined,
jugdingEndDate: d.judging_ends_at,
}))
})

Expand All @@ -96,6 +95,8 @@ type GetContestResponseData = {
lead_senior_auditor_handle: string
private: boolean
full_payment: number
judging_prize_pool: number | null
judging_ends_at?: number
}

export const contestQueryKey = (id: number) => ["contest", id]
Expand All @@ -118,38 +119,11 @@ export const useContest = (id: number) =>
leadSeniorAuditorHandle: response.lead_senior_auditor_handle,
private: response.private,
fullPayment: response.full_payment,
judgingPrizePool: response.judging_prize_pool ?? undefined,
jugdingEndDate: response.judging_ends_at,
}
})

type GetContestantResponseData = {
repo_name: string
counts_towards_ranking: boolean
handle: string
is_team: boolean
} | null
export const contestantQueryKey = (address: string, contestId: number) => ["contestant", address, contestId]
export const useContestant = (address: string, contestId: number, opts?: UseQueryOptions<Contestant | null, Error>) =>
useQuery<Contestant | null, Error>(
contestantQueryKey(address, contestId),
async () => {
try {
const { data } = await contestsAPI.get<GetContestantResponseData>(getContestantUrl(address, contestId))

if (!data) return null

return {
repo: data.repo_name,
countsTowardsRanking: data.counts_towards_ranking,
handle: data.handle,
isTeam: data.is_team,
}
} catch (error) {
return null
}
},
opts
)

export const useOptInOut = (contestId: number, optIn: boolean, handle: string) => {
const domain = {
name: "Sherlock Contest",
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/api/contests/useContestSignUp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { useAccount } from "wagmi"
import { FormError } from "../../../utils/Error"

import { contests as contestsAPI } from "../axios"
import { contestantQueryKey } from "../contests"
import { contestSignUp as contestSignUpUrl } from "../urls"
import { contestantQueryKey } from "./useContestant"

type SignUp = {
repo: string
Expand Down
Loading

0 comments on commit bd58fbd

Please sign in to comment.