Skip to content

Commit 8613090

Browse files
committed
feat(subgraph,web): add totalcoherentvotes, totalresolvedvotes, modify frontend
1 parent 22e1485 commit 8613090

File tree

15 files changed

+100
-74
lines changed

15 files changed

+100
-74
lines changed

subgraph/core/schema.graphql

+3-2
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,14 @@ type User @entity {
7979
resolvedDisputes: [Dispute!]!
8080
totalResolvedDisputes: BigInt!
8181
totalDisputes: BigInt!
82-
totalCoherent: BigInt!
83-
coherenceScore: BigInt!
8482
totalAppealingDisputes: BigInt!
8583
votes: [Vote!]! @derivedFrom(field: "juror")
8684
contributions: [Contribution!]! @derivedFrom(field: "contributor")
8785
evidences: [Evidence!]! @derivedFrom(field: "sender")
8886
penalties: [Penalty!]! @derivedFrom(field: "juror")
87+
totalCoherentVotes: BigInt!
88+
totalResolvedVotes: BigInt!
89+
coherenceScore: BigInt!
8990
}
9091

9192
type Penalty @entity {

subgraph/core/src/KlerosCore.ts

+38-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { updateJurorStake } from "./entities/JurorTokensPerCourt";
2424
import { createDrawFromEvent } from "./entities/Draw";
2525
import { updateTokenAndEthShiftFromEvent } from "./entities/TokenAndEthShift";
2626
import { updateArbitrableCases } from "./entities/Arbitrable";
27-
import { Court, Dispute, Round, User } from "../generated/schema";
27+
import { ClassicVote, Court, Dispute, Draw, Round, User } from "../generated/schema";
2828
import { BigInt } from "@graphprotocol/graph-ts";
2929
import { updatePenalty } from "./entities/Penalty";
3030
import { ensureFeeToken } from "./entities/FeeToken";
@@ -124,6 +124,43 @@ export function handleNewPeriod(event: NewPeriod): void {
124124
dispute.currentRuling = currentRulingInfo.getRuling();
125125
dispute.overridden = currentRulingInfo.getOverridden();
126126
dispute.tied = currentRulingInfo.getTied();
127+
dispute.save();
128+
129+
const rounds = dispute.rounds.load();
130+
for (let i = 0; i < rounds.length; i++) {
131+
const round = Round.load(rounds[i].id);
132+
if (!round) continue;
133+
134+
const draws = round.drawnJurors.load();
135+
// Iterate over all draws in the round
136+
for (let j = 0; j < draws.length; j++) {
137+
const draw = Draw.load(draws[j].id);
138+
if (!draw) continue;
139+
140+
// This will only work for Classic DisputeKit ("1-").
141+
const vote = ClassicVote.load(`1-${draw.id}`);
142+
143+
if (!vote) continue;
144+
145+
const juror = ensureUser(draw.juror);
146+
juror.totalResolvedVotes = juror.totalResolvedVotes.plus(ONE);
147+
148+
if (vote.choice === null) continue;
149+
150+
// Check if the vote choice matches the final ruling
151+
if (vote.choice!.equals(dispute.currentRuling)) {
152+
juror.totalCoherentVotes = juror.totalCoherentVotes.plus(ONE);
153+
}
154+
155+
// Recalculate coherenceScore
156+
if (juror.totalResolvedVotes.gt(ZERO)) {
157+
const coherenceScore = juror.totalCoherentVotes.times(BigInt.fromI32(100)).div(juror.totalResolvedVotes);
158+
juror.coherenceScore = coherenceScore;
159+
}
160+
161+
juror.save();
162+
}
163+
}
127164
}
128165

129166
dispute.period = newPeriod;

subgraph/core/src/entities/TokenAndEthShift.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function updateTokenAndEthShiftFromEvent(event: TokenAndETHShiftEvent): v
2929
const previousEthAmount = shift.ethAmount;
3030
const newEthAmount = previousEthAmount.plus(ethAmount);
3131
shift.ethAmount = newEthAmount;
32-
resolveUserDispute(jurorAddress.toHexString(), previousEthAmount, newEthAmount, disputeID.toString());
32+
resolveUserDispute(jurorAddress.toHexString(), disputeID.toString());
3333
court.paidETH = court.paidETH.plus(ethAmount);
3434
updatePaidETH(ethAmount, event.block.timestamp);
3535
if (pnkAmount.gt(ZERO)) {

subgraph/core/src/entities/User.ts

+3-17
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ export function createUserFromAddress(id: string): User {
3636
user.totalResolvedDisputes = ZERO;
3737
user.totalAppealingDisputes = ZERO;
3838
user.totalDisputes = ZERO;
39-
user.totalCoherent = ZERO;
39+
user.totalCoherentVotes = ZERO;
40+
user.totalResolvedVotes = ZERO;
4041
user.coherenceScore = ZERO;
4142
user.save();
4243

@@ -54,28 +55,13 @@ export function addUserActiveDispute(id: string, disputeID: string): void {
5455
user.save();
5556
}
5657

57-
export function resolveUserDispute(id: string, previousFeeAmount: BigInt, feeAmount: BigInt, disputeID: string): void {
58+
export function resolveUserDispute(id: string, disputeID: string): void {
5859
const user = ensureUser(id);
5960
if (user.resolvedDisputes.includes(disputeID)) {
60-
if (previousFeeAmount.gt(ZERO)) {
61-
if (feeAmount.le(ZERO)) {
62-
user.totalCoherent = user.totalCoherent.minus(ONE);
63-
}
64-
} else if (previousFeeAmount.le(ZERO)) {
65-
if (feeAmount.gt(ZERO)) {
66-
user.totalCoherent = user.totalCoherent.plus(ONE);
67-
}
68-
}
69-
user.coherenceScore = computeCoherenceScore(user.totalCoherent, user.totalResolvedDisputes);
70-
user.save();
7161
return;
7262
}
7363
user.resolvedDisputes = user.resolvedDisputes.concat([disputeID]);
7464
user.totalResolvedDisputes = user.totalResolvedDisputes.plus(ONE);
75-
if (feeAmount.gt(ZERO)) {
76-
user.totalCoherent = user.totalCoherent.plus(ONE);
77-
}
7865
user.activeDisputes = user.activeDisputes.minus(ONE);
79-
user.coherenceScore = computeCoherenceScore(user.totalCoherent, user.totalResolvedDisputes);
8066
user.save();
8167
}

web/.env.devnet.public

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Do not enter sensitive information here.
22
export REACT_APP_DEPLOYMENT=devnet
3-
export REACT_APP_CORE_SUBGRAPH=https://api.studio.thegraph.com/query/61738/kleros-v2-core-devnet/version/latest
3+
export REACT_APP_CORE_SUBGRAPH=https://api.studio.thegraph.com/query/44313/kleros-v2-test/version/latest
44
export REACT_APP_DRT_ARBSEPOLIA_SUBGRAPH=https://api.studio.thegraph.com/query/61738/kleros-v2-drt-arbisep-devnet/version/latest
55
export REACT_APP_STATUS_URL=https://kleros-v2-devnet.betteruptime.com/badge
66
export REACT_APP_GENESIS_BLOCK_ARBSEPOLIA=3084598

web/src/components/Popup/MiniGuides/JurorLevels.tsx

+12-12
Original file line numberDiff line numberDiff line change
@@ -63,32 +63,32 @@ const userLevelData = [
6363
{
6464
level: 1,
6565
title: "Phytagoras",
66-
totalCoherent: 6,
67-
totalResolvedDisputes: 10,
66+
totalCoherentVotes: 6,
67+
totalResolvedVotes: 10,
6868
},
6969
{
7070
level: 2,
7171
title: "Socrates",
72-
totalCoherent: 7,
73-
totalResolvedDisputes: 10,
72+
totalCoherentVotes: 7,
73+
totalResolvedVotes: 10,
7474
},
7575
{
7676
level: 3,
7777
title: "Plato",
78-
totalCoherent: 8,
79-
totalResolvedDisputes: 10,
78+
totalCoherentVotes: 8,
79+
totalResolvedVotes: 10,
8080
},
8181
{
8282
level: 4,
8383
title: "Aristotle",
84-
totalCoherent: 9,
85-
totalResolvedDisputes: 10,
84+
totalCoherentVotes: 9,
85+
totalResolvedVotes: 10,
8686
},
8787
{
8888
level: 0,
8989
title: "Diogenes",
90-
totalCoherent: 3,
91-
totalResolvedDisputes: 10,
90+
totalCoherentVotes: 3,
91+
totalResolvedVotes: 10,
9292
},
9393
];
9494

@@ -114,8 +114,8 @@ const RightContent: React.FC<{ currentPage: number }> = ({ currentPage }) => {
114114
<PixelArt level={userData.level} width="189px" height="189px" />
115115
<Coherency
116116
userLevelData={userData}
117-
totalCoherent={userData.totalCoherent}
118-
totalResolvedDisputes={userData.totalResolvedDisputes}
117+
totalCoherentVotes={userData.totalCoherentVotes}
118+
totalResolvedVotes={userData.totalResolvedVotes}
119119
isMiniGuide={true}
120120
/>
121121
</Card>

web/src/hooks/queries/useTopUsersByCoherenceScore.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ const topUsersByCoherenceScoreQuery = graphql(`
1212
users(first: $first, orderBy: $orderBy, orderDirection: $orderDirection) {
1313
id
1414
coherenceScore
15-
totalCoherent
15+
totalCoherentVotes
16+
totalResolvedVotes
1617
totalResolvedDisputes
1718
}
1819
}

web/src/hooks/queries/useUser.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ export const userFragment = graphql(`
1212
totalDisputes
1313
totalResolvedDisputes
1414
totalAppealingDisputes
15-
totalCoherent
15+
totalCoherentVotes
16+
totalResolvedVotes
1617
coherenceScore
1718
tokens {
1819
court {

web/src/pages/Dashboard/JurorInfo/Coherency.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,18 @@ interface ICoherency {
3030
level: number;
3131
title: string;
3232
};
33-
totalCoherent: number;
34-
totalResolvedDisputes: number;
33+
totalCoherentVotes: number;
34+
totalResolvedVotes: number;
3535
isMiniGuide: boolean;
3636
}
3737

38-
const Coherency: React.FC<ICoherency> = ({ userLevelData, totalCoherent, totalResolvedDisputes, isMiniGuide }) => {
38+
const Coherency: React.FC<ICoherency> = ({ userLevelData, totalCoherentVotes, totalResolvedVotes, isMiniGuide }) => {
3939
const votesContent = (
4040
<label>
4141
Coherent Votes:
4242
<small>
4343
{" "}
44-
{totalCoherent}/{totalResolvedDisputes}{" "}
44+
{totalCoherentVotes}/{totalResolvedVotes}{" "}
4545
</small>
4646
</label>
4747
);
@@ -51,7 +51,7 @@ const Coherency: React.FC<ICoherency> = ({ userLevelData, totalCoherent, totalRe
5151
<small>{userLevelData.title}</small>
5252
<label>Level {userLevelData.level}</label>
5353
<CircularProgress
54-
progress={parseFloat(((totalCoherent / Math.max(totalResolvedDisputes, 1)) * 100).toFixed(2))}
54+
progress={parseFloat(((totalCoherentVotes / Math.max(totalResolvedVotes, 1)) * 100).toFixed(2))}
5555
/>
5656
{!isMiniGuide ? (
5757
<WithHelpTooltip place="left" {...{ tooltipMsg }}>

web/src/pages/Dashboard/JurorInfo/Header.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,16 @@ const StyledLink = styled.a`
6565
interface IHeader {
6666
levelTitle: string;
6767
levelNumber: number;
68-
totalCoherent: number;
69-
totalResolvedDisputes: number;
68+
totalCoherentVotes: number;
69+
totalResolvedVotes: number;
7070
}
7171

72-
const Header: React.FC<IHeader> = ({ levelTitle, levelNumber, totalCoherent, totalResolvedDisputes }) => {
72+
const Header: React.FC<IHeader> = ({ levelTitle, levelNumber, totalCoherentVotes, totalResolvedVotes }) => {
7373
const [isJurorLevelsMiniGuideOpen, toggleJurorLevelsMiniGuide] = useToggle(false);
7474

75-
const coherencePercentage = parseFloat(((totalCoherent / Math.max(totalResolvedDisputes, 1)) * 100).toFixed(2));
75+
const coherencePercentage = parseFloat(((totalCoherentVotes / Math.max(totalResolvedVotes, 1)) * 100).toFixed(2));
7676
const courtUrl = window.location.origin;
77-
const xPostText = `Hey I've been busy as a Juror on the Kleros court, check out my score: \n\nLevel: ${levelNumber} (${levelTitle})\nCoherence Percentage: ${coherencePercentage}%\nCoherent Votes: ${totalCoherent}/${totalResolvedDisputes}\n\nBe a juror with me! ➡️ ${courtUrl}`;
77+
const xPostText = `Hey I've been busy as a Juror on the Kleros court, check out my score: \n\nLevel: ${levelNumber} (${levelTitle})\nCoherence Percentage: ${coherencePercentage}%\nCoherent Votes: ${totalCoherentVotes}/${totalResolvedVotes}\n\nBe a juror with me! ➡️ ${courtUrl}`;
7878
const xShareUrl = `https://twitter.com/intent/tweet?text=${encodeURIComponent(xPostText)}`;
7979

8080
return (
@@ -86,7 +86,7 @@ const Header: React.FC<IHeader> = ({ levelTitle, levelNumber, totalCoherent, tot
8686
toggleMiniGuide={toggleJurorLevelsMiniGuide}
8787
MiniGuideComponent={JurorLevels}
8888
/>
89-
{totalResolvedDisputes > 0 ? (
89+
{totalResolvedVotes > 0 ? (
9090
<StyledLink href={xShareUrl} target="_blank" rel="noreferrer">
9191
<StyledXIcon /> <span>Share your juror score</span>
9292
</StyledLink>

web/src/pages/Dashboard/JurorInfo/index.tsx

+4-10
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ const JurorInfo: React.FC = () => {
4444
const { data } = useUserQuery(address?.toLowerCase() as `0x${string}`);
4545
// TODO check graph schema
4646
const coherenceScore = data?.user ? parseInt(data?.user?.coherenceScore) : 0;
47-
const totalCoherent = data?.user ? parseInt(data?.user?.totalCoherent) : 0;
48-
const totalResolvedDisputes = data?.user ? parseInt(data?.user?.totalResolvedDisputes) : 0;
47+
const totalCoherentVotes = data?.user ? parseInt(data?.user?.totalCoherentVotes) : 0;
48+
const totalResolvedVotes = data?.user ? parseInt(data?.user?.totalResolvedVotes) : 0;
4949

5050
const userLevelData = getUserLevelData(coherenceScore);
5151

@@ -54,17 +54,11 @@ const JurorInfo: React.FC = () => {
5454
<Header
5555
levelTitle={userLevelData.title}
5656
levelNumber={userLevelData.level}
57-
totalCoherent={totalCoherent}
58-
totalResolvedDisputes={totalResolvedDisputes}
57+
{...{ totalCoherentVotes, totalResolvedVotes }}
5958
/>
6059
<Card>
6160
<PixelArt level={userLevelData.level} width="189px" height="189px" />
62-
<Coherency
63-
userLevelData={userLevelData}
64-
totalCoherent={totalCoherent}
65-
totalResolvedDisputes={totalResolvedDisputes}
66-
isMiniGuide={false}
67-
/>
61+
<Coherency userLevelData={userLevelData} isMiniGuide={false} {...{ totalCoherentVotes, totalResolvedVotes }} />
6862
<JurorRewards />
6963
</Card>
7064
</Container>

web/src/pages/Home/TopJurors/JurorCard/Coherency.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ const Container = styled.div`
1111
`;
1212

1313
interface ICoherency {
14-
totalCoherent: number;
15-
totalResolvedDisputes: number;
14+
totalCoherentVotes: number;
15+
totalResolvedVotes: number;
1616
}
1717

18-
const Coherency: React.FC<ICoherency> = ({ totalCoherent, totalResolvedDisputes }) => {
19-
const coherenceRatio = `${totalCoherent}/${totalResolvedDisputes}`;
18+
const Coherency: React.FC<ICoherency> = ({ totalCoherentVotes, totalResolvedVotes }) => {
19+
const coherenceRatio = `${totalCoherentVotes}/${totalResolvedVotes}`;
2020

2121
return <Container>{coherenceRatio}</Container>;
2222
};

web/src/pages/Home/TopJurors/JurorCard/DesktopCard.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,24 @@ const Container = styled.div`
3333
interface IDesktopCard {
3434
rank: number;
3535
address: string;
36-
totalCoherent: number;
37-
totalResolvedDisputes: number;
36+
totalCoherentVotes: number;
37+
totalResolvedVotes: number;
3838
coherenceScore: number;
3939
}
4040

4141
const DesktopCard: React.FC<IDesktopCard> = ({
4242
rank,
4343
address,
44-
totalCoherent,
45-
totalResolvedDisputes,
44+
totalCoherentVotes,
45+
totalResolvedVotes,
4646
coherenceScore,
4747
}) => {
4848
return (
4949
<Container>
5050
<Rank rank={rank} />
5151
<JurorTitle address={address} />
5252
<Rewards address={address} />
53-
<Coherency totalCoherent={totalCoherent} totalResolvedDisputes={totalResolvedDisputes} />
53+
<Coherency {...{ totalCoherentVotes, totalResolvedVotes }} />
5454
<JurorLevel coherenceScore={coherenceScore} />
5555
</Container>
5656
);

web/src/pages/Home/TopJurors/JurorCard/MobileCard.tsx

+10-4
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,17 @@ interface IMobileCard {
7575
rank: number;
7676
address: string;
7777
coherenceScore: number;
78-
totalCoherent: number;
79-
totalResolvedDisputes: number;
78+
totalCoherentVotes: number;
79+
totalResolvedVotes: number;
8080
}
8181

82-
const MobileCard: React.FC<IMobileCard> = ({ rank, address, coherenceScore, totalCoherent, totalResolvedDisputes }) => {
82+
const MobileCard: React.FC<IMobileCard> = ({
83+
rank,
84+
address,
85+
coherenceScore,
86+
totalCoherentVotes,
87+
totalResolvedVotes,
88+
}) => {
8389
return (
8490
<Container>
8591
<TopSide>
@@ -96,7 +102,7 @@ const MobileCard: React.FC<IMobileCard> = ({ rank, address, coherenceScore, tota
96102
</HeaderRewardsAndRewards>
97103
<HeaderCoherencyAndCoherency>
98104
<HeaderCoherency />
99-
<Coherency totalCoherent={totalCoherent} totalResolvedDisputes={totalResolvedDisputes} />
105+
<Coherency {...{ totalCoherentVotes, totalResolvedVotes }} />
100106
</HeaderCoherencyAndCoherency>
101107
</BottomSide>
102108
</Container>

web/src/pages/Home/TopJurors/JurorCard/index.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ interface IJurorCard {
77
rank: number;
88
address: `0x${string}`;
99
coherenceScore: number;
10-
totalCoherent: number;
11-
totalResolvedDisputes: number;
10+
totalCoherentVotes: number;
11+
totalResolvedVotes: number;
1212
}
1313

14-
const JurorCard: React.FC<IJurorCard> = ({ rank, address, coherenceScore, totalCoherent, totalResolvedDisputes }) => {
15-
const allProps = { rank, address, coherenceScore, totalCoherent, totalResolvedDisputes };
14+
const JurorCard: React.FC<IJurorCard> = ({ rank, address, coherenceScore, totalCoherentVotes, totalResolvedVotes }) => {
15+
const allProps = { rank, address, coherenceScore, totalCoherentVotes, totalResolvedVotes };
1616

1717
return (
1818
<>

0 commit comments

Comments
 (0)