diff --git a/web/src/hooks/useSpamEvidence.ts b/web/src/hooks/useSpamEvidence.ts new file mode 100644 index 000000000..93f80d6b3 --- /dev/null +++ b/web/src/hooks/useSpamEvidence.ts @@ -0,0 +1,44 @@ +import { useQuery } from "@tanstack/react-query"; +import { request } from "graphql-request"; + +import { isKlerosNeo, isKlerosUniversity, isTestnetDeployment } from "src/consts"; +import { graphql } from "src/graphql"; +import { isUndefined } from "src/utils"; + +const spamEvidenceQuery = graphql(` + query SpamEvidences($deployment: CourtV2Deployment!) { + courtv2EvidenceSpamsByDeployment(deployment: $deployment) { + disputeEvidenceIndex + dispute + } + } +`); + +type SpamEvidences = { + courtv2EvidenceSpamsByDeployment: { disputeEvidenceIndex: string; dispute: string }[]; +}; + +const getAtlasDeployment = () => { + if (isKlerosUniversity()) { + return "university"; + } else if (isKlerosNeo()) { + return "beta"; + } else if (isTestnetDeployment()) { + return "testnet"; + } else { + return "devnet"; + } +}; +const atlasUri = import.meta.env.REACT_APP_ATLAS_URI; + +export const useSpamEvidence = () => { + const isEnabled = !isUndefined(atlasUri); + + const variables = { deployment: getAtlasDeployment() }; + return useQuery({ + queryKey: [`evidenceSpamQuery`], + enabled: isEnabled, + staleTime: 60000, + queryFn: async () => await request(`${atlasUri}/graphql`, spamEvidenceQuery, variables), + }); +}; diff --git a/web/src/pages/Cases/CaseDetails/Evidence/index.tsx b/web/src/pages/Cases/CaseDetails/Evidence/index.tsx index 40f32dc4f..9a433d754 100644 --- a/web/src/pages/Cases/CaseDetails/Evidence/index.tsx +++ b/web/src/pages/Cases/CaseDetails/Evidence/index.tsx @@ -8,17 +8,18 @@ import { Button } from "@kleros/ui-components-library"; import DownArrow from "svgs/icons/arrow-down.svg"; +import { useSpamEvidence } from "hooks/useSpamEvidence"; + import { useDisputeDetailsQuery } from "queries/useDisputeDetailsQuery"; import { useEvidences } from "queries/useEvidences"; import { responsiveSize } from "styles/responsiveSize"; +import { Divider } from "components/Divider"; import EvidenceCard from "components/EvidenceCard"; import { SkeletonEvidenceCard } from "components/StyledSkeleton"; import EvidenceSearch from "./EvidenceSearch"; -import { Divider } from "components/Divider"; -import { spamEvidencesIds } from "src/consts"; const Container = styled.div` width: 100%; @@ -79,6 +80,7 @@ const Evidence: React.FC = () => { const [search, setSearch] = useState(); const [debouncedSearch, setDebouncedSearch] = useState(); const [showSpam, setShowSpam] = useState(false); + const { data: spamEvidences } = useSpamEvidence(); const { data } = useEvidences(disputeData?.dispute?.externalDisputeId?.toString(), debouncedSearch); @@ -93,12 +95,31 @@ const Evidence: React.FC = () => { latestEvidence.scrollIntoView({ behavior: "smooth" }); }, [ref]); + const flattenedSpamEvidences = useMemo( + () => + spamEvidences?.courtv2EvidenceSpamsByDeployment.reduce((acc, current) => { + if (current.dispute === id) { + acc.push(current.disputeEvidenceIndex); + return acc; + } + return acc; + }, []), + [id, spamEvidences] + ); + + const isSpam = useCallback( + (evidenceId: string) => { + return Boolean(flattenedSpamEvidences?.includes(evidenceId)); + }, + [flattenedSpamEvidences] + ); + const evidences = useMemo(() => { if (!data?.evidences) return; const spamEvidences = data.evidences.filter((evidence) => isSpam(evidence.id)); const realEvidences = data.evidences.filter((evidence) => !isSpam(evidence.id)); return { realEvidences, spamEvidences }; - }, [data]); + }, [data, isSpam]); return ( @@ -142,8 +163,4 @@ const Evidence: React.FC = () => { ); }; -const isSpam = (id: string) => { - return spamEvidencesIds.includes(id); -}; - export default Evidence; diff --git a/web/tsconfig.json b/web/tsconfig.json index 8b8b98b97..e4683ef39 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -67,7 +67,8 @@ "resolveJsonModule": true, "target": "ES2020", "lib": [ - "ESNext.Array" + "ESNext.Array", + "dom" ], "types": [ "vite/client",