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..fee7fd146 100644 --- a/subgraph/core/src/entities/Court.ts +++ b/subgraph/core/src/entities/Court.ts @@ -5,30 +5,15 @@ 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(); + court.effectiveStake = court.effectiveStake.plus(delta); + court.save(); - if (court.parent && court.parent !== null) { - court = Court.load(court.parent as string); - } else { - break; - } + if (court.parent) { + updateEffectiveStake(court.parent as string, delta); } } @@ -48,6 +33,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..9aa21c03c 100644 --- a/subgraph/core/src/entities/JurorTokensPerCourt.ts +++ b/subgraph/core/src/entities/JurorTokensPerCourt.ts @@ -32,34 +32,26 @@ 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; + + const jurorTokensPerCourt = ensureJurorTokensPerCourt(jurorAddress, court.id); + const previousEffectiveStake = jurorTokensPerCourt.effectiveStake; + const newEffectiveStake = previousEffectiveStake.plus(delta); + + 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); } - 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.save(); - - if (court.parent && court.parent !== null) { - court = Court.load(court.parent as string); - } else { - break; - } + jurorTokensPerCourt.effectiveStake = newEffectiveStake; + jurorTokensPerCourt.save(); + court.save(); + + if (court.parent) { + updateJurorEffectiveStake(jurorAddress, court.parent as string, delta); } } @@ -92,8 +84,8 @@ export function updateJurorStake( updateActiveJurors(activeJurorsDelta, timestamp); juror.save(); court.save(); - updateEffectiveStake(courtID); - updateJurorEffectiveStake(jurorAddress, courtID); + updateEffectiveStake(courtID, stakeDelta); + updateJurorEffectiveStake(jurorAddress, courtID, stakeDelta); 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/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 diff --git a/web/src/hooks/queries/useCourtDetails.ts b/web/src/hooks/queries/useCourtDetails.ts index 321c6ce33..46795d763 100644 --- a/web/src/hooks/queries/useCourtDetails.ts +++ b/web/src/hooks/queries/useCourtDetails.ts @@ -17,8 +17,10 @@ const courtDetailsQuery = graphql(` numberClosedDisputes numberAppealingDisputes numberStakedJurors + effectiveNumberStakedJurors numberVotes stake + effectiveStake paidETH paidPNK timesPerPeriod diff --git a/web/src/hooks/queries/useHomePageQuery.ts b/web/src/hooks/queries/useHomePageQuery.ts index 3ebfec2dc..096bed9e5 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: 366, where: { id_gt: $timeframe }) { id stakedPNK paidETH @@ -19,11 +19,12 @@ const homePageQuery = graphql(` activeJurors cases } - courts(orderBy: id, orderDirection: asc) { + courts(first: 1000, orderBy: id, orderDirection: asc) { id name numberDisputes feeForJuror + effectiveStake stake } } diff --git a/web/src/pages/Courts/CourtDetails/Stats/stats.ts b/web/src/pages/Courts/CourtDetails/Stats/stats.ts index 1dd645ad3..0be8be592 100644 --- a/web/src/pages/Courts/CourtDetails/Stats/stats.ts +++ b/web/src/pages/Courts/CourtDetails/Stats/stats.ts @@ -74,14 +74,14 @@ 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, }, { title: "Active Jurors", - getText: (data) => data?.numberStakedJurors, + getText: (data) => data?.effectiveNumberStakedJurors, color: "green", icon: StyledJurorIcon, }, diff --git a/web/src/pages/Home/CourtOverview/Chart.tsx b/web/src/pages/Home/CourtOverview/Chart.tsx index 8152d4521..d0c8eb59c 100644 --- a/web/src/pages/Home/CourtOverview/Chart.tsx +++ b/web/src/pages/Home/CourtOverview/Chart.tsx @@ -88,10 +88,10 @@ 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))], + stakes: [...accData.stakes, parseFloat(formatUnits(current.effectiveStake, 18))], totalStake: accData.totalStake + parseFloat(formatUnits(current.stake, 18)), }; }