From 2d8daeffaee3908f37bcaafd58574643da92fc76 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Wed, 24 Jan 2024 14:37:13 +0530 Subject: [PATCH 01/16] feat(web): basic-indicator-ui-hardcoded --- web/src/assets/svgs/label-icons/appeal.svg | 11 ++++ web/src/assets/svgs/label-icons/evidence.svg | 3 + .../assets/svgs/label-icons/rewards-lost.svg | 3 + .../assets/svgs/label-icons/rewards-won.svg | 3 + web/src/assets/svgs/label-icons/vote.svg | 4 ++ web/src/assets/svgs/label-icons/voted.svg | 5 ++ .../DisputeCard/CardLabels/Label.tsx | 60 +++++++++++++++++++ .../DisputeCard/CardLabels/index.tsx | 27 +++++++++ .../components/DisputeCard/DisputeInfo.tsx | 2 + 9 files changed, 118 insertions(+) create mode 100644 web/src/assets/svgs/label-icons/appeal.svg create mode 100644 web/src/assets/svgs/label-icons/evidence.svg create mode 100644 web/src/assets/svgs/label-icons/rewards-lost.svg create mode 100644 web/src/assets/svgs/label-icons/rewards-won.svg create mode 100644 web/src/assets/svgs/label-icons/vote.svg create mode 100644 web/src/assets/svgs/label-icons/voted.svg create mode 100644 web/src/components/DisputeCard/CardLabels/Label.tsx create mode 100644 web/src/components/DisputeCard/CardLabels/index.tsx diff --git a/web/src/assets/svgs/label-icons/appeal.svg b/web/src/assets/svgs/label-icons/appeal.svg new file mode 100644 index 000000000..f7157ec13 --- /dev/null +++ b/web/src/assets/svgs/label-icons/appeal.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/web/src/assets/svgs/label-icons/evidence.svg b/web/src/assets/svgs/label-icons/evidence.svg new file mode 100644 index 000000000..79148204e --- /dev/null +++ b/web/src/assets/svgs/label-icons/evidence.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/src/assets/svgs/label-icons/rewards-lost.svg b/web/src/assets/svgs/label-icons/rewards-lost.svg new file mode 100644 index 000000000..6367e7b16 --- /dev/null +++ b/web/src/assets/svgs/label-icons/rewards-lost.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/src/assets/svgs/label-icons/rewards-won.svg b/web/src/assets/svgs/label-icons/rewards-won.svg new file mode 100644 index 000000000..54195deb4 --- /dev/null +++ b/web/src/assets/svgs/label-icons/rewards-won.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/web/src/assets/svgs/label-icons/vote.svg b/web/src/assets/svgs/label-icons/vote.svg new file mode 100644 index 000000000..da71a498b --- /dev/null +++ b/web/src/assets/svgs/label-icons/vote.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/src/assets/svgs/label-icons/voted.svg b/web/src/assets/svgs/label-icons/voted.svg new file mode 100644 index 000000000..2876498b5 --- /dev/null +++ b/web/src/assets/svgs/label-icons/voted.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/src/components/DisputeCard/CardLabels/Label.tsx b/web/src/components/DisputeCard/CardLabels/Label.tsx new file mode 100644 index 000000000..fa2f32fbc --- /dev/null +++ b/web/src/components/DisputeCard/CardLabels/Label.tsx @@ -0,0 +1,60 @@ +import React from "react"; +import styled, { useTheme } from "styled-components"; + +const LabelContainer = styled.div<{ contentColor: string; backgroundColor: string }>` + display: inline-flex; + padding: 4px 8px; + align-items: center; + gap: 10px; + border-radius: 300px; + background-color: ${({ backgroundColor }) => backgroundColor}; + div > svg { + fill: ${({ contentColor }) => contentColor}; + } + label { + color: ${({ contentColor }) => contentColor}; + } +`; +const IconContainer = styled.div` + height: 14px; + width: 14px; + display: flex; + align-items: center; + justify-content: center; +`; + +const StyledText = styled.label` + font-size: 12px; + font-weight: 400; +`; + +const createPair = (contentColor: string, backgroundColor: string) => ({ + contentColor, + backgroundColor, +}); + +interface ILabelProps { + text: string; + icon: React.FC>; + color: "red" | "green" | "blue" | "purple" | "grey"; +} +const Label: React.FC = ({ text, icon: Icon, color }) => { + const theme = useTheme(); + const COLORS = { + red: createPair(theme.error, theme.errorLight), + green: createPair(theme.success, theme.successLight), + blue: createPair(theme.primaryBlue, theme.mediumBlue), + purple: createPair(theme.secondaryPurple, theme.mediumPurple), + grey: createPair(theme.secondaryText, theme.lightGrey), + }; + return ( + + + + + {text} + + ); +}; + +export default Label; diff --git a/web/src/components/DisputeCard/CardLabels/index.tsx b/web/src/components/DisputeCard/CardLabels/index.tsx new file mode 100644 index 000000000..8c109e5ae --- /dev/null +++ b/web/src/components/DisputeCard/CardLabels/index.tsx @@ -0,0 +1,27 @@ +import React from "react"; +import styled from "styled-components"; +import Label from "./Label"; +import EvidenceIcon from "svgs/label-icons/evidence.svg"; +import { useDisputeDetailsQuery } from "hooks/queries/useDisputeDetailsQuery"; +import { useVotingHistory } from "hooks/queries/useVotingHistory"; + +const Container = styled.div` + width: 100%; + margin-top: 16px; +`; +interface ICardLabels { + disputeId: string; + round: string; +} + +const CardLabel: React.FC = ({ disputeId, round }) => { + const { data: disputeData } = useDisputeDetailsQuery(disputeId); + const { data: votingHistory } = useVotingHistory(disputeId); + return ( + + {" "} + + ); +}; +export default CardLabel; diff --git a/web/src/components/DisputeCard/DisputeInfo.tsx b/web/src/components/DisputeCard/DisputeInfo.tsx index cf7b431b8..0a4598c5d 100644 --- a/web/src/components/DisputeCard/DisputeInfo.tsx +++ b/web/src/components/DisputeCard/DisputeInfo.tsx @@ -12,6 +12,7 @@ import Field from "../Field"; import { getCourtsPath } from "pages/Courts/CourtDetails"; import { useCourtTree } from "hooks/queries/useCourtTree"; import { responsiveSize } from "styles/responsiveSize"; +import CardLabel from "./CardLabels"; const Container = styled.div<{ isList: boolean; isOverview?: boolean }>` display: flex; @@ -206,6 +207,7 @@ const DisputeInfo: React.FC = ({ isOverview={isOverview} /> )} + ); From 3496827f53754a265f9c67a455e8566afc9fd56a Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Fri, 26 Jan 2024 22:26:34 +0530 Subject: [PATCH 02/16] feat(web): card-labels-first-iteration --- web/src/assets/svgs/icons/eth.svg | 2 +- .../assets/svgs/label-icons/forgot-vote.svg | 5 ++ web/src/assets/svgs/label-icons/funded.svg | 4 + .../assets/svgs/label-icons/minus-circle.svg | 10 +++ .../DisputeCard/CardLabels/Label.tsx | 4 +- .../CardLabels/RewardsAndFundLabel.tsx | 46 +++++++++++ .../DisputeCard/CardLabels/index.tsx | 79 ++++++++++++++++--- .../components/DisputeCard/DisputeInfo.tsx | 10 ++- web/src/components/DisputeCard/index.tsx | 6 +- web/src/hooks/queries/useCasesQuery.ts | 5 ++ .../hooks/queries/useDisputeDetailsQuery.ts | 2 +- web/src/hooks/queries/useLabelInfoQuery.ts | 43 ++++++++++ 12 files changed, 201 insertions(+), 15 deletions(-) create mode 100644 web/src/assets/svgs/label-icons/forgot-vote.svg create mode 100644 web/src/assets/svgs/label-icons/funded.svg create mode 100644 web/src/assets/svgs/label-icons/minus-circle.svg create mode 100644 web/src/components/DisputeCard/CardLabels/RewardsAndFundLabel.tsx create mode 100644 web/src/hooks/queries/useLabelInfoQuery.ts diff --git a/web/src/assets/svgs/icons/eth.svg b/web/src/assets/svgs/icons/eth.svg index 449f2f658..da728a2d8 100644 --- a/web/src/assets/svgs/icons/eth.svg +++ b/web/src/assets/svgs/icons/eth.svg @@ -1,3 +1,3 @@ - + diff --git a/web/src/assets/svgs/label-icons/forgot-vote.svg b/web/src/assets/svgs/label-icons/forgot-vote.svg new file mode 100644 index 000000000..61df7f53d --- /dev/null +++ b/web/src/assets/svgs/label-icons/forgot-vote.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/web/src/assets/svgs/label-icons/funded.svg b/web/src/assets/svgs/label-icons/funded.svg new file mode 100644 index 000000000..7e02541da --- /dev/null +++ b/web/src/assets/svgs/label-icons/funded.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/web/src/assets/svgs/label-icons/minus-circle.svg b/web/src/assets/svgs/label-icons/minus-circle.svg new file mode 100644 index 000000000..2d0319676 --- /dev/null +++ b/web/src/assets/svgs/label-icons/minus-circle.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/web/src/components/DisputeCard/CardLabels/Label.tsx b/web/src/components/DisputeCard/CardLabels/Label.tsx index fa2f32fbc..fc6b2bec7 100644 --- a/web/src/components/DisputeCard/CardLabels/Label.tsx +++ b/web/src/components/DisputeCard/CardLabels/Label.tsx @@ -36,15 +36,17 @@ const createPair = (contentColor: string, backgroundColor: string) => ({ interface ILabelProps { text: string; icon: React.FC>; - color: "red" | "green" | "blue" | "purple" | "grey"; + color: "red" | "green" | "blue" | "purple" | "grey" | "lightPurple"; } const Label: React.FC = ({ text, icon: Icon, color }) => { const theme = useTheme(); + const COLORS = { red: createPair(theme.error, theme.errorLight), green: createPair(theme.success, theme.successLight), blue: createPair(theme.primaryBlue, theme.mediumBlue), purple: createPair(theme.secondaryPurple, theme.mediumPurple), + lightPurple: createPair(theme.tint, theme.mediumPurple), grey: createPair(theme.secondaryText, theme.lightGrey), }; return ( diff --git a/web/src/components/DisputeCard/CardLabels/RewardsAndFundLabel.tsx b/web/src/components/DisputeCard/CardLabels/RewardsAndFundLabel.tsx new file mode 100644 index 000000000..1886a68ca --- /dev/null +++ b/web/src/components/DisputeCard/CardLabels/RewardsAndFundLabel.tsx @@ -0,0 +1,46 @@ +import React from "react"; +import styled, { useTheme } from "styled-components"; +import EthIcon from "assets/svgs/icons/eth.svg"; +import PnkIcon from "assets/svgs/icons/kleros.svg"; +import NumberDisplay from "components/NumberDisplay"; + +const Container = styled.div` + display: flex; + gap: 4px; + align-items: center; + flex-wrap: wrap; +`; + +const StyledIcon = styled.div<{ color: string }>` + width: 12px; + height: 12px; + + path { + fill: ${({ color }) => color}; + } +`; + +const StyledLabel = styled.label<{ color: string }>` + color: ${({ color }) => color}; +`; +interface IRewardsAndFundLabel { + value: string; + unit: "ETH" | "PNK"; + isFund?: boolean; +} + +const RewardsAndFundLabel: React.FC = ({ value, unit = "ETH", isFund = false }) => { + const theme = useTheme(); + const isWon = Number(value) > 0; + const color = isWon ? theme.success : theme.error; + return Number(value) !== 0 ? ( + + + + + + + ) : null; +}; + +export default RewardsAndFundLabel; diff --git a/web/src/components/DisputeCard/CardLabels/index.tsx b/web/src/components/DisputeCard/CardLabels/index.tsx index 8c109e5ae..849ba0832 100644 --- a/web/src/components/DisputeCard/CardLabels/index.tsx +++ b/web/src/components/DisputeCard/CardLabels/index.tsx @@ -1,26 +1,87 @@ -import React from "react"; +import React, { useMemo } from "react"; import styled from "styled-components"; import Label from "./Label"; import EvidenceIcon from "svgs/label-icons/evidence.svg"; -import { useDisputeDetailsQuery } from "hooks/queries/useDisputeDetailsQuery"; -import { useVotingHistory } from "hooks/queries/useVotingHistory"; +import NotDrawnIcon from "svgs/label-icons/minus-circle.svg"; +import CanVoteIcon from "svgs/label-icons/vote.svg"; +import VotedIcon from "svgs/label-icons/voted.svg"; +import ForgotToVoteIcon from "svgs/label-icons/forgot-vote.svg"; +import AppealIcon from "svgs/label-icons/appeal.svg"; +import FundedIcon from "svgs/label-icons/funded.svg"; +import WonIcon from "svgs/label-icons/rewards-won.svg"; +import LostIcon from "svgs/label-icons/rewards-lost.svg"; +import { useAccount } from "wagmi"; +import { useLabelInfoQuery } from "hooks/queries/useLabelInfoQuery"; +import { isUndefined } from "utils/index"; +import { formatEther, formatUnits } from "viem"; +import RewardsAndFundLabel from "./RewardsAndFundLabel"; +import Skeleton from "react-loading-skeleton"; const Container = styled.div` width: 100%; + display: flex; + flex-wrap: wrap; + gap: 8px; margin-top: 16px; `; interface ICardLabels { disputeId: string; - round: string; + localRoundId: string; } +const LabelArgs = { + EvidenceTime: { text: "Evidence Time", icon: EvidenceIcon, color: "blue" }, + NotDrawn: { text: "Not Drawn", icon: NotDrawnIcon, color: "grey" }, + CanVote: { text: "Time to vote", icon: CanVoteIcon, color: "blue" }, + Voted: { text: "I voted", icon: VotedIcon, color: "purple" }, + DidNotVote: { text: "Forgot to vote", icon: ForgotToVoteIcon, color: "purple" }, + CanFund: { text: "I can fund the appeal", icon: AppealIcon, color: "lightPurple" }, + Funded: { text: "I funded", icon: FundedIcon, color: "lightPurple" }, + Won: { text: "Won", icon: WonIcon, color: "green" }, + Lost: { text: "Lost", icon: LostIcon, color: "red" }, +}; +const CardLabel: React.FC = ({ disputeId, localRoundId }) => { + const { address } = useAccount(); + const { data: labelInfo, isLoading } = useLabelInfoQuery(address?.toLowerCase(), disputeId, localRoundId); + const period = labelInfo?.dispute?.period!; + const hasVoted = !isUndefined(labelInfo?.dispute?.currentRound?.drawnJurors?.[0]?.vote); + const isDrawn = labelInfo?.dispute?.currentRound.drawnJurors.length !== 0; + const funded = labelInfo?.classicRound?.contributions.length !== 0; + const fundAmount = labelInfo?.classicRound?.contributions?.[0]?.amount; + const rewards = labelInfo?.dispute?.shifts?.[0]; + console.log({ labelInfo, isDrawn, hasVoted, funded, rewards, fundAmount }); + const labelData = useMemo(() => { + if (period === "evidence") return LabelArgs.EvidenceTime; + if (!isDrawn && period === "appeal" && !funded) return LabelArgs.CanFund; + if (!isDrawn && ["appeal", "execution"].includes(period) && funded) return LabelArgs.Funded; //plus amount if funded + if (!isDrawn) return LabelArgs.NotDrawn; + + if (["commit", "vote"].includes(period) && !hasVoted) return LabelArgs.CanVote; + if (["vote", "appeal", "execution"].includes(period) && hasVoted) return LabelArgs.Voted; //plus rewards if execution + if (["appeal", "execution"].includes(period) && !hasVoted) return LabelArgs.DidNotVote; //plus rewards if execution + return LabelArgs.NotDrawn; + }, [labelInfo]); + + const rewardsData = useMemo(() => { + const ethShift = formatEther(rewards?.ethAmount ?? ""); + const pnkShift = formatUnits(rewards?.pnkAmount ?? "", 18); + return { ethShift, pnkShift }; + }, [labelData, labelInfo]); + const isWon = Number(rewardsData.pnkShift) > 0; -const CardLabel: React.FC = ({ disputeId, round }) => { - const { data: disputeData } = useDisputeDetailsQuery(disputeId); - const { data: votingHistory } = useVotingHistory(disputeId); - return ( + return isLoading ? ( + + ) : ( {" "} - + + {!isUndefined(rewards) ? <>{isWon ? : } : null} + {!isUndefined(rewards) ? ( + <> + + + + ) : null} + {!isUndefined(fundAmount) ? : null} ); }; diff --git a/web/src/components/DisputeCard/DisputeInfo.tsx b/web/src/components/DisputeCard/DisputeInfo.tsx index 0a4598c5d..ae8099c0c 100644 --- a/web/src/components/DisputeCard/DisputeInfo.tsx +++ b/web/src/components/DisputeCard/DisputeInfo.tsx @@ -95,6 +95,7 @@ const getPeriodPhrase = (period: Periods): string => { }; export interface IDisputeInfo { + disputeID?: string; courtId?: string; court?: string; category?: string; @@ -102,8 +103,10 @@ export interface IDisputeInfo { period?: Periods; date?: number; round?: number; + disputeKitId?: string; overrideIsList?: boolean; isOverview?: boolean; + showLabels?: boolean; } const formatDate = (date: number) => { @@ -114,6 +117,7 @@ const formatDate = (date: number) => { }; const DisputeInfo: React.FC = ({ + disputeID, courtId, court, category, @@ -121,8 +125,10 @@ const DisputeInfo: React.FC = ({ period, date, round, + disputeKitId, overrideIsList, isOverview, + showLabels = false, }) => { const { isList } = useIsList(); const displayAsList = isList && !overrideIsList; @@ -136,7 +142,7 @@ const DisputeInfo: React.FC = ({ })) ?? []) ); const courtBranchValue = items.map((item) => item.text).join(" / "); - + const localRoundID = `${disputeKitId}-${disputeID}-${round! - 1}`; return ( @@ -207,7 +213,7 @@ const DisputeInfo: React.FC = ({ isOverview={isOverview} /> )} - + {showLabels && } ); diff --git a/web/src/components/DisputeCard/index.tsx b/web/src/components/DisputeCard/index.tsx index 55dccd0b6..c97ffc4c1 100644 --- a/web/src/components/DisputeCard/index.tsx +++ b/web/src/components/DisputeCard/index.tsx @@ -20,7 +20,7 @@ import { INVALID_DISPUTE_DATA_ERROR } from "consts/index"; const StyledCard = styled(Card)` width: 100%; - height: ${responsiveSize(280, 296)}; + height: ${responsiveSize(280, 335)}; ${landscapeStyle( () => @@ -97,6 +97,7 @@ const DisputeCard: React.FC = ({ period, lastPeriodChange, court, + currentRound, overrideIsList, }) => { const { isList } = useIsList(); @@ -131,10 +132,13 @@ const DisputeCard: React.FC = ({ )} diff --git a/web/src/hooks/queries/useCasesQuery.ts b/web/src/hooks/queries/useCasesQuery.ts index 46b2f82c7..e8647bfd4 100644 --- a/web/src/hooks/queries/useCasesQuery.ts +++ b/web/src/hooks/queries/useCasesQuery.ts @@ -19,6 +19,11 @@ export const disputeFragment = graphql(` id } currentRoundIndex + currentRound { + disputeKit { + id + } + } court { id policy diff --git a/web/src/hooks/queries/useDisputeDetailsQuery.ts b/web/src/hooks/queries/useDisputeDetailsQuery.ts index 221ef05b1..944eebd83 100644 --- a/web/src/hooks/queries/useDisputeDetailsQuery.ts +++ b/web/src/hooks/queries/useDisputeDetailsQuery.ts @@ -33,7 +33,7 @@ const disputeDetailsQuery = graphql(` export const useDisputeDetailsQuery = (id?: string | number) => { const isEnabled = id !== undefined; - return useQuery({ + return useQuery({ queryKey: ["refetchOnBlock", `disputeDetailsQuery${id}`], enabled: isEnabled, queryFn: async () => await graphqlQueryFnHelper(disputeDetailsQuery, { disputeID: id?.toString() }), diff --git a/web/src/hooks/queries/useLabelInfoQuery.ts b/web/src/hooks/queries/useLabelInfoQuery.ts new file mode 100644 index 000000000..a5e51fba5 --- /dev/null +++ b/web/src/hooks/queries/useLabelInfoQuery.ts @@ -0,0 +1,43 @@ +import { graphql } from "src/graphql"; +import { LabelInfoQuery } from "src/graphql/graphql"; +import { useQuery } from "@tanstack/react-query"; +import { graphqlQueryFnHelper } from "utils/graphqlQueryFnHelper"; +export type { LabelInfoQuery }; + +const labelQuery = graphql(` + query LabelInfo($address: String, $disputeID: ID!, $localRoundID: ID!) { + dispute(id: $disputeID) { + currentRuling + period + shifts(where: { juror: $address }) { + ethAmount + pnkAmount + } + currentRound { + id + drawnJurors(where: { juror: $address }, first: 1) { + vote { + ... on ClassicVote { + choice + } + } + } + } + } + classicRound(id: $localRoundID) { + contributions(where: { contributor: $address }) { + amount + } + } + } +`); + +export const useLabelInfoQuery = (address?: string | null, disputeID?: string, localRoundID?: string) => { + const isEnabled = !!(address && disputeID && localRoundID); + return useQuery({ + queryKey: [`labelQuery${[address, disputeID, localRoundID]}`], + enabled: isEnabled, + staleTime: Infinity, + queryFn: async () => await graphqlQueryFnHelper(labelQuery, { address, disputeID, localRoundID }), + }); +}; From 7c3fa54022b338266255eaabad67e07e74250704 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Sat, 27 Jan 2024 22:41:44 +0530 Subject: [PATCH 03/16] refactor(web): better-label-info-query --- .../DisputeCard/CardLabels/index.tsx | 71 +++++++++++++------ .../components/DisputeCard/DisputeInfo.tsx | 6 +- web/src/components/DisputeCard/index.tsx | 2 - web/src/hooks/queries/useCasesQuery.ts | 5 -- web/src/hooks/queries/useLabelInfoQuery.ts | 31 ++++---- 5 files changed, 68 insertions(+), 47 deletions(-) diff --git a/web/src/components/DisputeCard/CardLabels/index.tsx b/web/src/components/DisputeCard/CardLabels/index.tsx index 849ba0832..3c555a174 100644 --- a/web/src/components/DisputeCard/CardLabels/index.tsx +++ b/web/src/components/DisputeCard/CardLabels/index.tsx @@ -16,6 +16,7 @@ import { isUndefined } from "utils/index"; import { formatEther, formatUnits } from "viem"; import RewardsAndFundLabel from "./RewardsAndFundLabel"; import Skeleton from "react-loading-skeleton"; +import { getLocalRounds } from "utils/getLocalRounds"; const Container = styled.div` width: 100%; @@ -26,7 +27,7 @@ const Container = styled.div` `; interface ICardLabels { disputeId: string; - localRoundId: string; + round: number; } const LabelArgs = { EvidenceTime: { text: "Evidence Time", icon: EvidenceIcon, color: "blue" }, @@ -39,34 +40,57 @@ const LabelArgs = { Won: { text: "Won", icon: WonIcon, color: "green" }, Lost: { text: "Lost", icon: LostIcon, color: "red" }, }; -const CardLabel: React.FC = ({ disputeId, localRoundId }) => { +const CardLabel: React.FC = ({ disputeId, round }) => { const { address } = useAccount(); - const { data: labelInfo, isLoading } = useLabelInfoQuery(address?.toLowerCase(), disputeId, localRoundId); + const { data: labelInfo, isLoading } = useLabelInfoQuery(address?.toLowerCase(), disputeId); + const localRounds = getLocalRounds(labelInfo?.dispute?.disputeKitDispute); + const rounds = labelInfo?.dispute?.rounds; + const currentRound = rounds?.[round]; + const period = labelInfo?.dispute?.period!; - const hasVoted = !isUndefined(labelInfo?.dispute?.currentRound?.drawnJurors?.[0]?.vote); - const isDrawn = labelInfo?.dispute?.currentRound.drawnJurors.length !== 0; - const funded = labelInfo?.classicRound?.contributions.length !== 0; - const fundAmount = labelInfo?.classicRound?.contributions?.[0]?.amount; - const rewards = labelInfo?.dispute?.shifts?.[0]; - console.log({ labelInfo, isDrawn, hasVoted, funded, rewards, fundAmount }); + const hasVotedCurrentRound = !isUndefined(currentRound?.drawnJurors?.[0]?.vote); + const isDrawnCurrentRound = currentRound?.drawnJurors.length !== 0; + const hasVotedInDispute = rounds?.some((item) => !isUndefined(item.drawnJurors?.[0]?.vote)); + const isDrawnInDispute = rounds?.some((item) => item?.drawnJurors.length); + const funded = localRounds?.[round]?.contributions.length !== 0; //if funded in current round + const fundAmount = localRounds?.[round]?.contributions?.[0]?.amount; //current round's fund amount + const shifts = labelInfo?.dispute?.shifts; + console.log({ + labelInfo, + isDrawnCurrentRound, + hasVotedCurrentRound, + isDrawnInDispute, + hasVotedInDispute, + funded, + shifts, + fundAmount, + }); + const labelData = useMemo(() => { if (period === "evidence") return LabelArgs.EvidenceTime; - if (!isDrawn && period === "appeal" && !funded) return LabelArgs.CanFund; - if (!isDrawn && ["appeal", "execution"].includes(period) && funded) return LabelArgs.Funded; //plus amount if funded - if (!isDrawn) return LabelArgs.NotDrawn; + if (!isDrawnCurrentRound && period === "appeal" && !funded) return LabelArgs.CanFund; + if (!isDrawnCurrentRound && ["appeal", "execution"].includes(period) && funded) return LabelArgs.Funded; //plus amount if funded + if (period === "execution" && isDrawnInDispute && hasVotedInDispute) return LabelArgs.Voted; + if (period === "execution" && isDrawnInDispute && !hasVotedInDispute) return LabelArgs.DidNotVote; + if (!isDrawnCurrentRound) return LabelArgs.NotDrawn; - if (["commit", "vote"].includes(period) && !hasVoted) return LabelArgs.CanVote; - if (["vote", "appeal", "execution"].includes(period) && hasVoted) return LabelArgs.Voted; //plus rewards if execution - if (["appeal", "execution"].includes(period) && !hasVoted) return LabelArgs.DidNotVote; //plus rewards if execution + if (["commit", "vote"].includes(period) && !hasVotedCurrentRound) return LabelArgs.CanVote; + if (["vote", "appeal", "execution"].includes(period) && hasVotedCurrentRound) return LabelArgs.Voted; //plus rewards if execution + if (["appeal", "execution"].includes(period) && !hasVotedCurrentRound) return LabelArgs.DidNotVote; //plus rewards if execution return LabelArgs.NotDrawn; }, [labelInfo]); const rewardsData = useMemo(() => { - const ethShift = formatEther(rewards?.ethAmount ?? ""); - const pnkShift = formatUnits(rewards?.pnkAmount ?? "", 18); - return { ethShift, pnkShift }; + return shifts?.reduce( + (acc, val) => { + acc.ethShift += Number(formatEther(val.ethAmount)); + acc.pnkShift += Number(formatUnits(val.pnkAmount, 18)); + return acc; + }, + { ethShift: 0, pnkShift: 0 } + ); }, [labelData, labelInfo]); - const isWon = Number(rewardsData.pnkShift) > 0; + const isWon = Number(rewardsData?.pnkShift) > 0; return isLoading ? ( @@ -74,15 +98,16 @@ const CardLabel: React.FC = ({ disputeId, localRoundId }) => { {" "} - {!isUndefined(rewards) ? <>{isWon ? : } : null} - {!isUndefined(rewards) ? ( + {/* {!isUndefined(rewardsData) ? <>{isWon ? : } : null} */} + {!isUndefined(rewardsData) ? ( <> - - + + ) : null} {!isUndefined(fundAmount) ? : null} ); }; + export default CardLabel; diff --git a/web/src/components/DisputeCard/DisputeInfo.tsx b/web/src/components/DisputeCard/DisputeInfo.tsx index ae8099c0c..1e0f1a2b9 100644 --- a/web/src/components/DisputeCard/DisputeInfo.tsx +++ b/web/src/components/DisputeCard/DisputeInfo.tsx @@ -103,7 +103,6 @@ export interface IDisputeInfo { period?: Periods; date?: number; round?: number; - disputeKitId?: string; overrideIsList?: boolean; isOverview?: boolean; showLabels?: boolean; @@ -125,7 +124,6 @@ const DisputeInfo: React.FC = ({ period, date, round, - disputeKitId, overrideIsList, isOverview, showLabels = false, @@ -142,7 +140,7 @@ const DisputeInfo: React.FC = ({ })) ?? []) ); const courtBranchValue = items.map((item) => item.text).join(" / "); - const localRoundID = `${disputeKitId}-${disputeID}-${round! - 1}`; + return ( @@ -213,7 +211,7 @@ const DisputeInfo: React.FC = ({ isOverview={isOverview} /> )} - {showLabels && } + {showLabels && } ); diff --git a/web/src/components/DisputeCard/index.tsx b/web/src/components/DisputeCard/index.tsx index c97ffc4c1..d76e85c4f 100644 --- a/web/src/components/DisputeCard/index.tsx +++ b/web/src/components/DisputeCard/index.tsx @@ -97,7 +97,6 @@ const DisputeCard: React.FC = ({ period, lastPeriodChange, court, - currentRound, overrideIsList, }) => { const { isList } = useIsList(); @@ -137,7 +136,6 @@ const DisputeCard: React.FC = ({ court={courtName} period={currentPeriodIndex} round={parseInt(currentRoundIndex) + 1} - disputeKitId={currentRound.disputeKit.id} showLabels {...{ category, rewards, date, overrideIsList }} /> diff --git a/web/src/hooks/queries/useCasesQuery.ts b/web/src/hooks/queries/useCasesQuery.ts index e8647bfd4..46b2f82c7 100644 --- a/web/src/hooks/queries/useCasesQuery.ts +++ b/web/src/hooks/queries/useCasesQuery.ts @@ -19,11 +19,6 @@ export const disputeFragment = graphql(` id } currentRoundIndex - currentRound { - disputeKit { - id - } - } court { id policy diff --git a/web/src/hooks/queries/useLabelInfoQuery.ts b/web/src/hooks/queries/useLabelInfoQuery.ts index a5e51fba5..35681c61e 100644 --- a/web/src/hooks/queries/useLabelInfoQuery.ts +++ b/web/src/hooks/queries/useLabelInfoQuery.ts @@ -5,39 +5,44 @@ import { graphqlQueryFnHelper } from "utils/graphqlQueryFnHelper"; export type { LabelInfoQuery }; const labelQuery = graphql(` - query LabelInfo($address: String, $disputeID: ID!, $localRoundID: ID!) { + query LabelInfo($address: String, $disputeID: ID!) { dispute(id: $disputeID) { currentRuling period + shifts(where: { juror: $address }) { ethAmount pnkAmount } - currentRound { - id + rounds { drawnJurors(where: { juror: $address }, first: 1) { vote { - ... on ClassicVote { + id + } + } + } + disputeKitDispute { + localRounds { + ... on ClassicRound { + feeRewards + paidFees + contributions(where: { contributor: $address }) { + amount choice } } } } } - classicRound(id: $localRoundID) { - contributions(where: { contributor: $address }) { - amount - } - } } `); -export const useLabelInfoQuery = (address?: string | null, disputeID?: string, localRoundID?: string) => { - const isEnabled = !!(address && disputeID && localRoundID); +export const useLabelInfoQuery = (address?: string | null, disputeID?: string) => { + const isEnabled = !!(address && disputeID); return useQuery({ - queryKey: [`labelQuery${[address, disputeID, localRoundID]}`], + queryKey: [`labelQuery${[address, disputeID]}`], enabled: isEnabled, staleTime: Infinity, - queryFn: async () => await graphqlQueryFnHelper(labelQuery, { address, disputeID, localRoundID }), + queryFn: async () => await graphqlQueryFnHelper(labelQuery, { address, disputeID }), }); }; From 1b34347310a805234b14f0a9be09309478bccefe Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 29 Jan 2024 12:16:04 +0530 Subject: [PATCH 04/16] fix(web): remove-won-lost-labels --- web/src/components/DisputeCard/CardLabels/index.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/web/src/components/DisputeCard/CardLabels/index.tsx b/web/src/components/DisputeCard/CardLabels/index.tsx index 3c555a174..4832d018f 100644 --- a/web/src/components/DisputeCard/CardLabels/index.tsx +++ b/web/src/components/DisputeCard/CardLabels/index.tsx @@ -8,8 +8,6 @@ import VotedIcon from "svgs/label-icons/voted.svg"; import ForgotToVoteIcon from "svgs/label-icons/forgot-vote.svg"; import AppealIcon from "svgs/label-icons/appeal.svg"; import FundedIcon from "svgs/label-icons/funded.svg"; -import WonIcon from "svgs/label-icons/rewards-won.svg"; -import LostIcon from "svgs/label-icons/rewards-lost.svg"; import { useAccount } from "wagmi"; import { useLabelInfoQuery } from "hooks/queries/useLabelInfoQuery"; import { isUndefined } from "utils/index"; @@ -37,8 +35,6 @@ const LabelArgs = { DidNotVote: { text: "Forgot to vote", icon: ForgotToVoteIcon, color: "purple" }, CanFund: { text: "I can fund the appeal", icon: AppealIcon, color: "lightPurple" }, Funded: { text: "I funded", icon: FundedIcon, color: "lightPurple" }, - Won: { text: "Won", icon: WonIcon, color: "green" }, - Lost: { text: "Lost", icon: LostIcon, color: "red" }, }; const CardLabel: React.FC = ({ disputeId, round }) => { const { address } = useAccount(); @@ -90,7 +86,6 @@ const CardLabel: React.FC = ({ disputeId, round }) => { { ethShift: 0, pnkShift: 0 } ); }, [labelData, labelInfo]); - const isWon = Number(rewardsData?.pnkShift) > 0; return isLoading ? ( @@ -98,7 +93,6 @@ const CardLabel: React.FC = ({ disputeId, round }) => { {" "} - {/* {!isUndefined(rewardsData) ? <>{isWon ? : } : null} */} {!isUndefined(rewardsData) ? ( <> From b2620e43c5e2763cca7b40777756797d2f9afcea Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 29 Jan 2024 16:54:31 +0530 Subject: [PATCH 05/16] feat(web): add-reward-amount-to-contribution-entity --- subgraph/core/schema.graphql | 1 + subgraph/core/src/DisputeKitClassic.ts | 1 + subgraph/core/src/entities/ClassicContribution.ts | 5 ++++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/subgraph/core/schema.graphql b/subgraph/core/schema.graphql index 8e68d66c6..8b601f091 100644 --- a/subgraph/core/schema.graphql +++ b/subgraph/core/schema.graphql @@ -305,6 +305,7 @@ type ClassicContribution implements Contribution @entity { localRound: ClassicRound! amount: BigInt! + rewardAmount: BigInt choice: BigInt! rewardWithdrawn: Boolean! } diff --git a/subgraph/core/src/DisputeKitClassic.ts b/subgraph/core/src/DisputeKitClassic.ts index 686c91214..4004af2f4 100644 --- a/subgraph/core/src/DisputeKitClassic.ts +++ b/subgraph/core/src/DisputeKitClassic.ts @@ -126,5 +126,6 @@ export function handleWithdrawal(event: Withdrawal): void { const contribution = ensureClassicContributionFromEvent(event); if (!contribution) return; contribution.rewardWithdrawn = true; + contribution.rewardAmount = event.params._amount; contribution.save(); } diff --git a/subgraph/core/src/entities/ClassicContribution.ts b/subgraph/core/src/entities/ClassicContribution.ts index c21599a51..42b8c50a1 100644 --- a/subgraph/core/src/entities/ClassicContribution.ts +++ b/subgraph/core/src/entities/ClassicContribution.ts @@ -25,7 +25,10 @@ export function ensureClassicContributionFromEvent(event: T): ClassicContribu classicContribution.rewardWithdrawn = false; } else { const currentAmount = classicContribution.amount; - classicContribution.amount = currentAmount.plus(event.params._amount); + //we dont want to increase amount on withdraw event, the amount in that event is reward/reimburse amount + if (event instanceof ContributionEvent) { + classicContribution.amount = currentAmount.plus(event.params._amount); + } } classicContribution.save(); From ed267ebf799443b2822114cddb538a3c1b32ee73 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 29 Jan 2024 16:59:53 +0530 Subject: [PATCH 06/16] feat(web): add-funding-rewards-logic --- .../DisputeCard/CardLabels/index.tsx | 61 +++++++++++++------ web/src/hooks/queries/useLabelInfoQuery.ts | 5 +- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/web/src/components/DisputeCard/CardLabels/index.tsx b/web/src/components/DisputeCard/CardLabels/index.tsx index 4832d018f..b67e586eb 100644 --- a/web/src/components/DisputeCard/CardLabels/index.tsx +++ b/web/src/components/DisputeCard/CardLabels/index.tsx @@ -15,6 +15,7 @@ import { formatEther, formatUnits } from "viem"; import RewardsAndFundLabel from "./RewardsAndFundLabel"; import Skeleton from "react-loading-skeleton"; import { getLocalRounds } from "utils/getLocalRounds"; +import { ClassicContribution } from "src/graphql/graphql"; const Container = styled.div` width: 100%; @@ -36,6 +37,21 @@ const LabelArgs = { CanFund: { text: "I can fund the appeal", icon: AppealIcon, color: "lightPurple" }, Funded: { text: "I funded", icon: FundedIcon, color: "lightPurple" }, }; + +const getFundingRewards = (contributions: ClassicContribution[], closed: boolean) => { + if (isUndefined(contributions) || contributions.length === 0) return 0; + const contribution = contributions.reduce((acc, val) => { + if (isUndefined(val?.rewardAmount) && isUndefined(val?.amount)) return acc; + if (closed) { + acc += val.rewardAmount === null ? -1 * Number(val.amount) : Number(val.rewardAmount) - Number(val.amount); + } else { + acc += Number(val.amount); + } + return acc; + }, 0); + return Number(formatUnits(BigInt(contribution), 18)); +}; + const CardLabel: React.FC = ({ disputeId, round }) => { const { address } = useAccount(); const { data: labelInfo, isLoading } = useLabelInfoQuery(address?.toLowerCase(), disputeId); @@ -48,24 +64,28 @@ const CardLabel: React.FC = ({ disputeId, round }) => { const isDrawnCurrentRound = currentRound?.drawnJurors.length !== 0; const hasVotedInDispute = rounds?.some((item) => !isUndefined(item.drawnJurors?.[0]?.vote)); const isDrawnInDispute = rounds?.some((item) => item?.drawnJurors.length); - const funded = localRounds?.[round]?.contributions.length !== 0; //if funded in current round - const fundAmount = localRounds?.[round]?.contributions?.[0]?.amount; //current round's fund amount + const hasFundedCurrentRound = localRounds?.[round]?.contributions.length !== 0; //if hasFundedCurrentRound in current round + const currentRoundFund = getFundingRewards(localRounds?.[round]?.contributions, period === "execution"); //current round's fund amount const shifts = labelInfo?.dispute?.shifts; - console.log({ - labelInfo, - isDrawnCurrentRound, - hasVotedCurrentRound, - isDrawnInDispute, - hasVotedInDispute, - funded, - shifts, - fundAmount, - }); + + const contributions = useMemo( + () => + localRounds?.reduce((acc, val) => { + acc.push(...val.contributions); + return acc; + }, []), + [localRounds] + ); + + const contributionRewards = useMemo(() => getFundingRewards(contributions, true), [contributions]); + const hasFundedDispute = contributions?.length !== 0; //if ever funded the dispute in any round const labelData = useMemo(() => { if (period === "evidence") return LabelArgs.EvidenceTime; - if (!isDrawnCurrentRound && period === "appeal" && !funded) return LabelArgs.CanFund; - if (!isDrawnCurrentRound && ["appeal", "execution"].includes(period) && funded) return LabelArgs.Funded; //plus amount if funded + if (!isDrawnCurrentRound && period === "appeal" && !hasFundedCurrentRound) return LabelArgs.CanFund; + + if (!isDrawnCurrentRound && period === "execution" && hasFundedDispute) return LabelArgs.Funded; + if (!isDrawnCurrentRound && period === "appeal" && hasFundedCurrentRound) return LabelArgs.Funded; //plus amount if (period === "execution" && isDrawnInDispute && hasVotedInDispute) return LabelArgs.Voted; if (period === "execution" && isDrawnInDispute && !hasVotedInDispute) return LabelArgs.DidNotVote; if (!isDrawnCurrentRound) return LabelArgs.NotDrawn; @@ -77,7 +97,7 @@ const CardLabel: React.FC = ({ disputeId, round }) => { }, [labelInfo]); const rewardsData = useMemo(() => { - return shifts?.reduce( + const shift = shifts?.reduce( (acc, val) => { acc.ethShift += Number(formatEther(val.ethAmount)); acc.pnkShift += Number(formatUnits(val.pnkAmount, 18)); @@ -85,7 +105,10 @@ const CardLabel: React.FC = ({ disputeId, round }) => { }, { ethShift: 0, pnkShift: 0 } ); - }, [labelData, labelInfo]); + if (isUndefined(shift)) return undefined; + shift.ethShift += contributionRewards; + return shift; + }, [labelData, labelInfo, contributionRewards]); return isLoading ? ( @@ -93,13 +116,15 @@ const CardLabel: React.FC = ({ disputeId, round }) => { {" "} - {!isUndefined(rewardsData) ? ( + {!isUndefined(rewardsData) && period === "execution" ? ( <> ) : null} - {!isUndefined(fundAmount) ? : null} + {!isUndefined(currentRoundFund) && period === "appeal" ? ( + + ) : null} ); }; diff --git a/web/src/hooks/queries/useLabelInfoQuery.ts b/web/src/hooks/queries/useLabelInfoQuery.ts index 35681c61e..044dc9c76 100644 --- a/web/src/hooks/queries/useLabelInfoQuery.ts +++ b/web/src/hooks/queries/useLabelInfoQuery.ts @@ -7,7 +7,6 @@ export type { LabelInfoQuery }; const labelQuery = graphql(` query LabelInfo($address: String, $disputeID: ID!) { dispute(id: $disputeID) { - currentRuling period shifts(where: { juror: $address }) { @@ -24,11 +23,9 @@ const labelQuery = graphql(` disputeKitDispute { localRounds { ... on ClassicRound { - feeRewards - paidFees contributions(where: { contributor: $address }) { amount - choice + rewardAmount } } } From 64c0f6b75781fc08d54e0a60478123001c9d5c18 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 29 Jan 2024 17:09:21 +0530 Subject: [PATCH 07/16] fix(web): align-skeleton-loader --- .../DisputeCard/CardLabels/index.tsx | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/web/src/components/DisputeCard/CardLabels/index.tsx b/web/src/components/DisputeCard/CardLabels/index.tsx index b67e586eb..b6b087abb 100644 --- a/web/src/components/DisputeCard/CardLabels/index.tsx +++ b/web/src/components/DisputeCard/CardLabels/index.tsx @@ -110,21 +110,24 @@ const CardLabel: React.FC = ({ disputeId, round }) => { return shift; }, [labelData, labelInfo, contributionRewards]); - return isLoading ? ( - - ) : ( + return ( - {" "} - - {!isUndefined(rewardsData) && period === "execution" ? ( + {isLoading ? ( + + ) : ( <> - - + + {!isUndefined(rewardsData) && period === "execution" ? ( + <> + + + + ) : null} + {!isUndefined(currentRoundFund) && period === "appeal" ? ( + + ) : null} - ) : null} - {!isUndefined(currentRoundFund) && period === "appeal" ? ( - - ) : null} + )} ); }; From 7cb7d8619afd9a3042a1d2922992c20bd6453ff4 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 29 Jan 2024 17:29:52 +0530 Subject: [PATCH 08/16] refactor(web): change-label-query-stale-time --- web/src/hooks/queries/useLabelInfoQuery.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/hooks/queries/useLabelInfoQuery.ts b/web/src/hooks/queries/useLabelInfoQuery.ts index 044dc9c76..f64daf8b4 100644 --- a/web/src/hooks/queries/useLabelInfoQuery.ts +++ b/web/src/hooks/queries/useLabelInfoQuery.ts @@ -39,7 +39,7 @@ export const useLabelInfoQuery = (address?: string | null, disputeID?: string) = return useQuery({ queryKey: [`labelQuery${[address, disputeID]}`], enabled: isEnabled, - staleTime: Infinity, + staleTime: 60000, queryFn: async () => await graphqlQueryFnHelper(labelQuery, { address, disputeID }), }); }; From c36f002b98d5b45c2b7cf55061f68727331aca0a Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 29 Jan 2024 17:34:11 +0530 Subject: [PATCH 09/16] fix(web): hide-labels-if-disconnected --- web/src/components/DisputeCard/DisputeInfo.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/src/components/DisputeCard/DisputeInfo.tsx b/web/src/components/DisputeCard/DisputeInfo.tsx index 1e0f1a2b9..6f813ff33 100644 --- a/web/src/components/DisputeCard/DisputeInfo.tsx +++ b/web/src/components/DisputeCard/DisputeInfo.tsx @@ -13,6 +13,7 @@ import { getCourtsPath } from "pages/Courts/CourtDetails"; import { useCourtTree } from "hooks/queries/useCourtTree"; import { responsiveSize } from "styles/responsiveSize"; import CardLabel from "./CardLabels"; +import { useAccount } from "wagmi"; const Container = styled.div<{ isList: boolean; isOverview?: boolean }>` display: flex; @@ -129,6 +130,7 @@ const DisputeInfo: React.FC = ({ showLabels = false, }) => { const { isList } = useIsList(); + const { isDisconnected } = useAccount(); const displayAsList = isList && !overrideIsList; const { data } = useCourtTree(); const courtPath = getCourtsPath(data?.court, courtId); @@ -211,7 +213,7 @@ const DisputeInfo: React.FC = ({ isOverview={isOverview} /> )} - {showLabels && } + {showLabels && !isDisconnected ? : null} ); From c67884b76586c8b0364d9392dcca4a0912cde88b Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 29 Jan 2024 19:11:24 +0530 Subject: [PATCH 10/16] fix(web): fix-label-showing-voted-on-commit --- .../DisputeCard/CardLabels/index.tsx | 21 +++++++++---------- web/src/hooks/queries/useLabelInfoQuery.ts | 4 +++- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/web/src/components/DisputeCard/CardLabels/index.tsx b/web/src/components/DisputeCard/CardLabels/index.tsx index b6b087abb..64d9eacd4 100644 --- a/web/src/components/DisputeCard/CardLabels/index.tsx +++ b/web/src/components/DisputeCard/CardLabels/index.tsx @@ -60,12 +60,12 @@ const CardLabel: React.FC = ({ disputeId, round }) => { const currentRound = rounds?.[round]; const period = labelInfo?.dispute?.period!; - const hasVotedCurrentRound = !isUndefined(currentRound?.drawnJurors?.[0]?.vote); + const hasVotedCurrentRound = !isUndefined(currentRound?.drawnJurors?.[0]?.vote?.choice); const isDrawnCurrentRound = currentRound?.drawnJurors.length !== 0; - const hasVotedInDispute = rounds?.some((item) => !isUndefined(item.drawnJurors?.[0]?.vote)); + const hasVotedInDispute = rounds?.some((item) => !isUndefined(item.drawnJurors?.[0]?.vote?.choice)); const isDrawnInDispute = rounds?.some((item) => item?.drawnJurors.length); - const hasFundedCurrentRound = localRounds?.[round]?.contributions.length !== 0; //if hasFundedCurrentRound in current round - const currentRoundFund = getFundingRewards(localRounds?.[round]?.contributions, period === "execution"); //current round's fund amount + const hasFundedCurrentRound = localRounds?.[round]?.contributions.length !== 0; // if hasFundedCurrentRound in current round + const currentRoundFund = getFundingRewards(localRounds?.[round]?.contributions, period === "execution"); // current round's fund amount const shifts = labelInfo?.dispute?.shifts; const contributions = useMemo( @@ -78,22 +78,21 @@ const CardLabel: React.FC = ({ disputeId, round }) => { ); const contributionRewards = useMemo(() => getFundingRewards(contributions, true), [contributions]); - const hasFundedDispute = contributions?.length !== 0; //if ever funded the dispute in any round + const hasFundedDispute = contributions?.length !== 0; // if ever funded the dispute in any round const labelData = useMemo(() => { if (period === "evidence") return LabelArgs.EvidenceTime; - if (!isDrawnCurrentRound && period === "appeal" && !hasFundedCurrentRound) return LabelArgs.CanFund; + if (!isDrawnCurrentRound && period === "appeal") + return hasFundedCurrentRound ? LabelArgs.Funded : LabelArgs.CanFund; if (!isDrawnCurrentRound && period === "execution" && hasFundedDispute) return LabelArgs.Funded; - if (!isDrawnCurrentRound && period === "appeal" && hasFundedCurrentRound) return LabelArgs.Funded; //plus amount - if (period === "execution" && isDrawnInDispute && hasVotedInDispute) return LabelArgs.Voted; + if (period === "execution" && hasVotedInDispute) return LabelArgs.Voted; if (period === "execution" && isDrawnInDispute && !hasVotedInDispute) return LabelArgs.DidNotVote; if (!isDrawnCurrentRound) return LabelArgs.NotDrawn; if (["commit", "vote"].includes(period) && !hasVotedCurrentRound) return LabelArgs.CanVote; - if (["vote", "appeal", "execution"].includes(period) && hasVotedCurrentRound) return LabelArgs.Voted; //plus rewards if execution - if (["appeal", "execution"].includes(period) && !hasVotedCurrentRound) return LabelArgs.DidNotVote; //plus rewards if execution - return LabelArgs.NotDrawn; + if (hasVotedCurrentRound) return LabelArgs.Voted; // plus rewards if execution + return LabelArgs.DidNotVote; // plus rewards if execution }, [labelInfo]); const rewardsData = useMemo(() => { diff --git a/web/src/hooks/queries/useLabelInfoQuery.ts b/web/src/hooks/queries/useLabelInfoQuery.ts index f64daf8b4..3df57ed97 100644 --- a/web/src/hooks/queries/useLabelInfoQuery.ts +++ b/web/src/hooks/queries/useLabelInfoQuery.ts @@ -16,7 +16,9 @@ const labelQuery = graphql(` rounds { drawnJurors(where: { juror: $address }, first: 1) { vote { - id + ... on ClassicVote { + choice + } } } } From c73b7edf722ed9aaa5868624b8694955890fedb6 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 29 Jan 2024 19:13:03 +0530 Subject: [PATCH 11/16] refactor(web): refactor-ensure-classic-contribution-function --- subgraph/core/src/entities/ClassicContribution.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/subgraph/core/src/entities/ClassicContribution.ts b/subgraph/core/src/entities/ClassicContribution.ts index 42b8c50a1..6c9b59077 100644 --- a/subgraph/core/src/entities/ClassicContribution.ts +++ b/subgraph/core/src/entities/ClassicContribution.ts @@ -3,9 +3,7 @@ import { Contribution as ContributionEvent, Withdrawal } from "../../generated/D import { DISPUTEKIT_ID } from "../DisputeKitClassic"; export function ensureClassicContributionFromEvent(event: T): ClassicContribution | null { - if (!(event instanceof ContributionEvent) && !(event instanceof Withdrawal)) { - return null; - } + if (!(event instanceof ContributionEvent) && !(event instanceof Withdrawal)) return null; const coreDisputeID = event.params._coreDisputeID.toString(); const coreRoundIndex = event.params._coreRoundID.toString(); const roundID = `${DISPUTEKIT_ID}-${coreDisputeID}-${coreRoundIndex}`; @@ -25,12 +23,11 @@ export function ensureClassicContributionFromEvent(event: T): ClassicContribu classicContribution.rewardWithdrawn = false; } else { const currentAmount = classicContribution.amount; - //we dont want to increase amount on withdraw event, the amount in that event is reward/reimburse amount + // we dont want to increase amount on withdraw event, the amount in that event is reward/reimburse amount if (event instanceof ContributionEvent) { classicContribution.amount = currentAmount.plus(event.params._amount); } } - classicContribution.save(); return classicContribution; } From 24f87d0f0d751bbf20e718dd2c28bfaf9d416fb5 Mon Sep 17 00:00:00 2001 From: Harman-singh-waraich Date: Mon, 29 Jan 2024 19:18:39 +0530 Subject: [PATCH 12/16] refactor(web): fix-sonar-issues --- web/src/components/DisputeCard/DisputeInfo.tsx | 2 +- web/src/hooks/queries/useLabelInfoQuery.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/web/src/components/DisputeCard/DisputeInfo.tsx b/web/src/components/DisputeCard/DisputeInfo.tsx index 6f813ff33..5612a5374 100644 --- a/web/src/components/DisputeCard/DisputeInfo.tsx +++ b/web/src/components/DisputeCard/DisputeInfo.tsx @@ -213,7 +213,7 @@ const DisputeInfo: React.FC = ({ isOverview={isOverview} /> )} - {showLabels && !isDisconnected ? : null} + {showLabels && !isDisconnected ? : null} ); diff --git a/web/src/hooks/queries/useLabelInfoQuery.ts b/web/src/hooks/queries/useLabelInfoQuery.ts index 3df57ed97..85fb406d2 100644 --- a/web/src/hooks/queries/useLabelInfoQuery.ts +++ b/web/src/hooks/queries/useLabelInfoQuery.ts @@ -2,7 +2,6 @@ import { graphql } from "src/graphql"; import { LabelInfoQuery } from "src/graphql/graphql"; import { useQuery } from "@tanstack/react-query"; import { graphqlQueryFnHelper } from "utils/graphqlQueryFnHelper"; -export type { LabelInfoQuery }; const labelQuery = graphql(` query LabelInfo($address: String, $disputeID: ID!) { From f88927b5ee66a943fd02cb00e1cabfe2d185aacb Mon Sep 17 00:00:00 2001 From: alcercu <333aleix333@gmail.com> Date: Wed, 31 Jan 2024 16:53:55 +0100 Subject: [PATCH 13/16] refactor(web): improve typing on color card labels colors --- .../DisputeCard/CardLabels/Label.tsx | 59 ++++++++++--------- .../DisputeCard/CardLabels/index.tsx | 40 ++++++++----- 2 files changed, 55 insertions(+), 44 deletions(-) diff --git a/web/src/components/DisputeCard/CardLabels/Label.tsx b/web/src/components/DisputeCard/CardLabels/Label.tsx index fc6b2bec7..f3a7d6e38 100644 --- a/web/src/components/DisputeCard/CardLabels/Label.tsx +++ b/web/src/components/DisputeCard/CardLabels/Label.tsx @@ -1,60 +1,61 @@ -import React from "react"; -import styled, { useTheme } from "styled-components"; +import React, { useMemo } from "react"; +import styled, { Theme, useTheme } from "styled-components"; -const LabelContainer = styled.div<{ contentColor: string; backgroundColor: string }>` +const COLORS: Record> = { + red: ["error", "errorLight"], + green: ["success", "successLight"], + blue: ["primaryBlue", "mediumBlue"], + purple: ["secondaryPurple", "mediumPurple"], + lightPurple: ["tint", "mediumPurple"], + grey: ["secondaryText", "lightGrey"], +}; + +export type IColors = keyof typeof COLORS; + +const LabelContainer = styled.div<{ backgroundColor: string }>` display: inline-flex; padding: 4px 8px; align-items: center; gap: 10px; border-radius: 300px; background-color: ${({ backgroundColor }) => backgroundColor}; - div > svg { - fill: ${({ contentColor }) => contentColor}; - } - label { - color: ${({ contentColor }) => contentColor}; - } `; -const IconContainer = styled.div` + +const IconContainer = styled.div<{ contentColor: string }>` height: 14px; width: 14px; display: flex; align-items: center; justify-content: center; + > svg { + fill: ${({ contentColor }) => contentColor}; + } `; -const StyledText = styled.label` +const StyledText = styled.label<{ contentColor: string }>` font-size: 12px; font-weight: 400; + color: ${({ contentColor }) => contentColor}; `; -const createPair = (contentColor: string, backgroundColor: string) => ({ - contentColor, - backgroundColor, -}); - -interface ILabelProps { +export interface ILabelProps { text: string; icon: React.FC>; - color: "red" | "green" | "blue" | "purple" | "grey" | "lightPurple"; + color: keyof typeof COLORS; } + const Label: React.FC = ({ text, icon: Icon, color }) => { const theme = useTheme(); + const [contentColor, backgroundColor] = useMemo(() => { + return COLORS[color].map((color) => theme[color]); + }, [theme, color]); - const COLORS = { - red: createPair(theme.error, theme.errorLight), - green: createPair(theme.success, theme.successLight), - blue: createPair(theme.primaryBlue, theme.mediumBlue), - purple: createPair(theme.secondaryPurple, theme.mediumPurple), - lightPurple: createPair(theme.tint, theme.mediumPurple), - grey: createPair(theme.secondaryText, theme.lightGrey), - }; return ( - - + + - {text} + {text} ); }; diff --git a/web/src/components/DisputeCard/CardLabels/index.tsx b/web/src/components/DisputeCard/CardLabels/index.tsx index 64d9eacd4..375f34073 100644 --- a/web/src/components/DisputeCard/CardLabels/index.tsx +++ b/web/src/components/DisputeCard/CardLabels/index.tsx @@ -1,6 +1,8 @@ import React, { useMemo } from "react"; import styled from "styled-components"; -import Label from "./Label"; +import { formatEther, formatUnits } from "viem"; +import { useAccount } from "wagmi"; +import Skeleton from "react-loading-skeleton"; import EvidenceIcon from "svgs/label-icons/evidence.svg"; import NotDrawnIcon from "svgs/label-icons/minus-circle.svg"; import CanVoteIcon from "svgs/label-icons/vote.svg"; @@ -8,14 +10,12 @@ import VotedIcon from "svgs/label-icons/voted.svg"; import ForgotToVoteIcon from "svgs/label-icons/forgot-vote.svg"; import AppealIcon from "svgs/label-icons/appeal.svg"; import FundedIcon from "svgs/label-icons/funded.svg"; -import { useAccount } from "wagmi"; +import { ClassicContribution } from "src/graphql/graphql"; import { useLabelInfoQuery } from "hooks/queries/useLabelInfoQuery"; import { isUndefined } from "utils/index"; -import { formatEther, formatUnits } from "viem"; -import RewardsAndFundLabel from "./RewardsAndFundLabel"; -import Skeleton from "react-loading-skeleton"; import { getLocalRounds } from "utils/getLocalRounds"; -import { ClassicContribution } from "src/graphql/graphql"; +import Label, { IColors } from "./Label"; +import RewardsAndFundLabel from "./RewardsAndFundLabel"; const Container = styled.div` width: 100%; @@ -24,17 +24,19 @@ const Container = styled.div` gap: 8px; margin-top: 16px; `; + interface ICardLabels { disputeId: string; round: number; } -const LabelArgs = { + +const LabelArgs: Record>; color: IColors }> = { EvidenceTime: { text: "Evidence Time", icon: EvidenceIcon, color: "blue" }, NotDrawn: { text: "Not Drawn", icon: NotDrawnIcon, color: "grey" }, CanVote: { text: "Time to vote", icon: CanVoteIcon, color: "blue" }, Voted: { text: "I voted", icon: VotedIcon, color: "purple" }, - DidNotVote: { text: "Forgot to vote", icon: ForgotToVoteIcon, color: "purple" }, - CanFund: { text: "I can fund the appeal", icon: AppealIcon, color: "lightPurple" }, + DidNotVote: { text: "Didn't cast a vote", icon: ForgotToVoteIcon, color: "purple" }, + CanFund: { text: "Appeal possible", icon: AppealIcon, color: "lightPurple" }, Funded: { text: "I funded", icon: FundedIcon, color: "lightPurple" }, }; @@ -59,13 +61,13 @@ const CardLabel: React.FC = ({ disputeId, round }) => { const rounds = labelInfo?.dispute?.rounds; const currentRound = rounds?.[round]; - const period = labelInfo?.dispute?.period!; + const period = labelInfo?.dispute?.period; const hasVotedCurrentRound = !isUndefined(currentRound?.drawnJurors?.[0]?.vote?.choice); const isDrawnCurrentRound = currentRound?.drawnJurors.length !== 0; const hasVotedInDispute = rounds?.some((item) => !isUndefined(item.drawnJurors?.[0]?.vote?.choice)); const isDrawnInDispute = rounds?.some((item) => item?.drawnJurors.length); - const hasFundedCurrentRound = localRounds?.[round]?.contributions.length !== 0; // if hasFundedCurrentRound in current round - const currentRoundFund = getFundingRewards(localRounds?.[round]?.contributions, period === "execution"); // current round's fund amount + const hasFundedCurrentRound = localRounds?.[round]?.contributions.length !== 0; + const currentRoundFund = getFundingRewards(localRounds?.[round]?.contributions, period === "execution"); const shifts = labelInfo?.dispute?.shifts; const contributions = useMemo( @@ -90,10 +92,18 @@ const CardLabel: React.FC = ({ disputeId, round }) => { if (period === "execution" && isDrawnInDispute && !hasVotedInDispute) return LabelArgs.DidNotVote; if (!isDrawnCurrentRound) return LabelArgs.NotDrawn; - if (["commit", "vote"].includes(period) && !hasVotedCurrentRound) return LabelArgs.CanVote; + if (["commit", "vote"].includes(period ?? "") && !hasVotedCurrentRound) return LabelArgs.CanVote; if (hasVotedCurrentRound) return LabelArgs.Voted; // plus rewards if execution return LabelArgs.DidNotVote; // plus rewards if execution - }, [labelInfo]); + }, [ + hasFundedCurrentRound, + hasVotedCurrentRound, + hasFundedDispute, + hasVotedInDispute, + isDrawnCurrentRound, + isDrawnInDispute, + period, + ]); const rewardsData = useMemo(() => { const shift = shifts?.reduce( @@ -107,7 +117,7 @@ const CardLabel: React.FC = ({ disputeId, round }) => { if (isUndefined(shift)) return undefined; shift.ethShift += contributionRewards; return shift; - }, [labelData, labelInfo, contributionRewards]); + }, [contributionRewards, shifts]); return ( From 65a2d39fac5045835d1b1cdd4ef6c21267b27b21 Mon Sep 17 00:00:00 2001 From: alcercu <333aleix333@gmail.com> Date: Wed, 31 Jan 2024 16:54:35 +0100 Subject: [PATCH 14/16] refactor(web): make more clear when a value is small but not 0 number display --- web/src/components/NumberDisplay.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/web/src/components/NumberDisplay.tsx b/web/src/components/NumberDisplay.tsx index 825c008a9..997438863 100644 --- a/web/src/components/NumberDisplay.tsx +++ b/web/src/components/NumberDisplay.tsx @@ -9,6 +9,14 @@ interface INumberDisplay { isCurrency?: boolean; //currency units are shown in front } +const getFormattedValue = (value: number, decimals: number) => { + const withFixedDecimals = value % 1 !== 0 ? value.toFixed(decimals) : value.toFixed(0); + if (withFixedDecimals === `0.${"0".repeat(decimals)}` && value > 0) { + return `< 0.${"0".repeat(decimals - 1)}1`; + } + return withFixedDecimals; +}; + const NumberDisplay: React.FC = ({ value, unit, @@ -18,7 +26,7 @@ const NumberDisplay: React.FC = ({ isCurrency = false, }) => { const parsedValue = Number(value); - const formattedValue = parsedValue % 1 !== 0 ? parsedValue.toFixed(decimals) : parsedValue.toFixed(0); + const formattedValue = getFormattedValue(parsedValue, decimals); const tooltipValue = isCurrency ? `${unit} ${value}` : `${value} ${unit}`; const displayUnit = showUnitInDisplay ? unit : ""; const displayValue = isCurrency ? `${displayUnit} ${formattedValue}` : `${formattedValue} ${displayUnit}`; From b79b60eac83acf11bf804ec83a45d1219ee40d46 Mon Sep 17 00:00:00 2001 From: alcercu <333aleix333@gmail.com> Date: Thu, 1 Feb 2024 17:01:53 +0100 Subject: [PATCH 15/16] fix(web): account for values lower than 0 --- web/src/components/NumberDisplay.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/web/src/components/NumberDisplay.tsx b/web/src/components/NumberDisplay.tsx index 997438863..236c5b90e 100644 --- a/web/src/components/NumberDisplay.tsx +++ b/web/src/components/NumberDisplay.tsx @@ -11,8 +11,12 @@ interface INumberDisplay { const getFormattedValue = (value: number, decimals: number) => { const withFixedDecimals = value % 1 !== 0 ? value.toFixed(decimals) : value.toFixed(0); - if (withFixedDecimals === `0.${"0".repeat(decimals)}` && value > 0) { - return `< 0.${"0".repeat(decimals - 1)}1`; + if (value !== 0) { + if (withFixedDecimals === `0.${"0".repeat(decimals)}`) { + return `< 0.${"0".repeat(decimals - 1)}1`; + } else if (withFixedDecimals === `-0.${"0".repeat(decimals)}`) { + return `> -0.${"0".repeat(decimals - 1)}1`; + } } return withFixedDecimals; }; From a177460e2403b1113aec8ea5ed3b1702dc03c0b5 Mon Sep 17 00:00:00 2001 From: alcercu <333aleix333@gmail.com> Date: Fri, 2 Feb 2024 10:53:20 +0100 Subject: [PATCH 16/16] chore(subgraph): update package version --- subgraph/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subgraph/package.json b/subgraph/package.json index 4aa832fbd..5dac81eff 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -1,6 +1,6 @@ { "name": "@kleros/kleros-v2-subgraph", - "version": "0.4.0", + "version": "0.5.0", "license": "MIT", "scripts": { "update:core:arbitrum-sepolia-devnet": "./scripts/update.sh arbitrumSepoliaDevnet arbitrum-sepolia core/subgraph.yaml",