Skip to content
Merged
5 changes: 3 additions & 2 deletions subgraph/core/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,14 @@ type User @entity {
resolvedDisputes: [Dispute!]!
totalResolvedDisputes: BigInt!
totalDisputes: BigInt!
totalCoherent: BigInt!
coherenceScore: BigInt!
totalAppealingDisputes: BigInt!
votes: [Vote!]! @derivedFrom(field: "juror")
contributions: [Contribution!]! @derivedFrom(field: "contributor")
evidences: [Evidence!]! @derivedFrom(field: "sender")
penalties: [Penalty!]! @derivedFrom(field: "juror")
totalCoherentVotes: BigInt!
totalResolvedVotes: BigInt!
coherenceScore: BigInt!
}

type Penalty @entity {
Expand Down
39 changes: 38 additions & 1 deletion subgraph/core/src/KlerosCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { updateJurorStake } from "./entities/JurorTokensPerCourt";
import { createDrawFromEvent } from "./entities/Draw";
import { updateTokenAndEthShiftFromEvent } from "./entities/TokenAndEthShift";
import { updateArbitrableCases } from "./entities/Arbitrable";
import { Court, Dispute, Round, User } from "../generated/schema";
import { ClassicVote, Court, Dispute, Draw, Round, User } from "../generated/schema";
import { BigInt } from "@graphprotocol/graph-ts";
import { updatePenalty } from "./entities/Penalty";
import { ensureFeeToken } from "./entities/FeeToken";
Expand Down Expand Up @@ -124,6 +124,43 @@ export function handleNewPeriod(event: NewPeriod): void {
dispute.currentRuling = currentRulingInfo.getRuling();
dispute.overridden = currentRulingInfo.getOverridden();
dispute.tied = currentRulingInfo.getTied();
dispute.save();

const rounds = dispute.rounds.load();
for (let i = 0; i < rounds.length; i++) {
const round = Round.load(rounds[i].id);
if (!round) continue;

const draws = round.drawnJurors.load();
// Iterate over all draws in the round
for (let j = 0; j < draws.length; j++) {
const draw = Draw.load(draws[j].id);
if (!draw) continue;

// This will only work for Classic DisputeKit ("1-").
const vote = ClassicVote.load(`1-${draw.id}`);

if (!vote) continue;

const juror = ensureUser(draw.juror);
juror.totalResolvedVotes = juror.totalResolvedVotes.plus(ONE);

if (vote.choice === null) continue;

// Check if the vote choice matches the final ruling
if (vote.choice!.equals(dispute.currentRuling)) {
juror.totalCoherentVotes = juror.totalCoherentVotes.plus(ONE);
}

// Recalculate coherenceScore
if (juror.totalResolvedVotes.gt(ZERO)) {
const coherenceScore = juror.totalCoherentVotes.times(BigInt.fromI32(100)).div(juror.totalResolvedVotes);
juror.coherenceScore = coherenceScore;
}

juror.save();
}
}
}

dispute.period = newPeriod;
Expand Down
2 changes: 1 addition & 1 deletion subgraph/core/src/entities/TokenAndEthShift.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function updateTokenAndEthShiftFromEvent(event: TokenAndETHShiftEvent): v
const previousEthAmount = shift.ethAmount;
const newEthAmount = previousEthAmount.plus(ethAmount);
shift.ethAmount = newEthAmount;
resolveUserDispute(jurorAddress.toHexString(), previousEthAmount, newEthAmount, disputeID.toString());
resolveUserDispute(jurorAddress.toHexString(), disputeID.toString());
court.paidETH = court.paidETH.plus(ethAmount);
updatePaidETH(ethAmount, event.block.timestamp);
if (pnkAmount.gt(ZERO)) {
Expand Down
20 changes: 3 additions & 17 deletions subgraph/core/src/entities/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export function createUserFromAddress(id: string): User {
user.totalResolvedDisputes = ZERO;
user.totalAppealingDisputes = ZERO;
user.totalDisputes = ZERO;
user.totalCoherent = ZERO;
user.totalCoherentVotes = ZERO;
user.totalResolvedVotes = ZERO;
user.coherenceScore = ZERO;
user.save();

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

export function resolveUserDispute(id: string, previousFeeAmount: BigInt, feeAmount: BigInt, disputeID: string): void {
export function resolveUserDispute(id: string, disputeID: string): void {
const user = ensureUser(id);
if (user.resolvedDisputes.includes(disputeID)) {
if (previousFeeAmount.gt(ZERO)) {
if (feeAmount.le(ZERO)) {
user.totalCoherent = user.totalCoherent.minus(ONE);
}
} else if (previousFeeAmount.le(ZERO)) {
if (feeAmount.gt(ZERO)) {
user.totalCoherent = user.totalCoherent.plus(ONE);
}
}
user.coherenceScore = computeCoherenceScore(user.totalCoherent, user.totalResolvedDisputes);
user.save();
return;
}
user.resolvedDisputes = user.resolvedDisputes.concat([disputeID]);
user.totalResolvedDisputes = user.totalResolvedDisputes.plus(ONE);
if (feeAmount.gt(ZERO)) {
user.totalCoherent = user.totalCoherent.plus(ONE);
}
user.activeDisputes = user.activeDisputes.minus(ONE);
user.coherenceScore = computeCoherenceScore(user.totalCoherent, user.totalResolvedDisputes);
user.save();
}
2 changes: 1 addition & 1 deletion web/.env.devnet.public
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Do not enter sensitive information here.
export REACT_APP_DEPLOYMENT=devnet
export REACT_APP_CORE_SUBGRAPH=https://api.studio.thegraph.com/query/61738/kleros-v2-core-devnet/version/latest
export REACT_APP_CORE_SUBGRAPH=https://api.studio.thegraph.com/query/44313/kleros-v2-test/version/latest
export REACT_APP_DRT_ARBSEPOLIA_SUBGRAPH=https://api.studio.thegraph.com/query/61738/kleros-v2-drt-arbisep-devnet/version/latest
export REACT_APP_STATUS_URL=https://kleros-v2-devnet.betteruptime.com/badge
export REACT_APP_GENESIS_BLOCK_ARBSEPOLIA=3084598
Expand Down
24 changes: 12 additions & 12 deletions web/src/components/Popup/MiniGuides/JurorLevels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,32 +63,32 @@ const userLevelData = [
{
level: 1,
title: "Phytagoras",
totalCoherent: 6,
totalResolvedDisputes: 10,
totalCoherentVotes: 6,
totalResolvedVotes: 10,
},
{
level: 2,
title: "Socrates",
totalCoherent: 7,
totalResolvedDisputes: 10,
totalCoherentVotes: 7,
totalResolvedVotes: 10,
},
{
level: 3,
title: "Plato",
totalCoherent: 8,
totalResolvedDisputes: 10,
totalCoherentVotes: 8,
totalResolvedVotes: 10,
},
{
level: 4,
title: "Aristotle",
totalCoherent: 9,
totalResolvedDisputes: 10,
totalCoherentVotes: 9,
totalResolvedVotes: 10,
},
{
level: 0,
title: "Diogenes",
totalCoherent: 3,
totalResolvedDisputes: 10,
totalCoherentVotes: 3,
totalResolvedVotes: 10,
},
];

Expand All @@ -114,8 +114,8 @@ const RightContent: React.FC<{ currentPage: number }> = ({ currentPage }) => {
<PixelArt level={userData.level} width="189px" height="189px" />
<Coherency
userLevelData={userData}
totalCoherent={userData.totalCoherent}
totalResolvedDisputes={userData.totalResolvedDisputes}
totalCoherentVotes={userData.totalCoherentVotes}
totalResolvedVotes={userData.totalResolvedVotes}
isMiniGuide={true}
/>
</Card>
Expand Down
3 changes: 2 additions & 1 deletion web/src/hooks/queries/useTopUsersByCoherenceScore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const topUsersByCoherenceScoreQuery = graphql(`
users(first: $first, orderBy: $orderBy, orderDirection: $orderDirection) {
id
coherenceScore
totalCoherent
totalCoherentVotes
totalResolvedVotes
totalResolvedDisputes
}
}
Expand Down
3 changes: 2 additions & 1 deletion web/src/hooks/queries/useUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export const userFragment = graphql(`
totalDisputes
totalResolvedDisputes
totalAppealingDisputes
totalCoherent
totalCoherentVotes
totalResolvedVotes
coherenceScore
tokens {
court {
Expand Down
10 changes: 5 additions & 5 deletions web/src/pages/Dashboard/JurorInfo/Coherency.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,18 @@ interface ICoherency {
level: number;
title: string;
};
totalCoherent: number;
totalResolvedDisputes: number;
totalCoherentVotes: number;
totalResolvedVotes: number;
isMiniGuide: boolean;
}

const Coherency: React.FC<ICoherency> = ({ userLevelData, totalCoherent, totalResolvedDisputes, isMiniGuide }) => {
const Coherency: React.FC<ICoherency> = ({ userLevelData, totalCoherentVotes, totalResolvedVotes, isMiniGuide }) => {
const votesContent = (
<label>
Coherent Votes:
<small>
{" "}
{totalCoherent}/{totalResolvedDisputes}{" "}
{totalCoherentVotes}/{totalResolvedVotes}{" "}
</small>
</label>
);
Expand All @@ -51,7 +51,7 @@ const Coherency: React.FC<ICoherency> = ({ userLevelData, totalCoherent, totalRe
<small>{userLevelData.title}</small>
<label>Level {userLevelData.level}</label>
<CircularProgress
progress={parseFloat(((totalCoherent / Math.max(totalResolvedDisputes, 1)) * 100).toFixed(2))}
progress={parseFloat(((totalCoherentVotes / Math.max(totalResolvedVotes, 1)) * 100).toFixed(2))}
/>
{!isMiniGuide ? (
<WithHelpTooltip place="left" {...{ tooltipMsg }}>
Expand Down
12 changes: 6 additions & 6 deletions web/src/pages/Dashboard/JurorInfo/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,16 @@ const StyledLink = styled.a`
interface IHeader {
levelTitle: string;
levelNumber: number;
totalCoherent: number;
totalResolvedDisputes: number;
totalCoherentVotes: number;
totalResolvedVotes: number;
}

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

const coherencePercentage = parseFloat(((totalCoherent / Math.max(totalResolvedDisputes, 1)) * 100).toFixed(2));
const coherencePercentage = parseFloat(((totalCoherentVotes / Math.max(totalResolvedVotes, 1)) * 100).toFixed(2));
const courtUrl = window.location.origin;
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}`;
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}`;
const xShareUrl = `https://twitter.com/intent/tweet?text=${encodeURIComponent(xPostText)}`;

return (
Expand All @@ -86,7 +86,7 @@ const Header: React.FC<IHeader> = ({ levelTitle, levelNumber, totalCoherent, tot
toggleMiniGuide={toggleJurorLevelsMiniGuide}
MiniGuideComponent={JurorLevels}
/>
{totalResolvedDisputes > 0 ? (
{totalResolvedVotes > 0 ? (
<StyledLink href={xShareUrl} target="_blank" rel="noreferrer">
<StyledXIcon /> <span>Share your juror score</span>
</StyledLink>
Expand Down
15 changes: 5 additions & 10 deletions web/src/pages/Dashboard/JurorInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,27 +44,22 @@ const JurorInfo: React.FC = () => {
const { data } = useUserQuery(address?.toLowerCase() as `0x${string}`);
// TODO check graph schema
const coherenceScore = data?.user ? parseInt(data?.user?.coherenceScore) : 0;
const totalCoherent = data?.user ? parseInt(data?.user?.totalCoherent) : 0;
const totalCoherentVotes = data?.user ? parseInt(data?.user?.totalCoherentVotes) : 0;
const totalResolvedVotes = data?.user ? parseInt(data?.user?.totalResolvedVotes) : 0;
const totalResolvedDisputes = data?.user ? parseInt(data?.user?.totalResolvedDisputes) : 0;

const userLevelData = getUserLevelData(coherenceScore);
const userLevelData = getUserLevelData(coherenceScore, totalResolvedDisputes);

return (
<Container>
<Header
levelTitle={userLevelData.title}
levelNumber={userLevelData.level}
totalCoherent={totalCoherent}
totalResolvedDisputes={totalResolvedDisputes}
{...{ totalCoherentVotes, totalResolvedVotes }}
/>
<Card>
<PixelArt level={userLevelData.level} width="189px" height="189px" />
<Coherency
userLevelData={userLevelData}
totalCoherent={totalCoherent}
totalResolvedDisputes={totalResolvedDisputes}
isMiniGuide={false}
/>
<Coherency userLevelData={userLevelData} isMiniGuide={false} {...{ totalCoherentVotes, totalResolvedVotes }} />
<JurorRewards />
</Card>
</Container>
Expand Down
8 changes: 4 additions & 4 deletions web/src/pages/Home/TopJurors/JurorCard/Coherency.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ const Container = styled.div`
`;

interface ICoherency {
totalCoherent: number;
totalResolvedDisputes: number;
totalCoherentVotes: number;
totalResolvedVotes: number;
}

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

return <Container>{coherenceRatio}</Container>;
};
Expand Down
10 changes: 6 additions & 4 deletions web/src/pages/Home/TopJurors/JurorCard/DesktopCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,17 @@ const Container = styled.div`
interface IDesktopCard {
rank: number;
address: string;
totalCoherent: number;
totalCoherentVotes: number;
totalResolvedVotes: number;
totalResolvedDisputes: number;
coherenceScore: number;
}

const DesktopCard: React.FC<IDesktopCard> = ({
rank,
address,
totalCoherent,
totalCoherentVotes,
totalResolvedVotes,
totalResolvedDisputes,
coherenceScore,
}) => {
Expand All @@ -50,8 +52,8 @@ const DesktopCard: React.FC<IDesktopCard> = ({
<Rank rank={rank} />
<JurorTitle address={address} />
<Rewards address={address} />
<Coherency totalCoherent={totalCoherent} totalResolvedDisputes={totalResolvedDisputes} />
<JurorLevel coherenceScore={coherenceScore} />
<Coherency {...{ totalCoherentVotes, totalResolvedVotes }} />
<JurorLevel {...{ coherenceScore, totalResolvedDisputes }} />
</Container>
);
};
Expand Down
5 changes: 3 additions & 2 deletions web/src/pages/Home/TopJurors/JurorCard/JurorLevel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ const StyledLabel = styled.label`

interface IJurorLevel {
coherenceScore: number;
totalResolvedDisputes: number;
}

const JurorLevel: React.FC<IJurorLevel> = ({ coherenceScore }) => {
const userLevelData = getUserLevelData(coherenceScore);
const JurorLevel: React.FC<IJurorLevel> = ({ coherenceScore, totalResolvedDisputes }) => {
const userLevelData = getUserLevelData(coherenceScore, totalResolvedDisputes);
const level = userLevelData.level;

return (
Expand Down
16 changes: 12 additions & 4 deletions web/src/pages/Home/TopJurors/JurorCard/MobileCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,27 @@ interface IMobileCard {
rank: number;
address: string;
coherenceScore: number;
totalCoherent: number;
totalCoherentVotes: number;
totalResolvedVotes: number;
totalResolvedDisputes: number;
}

const MobileCard: React.FC<IMobileCard> = ({ rank, address, coherenceScore, totalCoherent, totalResolvedDisputes }) => {
const MobileCard: React.FC<IMobileCard> = ({
rank,
address,
coherenceScore,
totalCoherentVotes,
totalResolvedVotes,
totalResolvedDisputes,
}) => {
return (
<Container>
<TopSide>
<RankAndTitle>
<Rank rank={rank} />
<JurorTitle address={address} />
</RankAndTitle>
<JurorLevel coherenceScore={coherenceScore} />
<JurorLevel {...{ coherenceScore, totalResolvedDisputes }} />
</TopSide>
<BottomSide>
<HeaderRewardsAndRewards>
Expand All @@ -96,7 +104,7 @@ const MobileCard: React.FC<IMobileCard> = ({ rank, address, coherenceScore, tota
</HeaderRewardsAndRewards>
<HeaderCoherencyAndCoherency>
<HeaderCoherency />
<Coherency totalCoherent={totalCoherent} totalResolvedDisputes={totalResolvedDisputes} />
<Coherency {...{ totalCoherentVotes, totalResolvedVotes }} />
</HeaderCoherencyAndCoherency>
</BottomSide>
</Container>
Expand Down
Loading
Loading