From e7aacc16a55b3674da1a24273b3e4cc187b87c13 Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Fri, 11 Apr 2025 21:01:57 +0200 Subject: [PATCH 1/8] chore: use effectivestake instead of specific stake in court page --- web/src/hooks/queries/useCourtDetails.ts | 1 + web/src/pages/Courts/CourtDetails/Stats/stats.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/web/src/hooks/queries/useCourtDetails.ts b/web/src/hooks/queries/useCourtDetails.ts index 321c6ce33..a59b7ba05 100644 --- a/web/src/hooks/queries/useCourtDetails.ts +++ b/web/src/hooks/queries/useCourtDetails.ts @@ -19,6 +19,7 @@ const courtDetailsQuery = graphql(` numberStakedJurors numberVotes stake + effectiveStake paidETH paidPNK timesPerPeriod diff --git a/web/src/pages/Courts/CourtDetails/Stats/stats.ts b/web/src/pages/Courts/CourtDetails/Stats/stats.ts index 1dd645ad3..215d28059 100644 --- a/web/src/pages/Courts/CourtDetails/Stats/stats.ts +++ b/web/src/pages/Courts/CourtDetails/Stats/stats.ts @@ -74,8 +74,8 @@ export const stats: IStat[] = [ { title: "PNK Staked", coinId: 0, - getText: (data) => `${formatPNK(data?.stake)} PNK`, - getSubtext: (data, coinPrice) => formatUSD(Number(formatUnitsWei(data?.stake)) * (coinPrice ?? 0)), + getText: (data) => `${formatPNK(data?.effectiveStake)} PNK`, + getSubtext: (data, coinPrice) => formatUSD(Number(formatUnitsWei(data?.effectiveStake)) * (coinPrice ?? 0)), color: "green", icon: PNKIcon, }, From 1b015b8137e23fc33db7ab8285b425f1d0150942 Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Fri, 11 Apr 2025 23:22:14 +0200 Subject: [PATCH 2/8] feat: add effective number staked jurors, subgraph, frontend --- subgraph/core/schema.graphql | 1 + subgraph/core/src/entities/Court.ts | 30 +++++++++++++++++++ .../core/src/entities/JurorTokensPerCourt.ts | 3 +- subgraph/package.json | 2 +- web/src/hooks/queries/useCourtDetails.ts | 1 + .../pages/Courts/CourtDetails/Stats/stats.ts | 2 +- 6 files changed, 36 insertions(+), 3 deletions(-) diff --git a/subgraph/core/schema.graphql b/subgraph/core/schema.graphql index 243d4bb9d..b4b0626b5 100644 --- a/subgraph/core/schema.graphql +++ b/subgraph/core/schema.graphql @@ -150,6 +150,7 @@ type Court @entity { numberVotes: BigInt! stakedJurors: [JurorTokensPerCourt!]! @derivedFrom(field: "court") numberStakedJurors: BigInt! + effectiveNumberStakedJurors: BigInt! stake: BigInt! effectiveStake: BigInt! delayedStake: BigInt! diff --git a/subgraph/core/src/entities/Court.ts b/subgraph/core/src/entities/Court.ts index 03f20e977..ee939e23c 100644 --- a/subgraph/core/src/entities/Court.ts +++ b/subgraph/core/src/entities/Court.ts @@ -32,6 +32,35 @@ export function updateEffectiveStake(courtID: string): void { } } +// This function calculates the "effective" numberStakedJurors, which is the specific numberStakedJurors +// of the current court + the specific numberStakedJurors of all of its children courts +export function updateEffectiveNumberStakedJurors(courtID: string): void { + let court = Court.load(courtID); + if (!court) return; + + while (court) { + let totalJurors = court.numberStakedJurors; + + const childrenCourts = court.children.load(); + + for (let i = 0; i < childrenCourts.length; i++) { + const childCourt = Court.load(childrenCourts[i].id); + if (childCourt) { + totalJurors = totalJurors.plus(childCourt.effectiveNumberStakedJurors); + } + } + + court.effectiveNumberStakedJurors = totalJurors; + court.save(); + + if (court.parent && court.parent !== null) { + court = Court.load(court.parent as string); + } else { + break; + } + } +} + export function createCourtFromEvent(event: CourtCreated): void { const court = new Court(event.params._courtID.toString()); court.hiddenVotes = event.params._hiddenVotes; @@ -48,6 +77,7 @@ export function createCourtFromEvent(event: CourtCreated): void { court.numberAppealingDisputes = ZERO; court.numberVotes = ZERO; court.numberStakedJurors = ZERO; + court.effectiveNumberStakedJurors = ZERO; court.stake = ZERO; court.effectiveStake = ZERO; court.delayedStake = ZERO; diff --git a/subgraph/core/src/entities/JurorTokensPerCourt.ts b/subgraph/core/src/entities/JurorTokensPerCourt.ts index 98fa8cb24..fc7ed382d 100644 --- a/subgraph/core/src/entities/JurorTokensPerCourt.ts +++ b/subgraph/core/src/entities/JurorTokensPerCourt.ts @@ -4,7 +4,7 @@ import { updateActiveJurors, getDelta, updateStakedPNK, updateCourtStateVariable import { ensureUser } from "./User"; import { ONE, ZERO } from "../utils"; import { SortitionModule } from "../../generated/SortitionModule/SortitionModule"; -import { updateEffectiveStake } from "./Court"; +import { updateEffectiveNumberStakedJurors, updateEffectiveStake } from "./Court"; export function ensureJurorTokensPerCourt(jurorAddress: string, courtID: string): JurorTokensPerCourt { const id = `${jurorAddress}-${courtID}`; @@ -93,6 +93,7 @@ export function updateJurorStake( juror.save(); court.save(); updateEffectiveStake(courtID); + updateEffectiveNumberStakedJurors(courtID); updateJurorEffectiveStake(jurorAddress, courtID); updateCourtStateVariable(courtID, court.effectiveStake, timestamp, "effectiveStake"); } diff --git a/subgraph/package.json b/subgraph/package.json index d38bdffab..0a125ee5e 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -1,6 +1,6 @@ { "name": "@kleros/kleros-v2-subgraph", - "version": "0.15.0", + "version": "0.15.2", "drtVersion": "0.12.0", "license": "MIT", "scripts": { diff --git a/web/src/hooks/queries/useCourtDetails.ts b/web/src/hooks/queries/useCourtDetails.ts index a59b7ba05..46795d763 100644 --- a/web/src/hooks/queries/useCourtDetails.ts +++ b/web/src/hooks/queries/useCourtDetails.ts @@ -17,6 +17,7 @@ const courtDetailsQuery = graphql(` numberClosedDisputes numberAppealingDisputes numberStakedJurors + effectiveNumberStakedJurors numberVotes stake effectiveStake diff --git a/web/src/pages/Courts/CourtDetails/Stats/stats.ts b/web/src/pages/Courts/CourtDetails/Stats/stats.ts index 215d28059..0be8be592 100644 --- a/web/src/pages/Courts/CourtDetails/Stats/stats.ts +++ b/web/src/pages/Courts/CourtDetails/Stats/stats.ts @@ -81,7 +81,7 @@ export const stats: IStat[] = [ }, { title: "Active Jurors", - getText: (data) => data?.numberStakedJurors, + getText: (data) => data?.effectiveNumberStakedJurors, color: "green", icon: StyledJurorIcon, }, From 23825822d5bd12c642898d8ece0a3e916aa78e0e Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Mon, 14 Apr 2025 15:54:52 +0200 Subject: [PATCH 3/8] chore: optimizations --- subgraph/core/src/entities/Court.ts | 54 ++++--------------- .../core/src/entities/JurorTokensPerCourt.ts | 28 +++------- 2 files changed, 17 insertions(+), 65 deletions(-) diff --git a/subgraph/core/src/entities/Court.ts b/subgraph/core/src/entities/Court.ts index ee939e23c..d27c76c77 100644 --- a/subgraph/core/src/entities/Court.ts +++ b/subgraph/core/src/entities/Court.ts @@ -5,59 +5,25 @@ import { ZERO } from "../utils"; // This function calculates the "effective" stake, which is the specific stake // of the current court + the specific stake of all of its children courts -export function updateEffectiveStake(courtID: string): void { +export function updateEffectiveStake(courtID: string, delta: BigInt): void { let court = Court.load(courtID); if (!court) return; - - while (court) { - let totalStake = court.stake; - - const childrenCourts = court.children.load(); - - for (let i = 0; i < childrenCourts.length; i++) { - const childCourt = Court.load(childrenCourts[i].id); - if (childCourt) { - totalStake = totalStake.plus(childCourt.effectiveStake); - } - } - - court.effectiveStake = totalStake; - court.save(); - - if (court.parent && court.parent !== null) { - court = Court.load(court.parent as string); - } else { - break; - } + court.effectiveStake = court.effectiveStake.plus(delta); + court.save(); + if (court.parent) { + updateEffectiveStake(court.parent as string, delta); } } // This function calculates the "effective" numberStakedJurors, which is the specific numberStakedJurors // of the current court + the specific numberStakedJurors of all of its children courts -export function updateEffectiveNumberStakedJurors(courtID: string): void { +export function updateEffectiveNumberStakedJurors(courtID: string, delta: BigInt): void { let court = Court.load(courtID); if (!court) return; - - while (court) { - let totalJurors = court.numberStakedJurors; - - const childrenCourts = court.children.load(); - - for (let i = 0; i < childrenCourts.length; i++) { - const childCourt = Court.load(childrenCourts[i].id); - if (childCourt) { - totalJurors = totalJurors.plus(childCourt.effectiveNumberStakedJurors); - } - } - - court.effectiveNumberStakedJurors = totalJurors; - court.save(); - - if (court.parent && court.parent !== null) { - court = Court.load(court.parent as string); - } else { - break; - } + court.effectiveNumberStakedJurors = court.effectiveNumberStakedJurors.plus(delta); + court.save(); + if (court.parent) { + updateEffectiveNumberStakedJurors(court.parent as string, delta); } } diff --git a/subgraph/core/src/entities/JurorTokensPerCourt.ts b/subgraph/core/src/entities/JurorTokensPerCourt.ts index fc7ed382d..a75f2a2fa 100644 --- a/subgraph/core/src/entities/JurorTokensPerCourt.ts +++ b/subgraph/core/src/entities/JurorTokensPerCourt.ts @@ -32,30 +32,16 @@ export function createJurorTokensPerCourt(jurorAddress: string, courtID: string) return jurorTokens; } -export function updateJurorEffectiveStake(jurorAddress: string, courtID: string): void { +export function updateJurorEffectiveStake(jurorAddress: string, courtID: string, delta: BigInt): void { let court = Court.load(courtID); - if (!court) { - return; - } + if (!court) return; while (court) { const jurorTokensPerCourt = ensureJurorTokensPerCourt(jurorAddress, court.id); - let totalStake = jurorTokensPerCourt.staked; - const childrenCourts = court.children.load(); - - for (let i = 0; i < childrenCourts.length; i++) { - const childCourtID = childrenCourts[i].id; - const childCourt = Court.load(childCourtID); - if (childCourt) { - const childJurorTokensPerCourt = ensureJurorTokensPerCourt(jurorAddress, childCourt.id); - totalStake = totalStake.plus(childJurorTokensPerCourt.effectiveStake); - } - } - - jurorTokensPerCourt.effectiveStake = totalStake; + jurorTokensPerCourt.effectiveStake = jurorTokensPerCourt.effectiveStake.plus(delta); jurorTokensPerCourt.save(); - if (court.parent && court.parent !== null) { + if (court.parent) { court = Court.load(court.parent as string); } else { break; @@ -92,9 +78,9 @@ export function updateJurorStake( updateActiveJurors(activeJurorsDelta, timestamp); juror.save(); court.save(); - updateEffectiveStake(courtID); - updateEffectiveNumberStakedJurors(courtID); - updateJurorEffectiveStake(jurorAddress, courtID); + updateEffectiveStake(courtID, stakeDelta); + updateJurorEffectiveStake(jurorAddress, courtID, stakeDelta); + updateEffectiveNumberStakedJurors(courtID, stakedJurorsDelta); updateCourtStateVariable(courtID, court.effectiveStake, timestamp, "effectiveStake"); } From b7384062fec05118e76e1cf514ba16d658fe5aa4 Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Tue, 15 Apr 2025 04:25:30 +0200 Subject: [PATCH 4/8] fix: correctly calculate effectivenumberstakedjurors --- subgraph/core/src/entities/Court.ts | 14 ++-------- .../core/src/entities/JurorTokensPerCourt.ts | 27 +++++++++++-------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/subgraph/core/src/entities/Court.ts b/subgraph/core/src/entities/Court.ts index d27c76c77..fee7fd146 100644 --- a/subgraph/core/src/entities/Court.ts +++ b/subgraph/core/src/entities/Court.ts @@ -8,22 +8,12 @@ import { ZERO } from "../utils"; export function updateEffectiveStake(courtID: string, delta: BigInt): void { let court = Court.load(courtID); if (!court) return; + court.effectiveStake = court.effectiveStake.plus(delta); court.save(); - if (court.parent) { - updateEffectiveStake(court.parent as string, delta); - } -} -// This function calculates the "effective" numberStakedJurors, which is the specific numberStakedJurors -// of the current court + the specific numberStakedJurors of all of its children courts -export function updateEffectiveNumberStakedJurors(courtID: string, delta: BigInt): void { - let court = Court.load(courtID); - if (!court) return; - court.effectiveNumberStakedJurors = court.effectiveNumberStakedJurors.plus(delta); - court.save(); if (court.parent) { - updateEffectiveNumberStakedJurors(court.parent as string, delta); + updateEffectiveStake(court.parent as string, delta); } } diff --git a/subgraph/core/src/entities/JurorTokensPerCourt.ts b/subgraph/core/src/entities/JurorTokensPerCourt.ts index a75f2a2fa..9aa21c03c 100644 --- a/subgraph/core/src/entities/JurorTokensPerCourt.ts +++ b/subgraph/core/src/entities/JurorTokensPerCourt.ts @@ -4,7 +4,7 @@ import { updateActiveJurors, getDelta, updateStakedPNK, updateCourtStateVariable import { ensureUser } from "./User"; import { ONE, ZERO } from "../utils"; import { SortitionModule } from "../../generated/SortitionModule/SortitionModule"; -import { updateEffectiveNumberStakedJurors, updateEffectiveStake } from "./Court"; +import { updateEffectiveStake } from "./Court"; export function ensureJurorTokensPerCourt(jurorAddress: string, courtID: string): JurorTokensPerCourt { const id = `${jurorAddress}-${courtID}`; @@ -36,16 +36,22 @@ export function updateJurorEffectiveStake(jurorAddress: string, courtID: string, let court = Court.load(courtID); if (!court) return; - while (court) { - const jurorTokensPerCourt = ensureJurorTokensPerCourt(jurorAddress, court.id); - jurorTokensPerCourt.effectiveStake = jurorTokensPerCourt.effectiveStake.plus(delta); - jurorTokensPerCourt.save(); + const jurorTokensPerCourt = ensureJurorTokensPerCourt(jurorAddress, court.id); + const previousEffectiveStake = jurorTokensPerCourt.effectiveStake; + const newEffectiveStake = previousEffectiveStake.plus(delta); - if (court.parent) { - court = Court.load(court.parent as string); - } else { - break; - } + if (previousEffectiveStake.equals(ZERO) && newEffectiveStake.gt(ZERO)) { + court.effectiveNumberStakedJurors = court.effectiveNumberStakedJurors.plus(ONE); + } else if (previousEffectiveStake.gt(ZERO) && newEffectiveStake.equals(ZERO)) { + court.effectiveNumberStakedJurors = court.effectiveNumberStakedJurors.minus(ONE); + } + + jurorTokensPerCourt.effectiveStake = newEffectiveStake; + jurorTokensPerCourt.save(); + court.save(); + + if (court.parent) { + updateJurorEffectiveStake(jurorAddress, court.parent as string, delta); } } @@ -80,7 +86,6 @@ export function updateJurorStake( court.save(); updateEffectiveStake(courtID, stakeDelta); updateJurorEffectiveStake(jurorAddress, courtID, stakeDelta); - updateEffectiveNumberStakedJurors(courtID, stakedJurorsDelta); updateCourtStateVariable(courtID, court.effectiveStake, timestamp, "effectiveStake"); } From cdcfa3a9d764146136fe61037aaae09125df2858 Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Tue, 15 Apr 2025 13:29:55 +0200 Subject: [PATCH 5/8] fix: temp fix on homepage --- web/src/hooks/queries/useHomePageQuery.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/hooks/queries/useHomePageQuery.ts b/web/src/hooks/queries/useHomePageQuery.ts index 3ebfec2dc..618bb9240 100644 --- a/web/src/hooks/queries/useHomePageQuery.ts +++ b/web/src/hooks/queries/useHomePageQuery.ts @@ -11,7 +11,7 @@ const homePageQuery = graphql(` disputes(first: 3) { id } - counters(where: { id_gt: $timeframe }) { + counters(first: 1000, where: { id_gt: $timeframe }) { id stakedPNK paidETH @@ -19,7 +19,7 @@ const homePageQuery = graphql(` activeJurors cases } - courts(orderBy: id, orderDirection: asc) { + courts(first: 1000, orderBy: id, orderDirection: asc) { id name numberDisputes From 3db0efc808d91579b3b65dd0e9deee145288a3f7 Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Tue, 15 Apr 2025 14:06:21 +0200 Subject: [PATCH 6/8] fix: chart and query numbers --- web/src/hooks/queries/useHomePageQuery.ts | 4 ++-- web/src/pages/Home/CourtOverview/Chart.tsx | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/web/src/hooks/queries/useHomePageQuery.ts b/web/src/hooks/queries/useHomePageQuery.ts index 618bb9240..321f79b13 100644 --- a/web/src/hooks/queries/useHomePageQuery.ts +++ b/web/src/hooks/queries/useHomePageQuery.ts @@ -11,7 +11,7 @@ const homePageQuery = graphql(` disputes(first: 3) { id } - counters(first: 1000, where: { id_gt: $timeframe }) { + counters(first: 366, where: { id_gt: $timeframe }) { id stakedPNK paidETH @@ -24,7 +24,7 @@ const homePageQuery = graphql(` name numberDisputes feeForJuror - stake + effectiveStake } } `); diff --git a/web/src/pages/Home/CourtOverview/Chart.tsx b/web/src/pages/Home/CourtOverview/Chart.tsx index 8152d4521..4ce47e8aa 100644 --- a/web/src/pages/Home/CourtOverview/Chart.tsx +++ b/web/src/pages/Home/CourtOverview/Chart.tsx @@ -88,11 +88,11 @@ const Chart: React.FC = () => { const processedStakedPNKData = courtsChartData?.reduce( (accData: StakedPNKByCourtsChartData, current) => { - if (BigInt(current.stake) > 0) { + if (BigInt(current.effectiveStake) > 0) { return { labels: [...accData.labels, current.name ?? ""], - stakes: [...accData.stakes, parseFloat(formatUnits(current.stake, 18))], - totalStake: accData.totalStake + parseFloat(formatUnits(current.stake, 18)), + stakes: [...accData.stakes, parseFloat(formatUnits(current.effectiveStake, 18))], + totalStake: accData.totalStake + parseFloat(formatUnits(current.effectiveStake, 18)), }; } return accData; From 28e85d6c39c9be67140e8493c54a14c01589358f Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Tue, 15 Apr 2025 14:21:40 +0200 Subject: [PATCH 7/8] fix: tiny bug in barchart --- web/src/hooks/queries/useHomePageQuery.ts | 1 + web/src/pages/Home/CourtOverview/Chart.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/web/src/hooks/queries/useHomePageQuery.ts b/web/src/hooks/queries/useHomePageQuery.ts index 321f79b13..096bed9e5 100644 --- a/web/src/hooks/queries/useHomePageQuery.ts +++ b/web/src/hooks/queries/useHomePageQuery.ts @@ -25,6 +25,7 @@ const homePageQuery = graphql(` numberDisputes feeForJuror effectiveStake + stake } } `); diff --git a/web/src/pages/Home/CourtOverview/Chart.tsx b/web/src/pages/Home/CourtOverview/Chart.tsx index 4ce47e8aa..d0c8eb59c 100644 --- a/web/src/pages/Home/CourtOverview/Chart.tsx +++ b/web/src/pages/Home/CourtOverview/Chart.tsx @@ -92,7 +92,7 @@ const Chart: React.FC = () => { return { labels: [...accData.labels, current.name ?? ""], stakes: [...accData.stakes, parseFloat(formatUnits(current.effectiveStake, 18))], - totalStake: accData.totalStake + parseFloat(formatUnits(current.effectiveStake, 18)), + totalStake: accData.totalStake + parseFloat(formatUnits(current.stake, 18)), }; } return accData; From 0cc67e1f03d9ea49af703ff3634069a1a7dbe291 Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Tue, 15 Apr 2025 14:52:11 +0200 Subject: [PATCH 8/8] chore: retrigger deploy preview --- web/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/README.md b/web/README.md index e6b643337..61fe8c865 100644 --- a/web/README.md +++ b/web/README.md @@ -23,7 +23,7 @@ ### Pre-Requisites -If you haven't already, you need to follow all the previous steps of the **Contributing** section of the repo's [Contribution Guidelines](../CONTRIBUTING.md) +If you haven't already, you need to follow all the previous steps of the **Contributing** section of the repo's [Contribution Guidelines](../CONTRIBUTING.md). ### Getting Started