diff --git a/packages/nextjs/app/_components/ApplyEligibilityLink.tsx b/packages/nextjs/app/_components/ApplyEligibilityLink.tsx index 93d05f28..0fc31818 100644 --- a/packages/nextjs/app/_components/ApplyEligibilityLink.tsx +++ b/packages/nextjs/app/_components/ApplyEligibilityLink.tsx @@ -4,7 +4,6 @@ import Link from "next/link"; import { useConnectModal } from "@rainbow-me/rainbowkit"; import { useAccount } from "wagmi"; import { LockClosedIcon, LockOpenIcon } from "@heroicons/react/24/outline"; -import { useBGBuilderData } from "~~/hooks/useBGBuilderData"; import { useSpeedRunChallengeEligibility } from "~~/hooks/useSpeedRunChallengeEligibility"; import { REQUIRED_CHALLENGE_COUNT } from "~~/utils/eligibility-criteria"; @@ -61,25 +60,18 @@ const FeedbackMessage = ({ export const ApplyEligibilityLink = () => { const { isConnected, address: connectedAddress } = useAccount(); - const { isBuilderPresent, isLoading: isFetchingBuilderData } = useBGBuilderData(connectedAddress); const { openConnectModal } = useConnectModal(); - const { - isLoading: isLoadingSRE, - isEligible: isEligibleSRE, - completedChallengesCount, - } = useSpeedRunChallengeEligibility(connectedAddress); + const { isLoading, isEligible, completedChallengesCount } = useSpeedRunChallengeEligibility(connectedAddress); let builderStatus: BuilderStatus = "notConnected"; - if (!isConnected || isLoadingSRE) { + if (!isConnected || isLoading) { builderStatus = "notConnected"; - } else if (isEligibleSRE || isBuilderPresent) { + } else if (isEligible) { builderStatus = "eligible"; } else { builderStatus = "notElegible"; } - const isFetching = isLoadingSRE || (isEligibleSRE === false && isFetchingBuilderData); - return (

Do you qualify?

@@ -101,7 +93,7 @@ export const ApplyEligibilityLink = () => { if (!isConnected && openConnectModal) openConnectModal(); }} > - {isFetching ? ( + {isLoading ? ( ) : ( diff --git a/packages/nextjs/app/_components/EcosystemGrants.tsx b/packages/nextjs/app/_components/EcosystemGrants.tsx index 75148900..96d106ab 100644 --- a/packages/nextjs/app/_components/EcosystemGrants.tsx +++ b/packages/nextjs/app/_components/EcosystemGrants.tsx @@ -1,4 +1,5 @@ import Image from "next/image"; +import XIcon from "~~/components/assets/XIcon"; import { getAllEcosystemGrants } from "~~/services/database/grants"; const EcosystemGrantsCard = ({ @@ -6,13 +7,13 @@ const EcosystemGrantsCard = ({ description, imageLink, amountGranted, - twitterLink, + xLink, }: { title: string; description: string; imageLink: string; amountGranted: string; - twitterLink: string; + xLink: string; }) => { return (
@@ -24,13 +25,13 @@ const EcosystemGrantsCard = ({

{description}

-
+
Amount: {Number(amountGranted).toFixed(2)} ETH
- - Twitter + +
@@ -58,7 +59,7 @@ export const EcosystemGrants = async () => { description={grant.description} imageLink={grant.imgLink} amountGranted={grant.amountGranted} - twitterLink={grant.twitterLink} + xLink={grant.xLink} /> ))}
diff --git a/packages/nextjs/app/admin/_components/GrantReview.tsx b/packages/nextjs/app/admin/_components/GrantReview.tsx index 90456dc3..121849fd 100644 --- a/packages/nextjs/app/admin/_components/GrantReview.tsx +++ b/packages/nextjs/app/admin/_components/GrantReview.tsx @@ -8,10 +8,11 @@ import { useNetwork } from "wagmi"; import { ArrowTopRightOnSquareIcon, QuestionMarkCircleIcon } from "@heroicons/react/20/solid"; import { PencilSquareIcon } from "@heroicons/react/24/outline"; import TelegramIcon from "~~/components/assets/TelegramIcon"; -import TwitterIcon from "~~/components/assets/TwitterIcon"; +import XIcon from "~~/components/assets/XIcon"; import { Address } from "~~/components/scaffold-eth"; import { useScaffoldContractWrite } from "~~/hooks/scaffold-eth"; -import { GrantData, GrantDataWithPrivateNote, SocialLinks } from "~~/services/database/schema"; +import { SocialLinks } from "~~/services/api/sre/schema"; +import { GrantData, GrantDataWithPrivateNote } from "~~/services/database/schema"; import { PROPOSAL_STATUS, ProposalStatusType } from "~~/utils/grants"; const BuilderSocials = ({ socialLinks }: { socialLinks?: SocialLinks }) => { @@ -19,20 +20,20 @@ const BuilderSocials = ({ socialLinks }: { socialLinks?: SocialLinks }) => { return ( <> - {socialLinks?.twitter && ( + {socialLinks?.socialX && ( - + )} - {socialLinks?.telegram && ( + {socialLinks?.socialTelegram && ( @@ -160,16 +161,9 @@ export const GrantReview = ({ grant, selected, toggleSelection }: GrantReviewPro
- {grant.builderData?.batch?.number && ( -
Batch #{grant.builderData.batch?.number}
+ {grant.builderData?.batchId?.number && ( +
Batch #{grant.builderData.batchId?.number}
)} - {grant.builderData?.builderCohort?.map(cohort => { - return ( -
-
{cohort.name}
-
- ); - })}
diff --git a/packages/nextjs/app/api/admin/signin/route.ts b/packages/nextjs/app/api/admin/signin/route.ts index 7db51516..45820a2d 100644 --- a/packages/nextjs/app/api/admin/signin/route.ts +++ b/packages/nextjs/app/api/admin/signin/route.ts @@ -1,6 +1,6 @@ import { NextResponse } from "next/server"; import { recoverTypedDataAddress } from "viem"; -import { findUserByAddress } from "~~/services/database/users"; +import { fetchBuilderData } from "~~/services/api/sre/builders"; import { EIP_712_DOMAIN, EIP_712_TYPES__ADMIN_SIGN_IN } from "~~/utils/eip712"; import { validateSafeSignature } from "~~/utils/safe-signature"; @@ -10,6 +10,7 @@ type AdminSignInBody = { isSafeSignature?: boolean; chainId?: number; }; + export async function POST(req: Request) { try { const { signer, signature, isSafeSignature, chainId } = (await req.json()) as AdminSignInBody; @@ -18,8 +19,8 @@ export async function POST(req: Request) { return new Response("Missing signer or signature", { status: 400 }); } - const signerData = await findUserByAddress(signer); - if (signerData.data?.role !== "admin") { + const userData = await fetchBuilderData(signer); + if (userData?.role !== "admin") { console.error("Unauthorized", signer); return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } diff --git a/packages/nextjs/app/api/builders/[builderAddress]/route.ts b/packages/nextjs/app/api/builders/[builderAddress]/route.ts deleted file mode 100644 index 12f3f416..00000000 --- a/packages/nextjs/app/api/builders/[builderAddress]/route.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { NextResponse } from "next/server"; -import { findUserByAddress } from "~~/services/database/users"; - -export async function GET(_request: Request, { params }: { params: { builderAddress: string } }) { - try { - const builderAddress = params.builderAddress; - const builderData = await findUserByAddress(builderAddress); - return NextResponse.json(builderData); - } catch (error) { - return NextResponse.json( - { error: "Internal Server Error" }, - { - status: 500, - }, - ); - } -} diff --git a/packages/nextjs/app/api/grants/[grantId]/review/route.tsx b/packages/nextjs/app/api/grants/[grantId]/review/route.tsx index 4e2fde47..b0eee07f 100644 --- a/packages/nextjs/app/api/grants/[grantId]/review/route.tsx +++ b/packages/nextjs/app/api/grants/[grantId]/review/route.tsx @@ -2,8 +2,8 @@ import { NextRequest, NextResponse } from "next/server"; import { EIP712TypedData } from "@safe-global/safe-core-sdk-types"; import { waitUntil } from "@vercel/functions"; import { recoverTypedDataAddress } from "viem"; +import { fetchBuilderData } from "~~/services/api/sre/builders"; import { getGrantById, reviewGrant } from "~~/services/database/grants"; -import { findUserByAddress } from "~~/services/database/users"; import { extractBuildId, sendBuildToSRE } from "~~/services/sre"; import { EIP_712_DOMAIN, EIP_712_TYPES__REVIEW_GRANT, EIP_712_TYPES__REVIEW_GRANT_WITH_NOTE } from "~~/utils/eip712"; import { PROPOSAL_STATUS, ProposalStatusType } from "~~/utils/grants"; @@ -89,9 +89,9 @@ export async function POST(req: NextRequest, { params }: { params: { grantId: st } // Only admins can review grants - const signerData = await findUserByAddress(signer); - - if (signerData.data?.role !== "admin") { + const signerData = await fetchBuilderData(signer); + if (signerData?.role !== "admin") { + console.error("Unauthorized", signer); return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } diff --git a/packages/nextjs/app/api/grants/[grantId]/route.ts b/packages/nextjs/app/api/grants/[grantId]/route.ts index 5aed5cb2..59c7ee7d 100644 --- a/packages/nextjs/app/api/grants/[grantId]/route.ts +++ b/packages/nextjs/app/api/grants/[grantId]/route.ts @@ -1,8 +1,8 @@ import { NextRequest, NextResponse } from "next/server"; import { EIP712TypedData } from "@safe-global/safe-core-sdk-types"; import { recoverTypedDataAddress } from "viem"; +import { fetchBuilderData } from "~~/services/api/sre/builders"; import { updateGrant } from "~~/services/database/grants"; -import { findUserByAddress } from "~~/services/database/users"; import { EIP_712_DOMAIN, EIP_712_TYPES__EDIT_GRANT } from "~~/utils/eip712"; import { validateSafeSignature } from "~~/utils/safe-signature"; @@ -55,8 +55,8 @@ export async function PATCH(req: NextRequest, { params }: { params: { grantId: s } // Only admins can edit grant - const signerData = await findUserByAddress(signer); - if (signerData.data?.role !== "admin") { + const signerData = await fetchBuilderData(signer); + if (signerData?.role !== "admin") { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } await updateGrant(grantId, { title, description, askAmount }, private_note); diff --git a/packages/nextjs/app/api/grants/new/route.ts b/packages/nextjs/app/api/grants/new/route.ts index fae04248..3e413a4d 100644 --- a/packages/nextjs/app/api/grants/new/route.ts +++ b/packages/nextjs/app/api/grants/new/route.ts @@ -1,7 +1,6 @@ import { NextResponse } from "next/server"; import { recoverTypedDataAddress } from "viem"; import { createGrant } from "~~/services/database/grants"; -import { findUserByAddress } from "~~/services/database/users"; import { EIP_712_DOMAIN, EIP_712_TYPES__APPLY_FOR_GRANT } from "~~/utils/eip712"; import { REQUIRED_CHALLENGE_COUNT, fetchAcceptedChallengeCount } from "~~/utils/eligibility-criteria"; @@ -24,19 +23,9 @@ export async function POST(req: Request) { return NextResponse.json({ error: "Invalid form details submitted" }, { status: 400 }); } - // Verify if the builder is present (legacy BG check) - const builder = await findUserByAddress(signer); - let eligible = false; - if (builder.exists) { - eligible = true; - } else { - // New SRE challenge check - const completed = await fetchAcceptedChallengeCount(signer); - if (completed >= REQUIRED_CHALLENGE_COUNT) { - eligible = true; - } - } - if (!eligible) { + // Legacy BG builder presence check removed. All eligibility is now based on the new SpeedRunEthereum system. If needed we could try do some kind of ROLE validation and make sure OG BuidlGuidl members that that certain ROLE in new SRE database. + const completed = await fetchAcceptedChallengeCount(signer); + if (completed < REQUIRED_CHALLENGE_COUNT) { return NextResponse.json( { error: `Only builders with at least ${REQUIRED_CHALLENGE_COUNT} accepted SpeedRun Ethereum challenges can submit for grants`, diff --git a/packages/nextjs/app/api/grants/review/route.tsx b/packages/nextjs/app/api/grants/review/route.tsx index bb7847fa..eaa1cbbc 100644 --- a/packages/nextjs/app/api/grants/review/route.tsx +++ b/packages/nextjs/app/api/grants/review/route.tsx @@ -2,8 +2,8 @@ import { headers } from "next/headers"; import { NextRequest, NextResponse } from "next/server"; import { EIP712TypedData } from "@safe-global/safe-core-sdk-types"; import { recoverTypedDataAddress } from "viem"; +import { fetchBuilderData } from "~~/services/api/sre/builders"; import { getAllGrantsForReview, reviewGrant } from "~~/services/database/grants"; -import { findUserByAddress } from "~~/services/database/users"; import { EIP_712_DOMAIN, EIP_712_TYPES__REVIEW_GRANT_BATCH } from "~~/utils/eip712"; import { PROPOSAL_STATUS, ProposalStatusType } from "~~/utils/grants"; import { validateSafeSignature } from "~~/utils/safe-signature"; @@ -26,8 +26,8 @@ export async function GET() { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } - const signerData = await findUserByAddress(address); - if (signerData.data?.role !== "admin") { + const signerData = await fetchBuilderData(address); + if (signerData?.role !== "admin") { console.error("Unauthorized", address); return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } @@ -76,8 +76,8 @@ export async function POST(req: NextRequest) { } // Only admins can review grants - const signerData = await findUserByAddress(signer); - if (signerData.data?.role !== "admin") { + const signerData = await fetchBuilderData(signer); + if (signerData?.role !== "admin") { console.error("Unauthorized", signer); return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } diff --git a/packages/nextjs/app/apply/_component/SubmitButton.tsx b/packages/nextjs/app/apply/_component/SubmitButton.tsx index 397046e6..d5debd40 100644 --- a/packages/nextjs/app/apply/_component/SubmitButton.tsx +++ b/packages/nextjs/app/apply/_component/SubmitButton.tsx @@ -2,7 +2,6 @@ import { useFormStatus } from "react-dom"; import { useAccount } from "wagmi"; -import { useBGBuilderData } from "~~/hooks/useBGBuilderData"; import { useSpeedRunChallengeEligibility } from "~~/hooks/useSpeedRunChallengeEligibility"; import { REQUIRED_CHALLENGE_COUNT } from "~~/utils/eligibility-criteria"; @@ -10,16 +9,9 @@ import { REQUIRED_CHALLENGE_COUNT } from "~~/utils/eligibility-criteria"; const SubmitButton = () => { const { pending } = useFormStatus(); const { isConnected, address: connectedAddress } = useAccount(); - const { isBuilderPresent, isLoading: isFetchingBuilderData } = useBGBuilderData(connectedAddress); - const { - isLoading: isLoadingSRE, - isEligible: isEligibleSRE, - completedChallengesCount, - } = useSpeedRunChallengeEligibility(connectedAddress); + const { isLoading, isEligible, completedChallengesCount } = useSpeedRunChallengeEligibility(connectedAddress); - const isEligible = isEligibleSRE || isBuilderPresent; - const isFetching = isLoadingSRE || (isEligibleSRE === false && isFetchingBuilderData); - const isSubmitDisabled = !isConnected || isFetching || !isEligible || pending; + const isSubmitDisabled = !isConnected || isLoading || !isEligible || pending; let tooltip = ""; if (!isConnected) { @@ -33,7 +25,7 @@ const SubmitButton = () => { return (
diff --git a/packages/nextjs/components/assets/TwitterIcon.tsx b/packages/nextjs/components/assets/TwitterIcon.tsx deleted file mode 100644 index 5d4c946d..00000000 --- a/packages/nextjs/components/assets/TwitterIcon.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from "react"; - -const TwitterIcon = (props: React.JSX.IntrinsicAttributes & React.SVGProps) => ( - - Twitter - - -); - -export default TwitterIcon; diff --git a/packages/nextjs/components/assets/XIcon.tsx b/packages/nextjs/components/assets/XIcon.tsx new file mode 100644 index 00000000..ac68516d --- /dev/null +++ b/packages/nextjs/components/assets/XIcon.tsx @@ -0,0 +1,12 @@ +import { SVGProps } from "react"; + +type XIconProps = SVGProps; + +const XIcon = ({ ...props }: XIconProps) => ( + + X + + +); + +export default XIcon; diff --git a/packages/nextjs/hooks/useBGBuilderData.ts b/packages/nextjs/hooks/useBGBuilderData.ts index 65f2c83b..64c99aca 100644 --- a/packages/nextjs/hooks/useBGBuilderData.ts +++ b/packages/nextjs/hooks/useBGBuilderData.ts @@ -1,15 +1,16 @@ import useSWRImmutable from "swr/immutable"; -import { BuilderDataResponse } from "~~/services/database/schema"; +import { BuilderData } from "~~/services/api/sre/schema"; +import { fetchBuilderData } from "~~/services/api/sre/builders"; export const useBGBuilderData = (address?: string) => { const { - data: responseData, + data, isLoading, error, - } = useSWRImmutable(address ? `/api/builders/${address}` : null); + } = useSWRImmutable( + address ? `builder-${address}` : null, + () => fetchBuilderData(address!) + ); - const data = responseData?.data; - const isBuilderPresent = responseData?.exists ?? false; - - return { isLoading, error, data, isBuilderPresent }; + return { isLoading, error, data }; }; diff --git a/packages/nextjs/services/api/sre/builders.ts b/packages/nextjs/services/api/sre/builders.ts new file mode 100644 index 00000000..83474819 --- /dev/null +++ b/packages/nextjs/services/api/sre/builders.ts @@ -0,0 +1,33 @@ +import { BuilderData, SocialLinks } from "./schema"; + +export const SRE_ENDPOINT = "https://speedrunethereum.com"; + +export async function fetchBuilderData(address: string): Promise { + try { + const res = await fetch(`${SRE_ENDPOINT}/api/users/${address}`); + + if (!res.ok) return undefined; + + const apiData = await res.json(); + const user = apiData.user; + + const socialLinks: SocialLinks = { + socialX: user.socialX, + socialGithub: user.socialGithub, + socialDiscord: user.socialDiscord, + socialTelegram: user.socialTelegram, + socialInstagram: user.socialInstagram, + socialEmail: user.socialEmail, + }; + + return { + userAddress: user.userAddress, + role: user.role ? user.role.toLowerCase() : undefined, + socialLinks, + batchId: user.batchId ? { number: String(Number(user.batchId) - 1), status: user.batchStatus } : undefined, + }; + } catch (error) { + console.error("Failed to fetch builder data:", error); + return undefined; + } +} diff --git a/packages/nextjs/services/api/sre/schema.ts b/packages/nextjs/services/api/sre/schema.ts new file mode 100644 index 00000000..a6b8783f --- /dev/null +++ b/packages/nextjs/services/api/sre/schema.ts @@ -0,0 +1,15 @@ +export type SocialLinks = { + socialX?: string; + socialGithub?: string; + socialDiscord?: string; + socialTelegram?: string; + socialInstagram?: string; + socialEmail?: string; +}; + +export type BuilderData = { + userAddress: string; + role?: "anonymous" | "user" | "admin"; + socialLinks?: SocialLinks; + batchId?: { number: string; status: string }; +}; diff --git a/packages/nextjs/services/database/ecosystemGrants.json b/packages/nextjs/services/database/ecosystemGrants.json index 0e82f4ad..7f0ae228 100644 --- a/packages/nextjs/services/database/ecosystemGrants.json +++ b/packages/nextjs/services/database/ecosystemGrants.json @@ -4,42 +4,42 @@ "name": "Jessy's Hacker House", "description": "Jessy is helping the BuidlGuidl find high-impact up-and-coming devs. Our goal is to fund developers on the edge and help them remain free agents to have the most open source impact.", "amountGranted": "0", - "twitterLink": "https://twitter.com/wehack247", + "xLink": "https://x.com/wehack247", "imgLink": "/assets/jessy-hacker-house.png" }, { "name": "Solidity By Example", "description": "Solidity-by-example is the best solidity resource out there. It stays up-to-date and Taz is always adding new examples.", "amountGranted": "13", - "twitterLink": "https://twitter.com/ProgrammerSmart", + "xLink": "https://x.com/ProgrammerSmart", "imgLink": "/assets/solidity-by-example.png" }, { "name": "W1nt3r", "description": "W1nt3r created EVMFromScratch.com and many other engaging onchain apps. He is a model app builder on Ethereum.", "amountGranted": "13", - "twitterLink": "https://x.com/w1nt3r_eth", + "xLink": "https://x.com/w1nt3r_eth", "imgLink": "/assets/w1nt3r-evm.png" } , { "name": "jtriley.eth", "description": "Ether Deck Mk2: A reasonably optimized, extensible smart account.", "amountGranted": "2.262", - "twitterLink": "https://twitter.com/jtriley_eth", + "xLink": "https://x.com/jtriley_eth", "imgLink": "/assets/etherdeck.png" } , { "name": "erhant.eth", "description": "Circomkit is a Circom circuit development & testing toolkit. It provides a simple CLI that abstracts away pathing & setups for SnarkJS commands...", "amountGranted": "2.262", - "twitterLink": "https://twitter.com/0xerhant", + "xLink": "https://x.com/0xerhant", "imgLink": "/assets/circomkit.png" } , { "name": "bytes032.eth", "description": "FindAudit is a public good platform that allows protocols to connect with over 100 auditors/audit firms in less than 48 hours.", "amountGranted": "2.262", - "twitterLink": "https://twitter.com/bytes032", + "xLink": "https://x.com/bytes032", "imgLink": "/assets/findaudit.png" } ] diff --git a/packages/nextjs/services/database/grants.ts b/packages/nextjs/services/database/grants.ts index 5021239d..064e896f 100644 --- a/packages/nextjs/services/database/grants.ts +++ b/packages/nextjs/services/database/grants.ts @@ -1,7 +1,7 @@ import { getFirestoreConnector } from "./firestoreDB"; -import { BuilderData, GrantData, GrantDataWithPrivateNote } from "./schema"; +import { GrantData, GrantDataWithPrivateNote } from "./schema"; +import { fetchBuilderData } from "../api/sre/builders"; import ecosystemGrants from "~~/services/database/ecosystemGrants.json"; -import { findUserByAddress } from "~~/services/database/users"; import { PROPOSAL_STATUS, ProposalStatusType } from "~~/utils/grants"; const firestoreDB = getFirestoreConnector(); @@ -63,13 +63,12 @@ export const getAllGrantsForReview = async () => { const privateNotes = doc.ref.collection("private_note"); const privateNotesSnapshot = await privateNotes.get(); const private_note = privateNotesSnapshot.empty ? undefined : privateNotesSnapshot.docs[0].data().note; - const builderDataResponse = await findUserByAddress(grantData.builder); - + const builderData = await fetchBuilderData(grantData.builder); return { id: doc.id, ...grantData, private_note, - builderData: builderDataResponse.exists ? (builderDataResponse.data as BuilderData) : undefined, + builderData, } as GrantDataWithPrivateNote; }); diff --git a/packages/nextjs/services/database/schema.ts b/packages/nextjs/services/database/schema.ts index 25d32699..bdbe0469 100644 --- a/packages/nextjs/services/database/schema.ts +++ b/packages/nextjs/services/database/schema.ts @@ -1,57 +1,5 @@ import type { Simplify } from "type-fest"; - -export type SocialLinks = { - twitter?: string; - github?: string; - discord?: string; - telegram?: string; - instagram?: string; - email?: string; -}; - -type Build = { - submittedTimestamp: number; - id: string; -}; - -type Status = { - text: string; - timestamp: number; -}; - -type Graduated = { - reason: string; - status: boolean; -}; - -export type BuilderData = { - id: string; - socialLinks?: SocialLinks; - role?: "anonymous" | "builder" | "admin"; - function?: string; - creationTimestamp?: number; - builds?: Build[]; - status?: Status; - graduated?: Graduated; - batch?: { - number: string; - status: string; - }; - builderCohort?: { id: string; name: string; url: string }[]; - stream?: { - balance: string; - cap: string; - frequency: number; - lastContract: number; - lastIndexedBlock: number; - streamAddress: string; - }; -}; - -export type BuilderDataResponse = { - exists: boolean; - data?: BuilderData; -}; +import type { BuilderData } from "../api/sre/schema"; export type GrantWithoutTimestamps = { id: string; diff --git a/packages/nextjs/services/database/users.ts b/packages/nextjs/services/database/users.ts deleted file mode 100644 index a30753f8..00000000 --- a/packages/nextjs/services/database/users.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { getFirestoreConnector } from "./firestoreDB"; -import { BuilderDataResponse } from "./schema"; -import { DocumentData } from "firebase-admin/firestore"; - -const firestoreDB = getFirestoreConnector(); -const getUserDoc = (id: string) => firestoreDB.collection("users").doc(id); -const getUserSnapshotById = (id: string) => getUserDoc(id).get(); - -export const findUserByAddress = async (builderAddress: string): Promise => { - try { - const builderSnapshot = await getUserSnapshotById(builderAddress); - if (!builderSnapshot.exists) { - return { exists: false }; - } - const data = builderSnapshot.data() as DocumentData; - return { exists: true, data: { id: builderSnapshot.id, ...data } }; - } catch (error) { - console.error("Error finding user by address:", error); - throw error; - } -}; diff --git a/packages/nextjs/utils/eligibility-criteria.ts b/packages/nextjs/utils/eligibility-criteria.ts index 0f86b23b..09b4ca68 100644 --- a/packages/nextjs/utils/eligibility-criteria.ts +++ b/packages/nextjs/utils/eligibility-criteria.ts @@ -1,9 +1,11 @@ +import { SRE_ENDPOINT } from "~~/services/api/sre/builders"; + export const REQUIRED_CHALLENGE_COUNT = 5; export async function fetchAcceptedChallengeCount(address: string): Promise { if (!address) return 0; try { - const res = await fetch(`https://speedrunethereum.com/api/user-challenges/${address}`); + const res = await fetch(`${SRE_ENDPOINT}/api/user-challenges/${address}`); if (!res.ok) return 0; const data = await res.json(); return data.challenges?.filter((ch: any) => ch.reviewAction === "ACCEPTED").length ?? 0;