From 2321845ea2810319ed81638f9f6ce7b4366bd9e0 Mon Sep 17 00:00:00 2001 From: shotaronowhere Date: Wed, 11 Oct 2023 17:47:55 -0700 Subject: [PATCH 01/12] feat(subgraph): notification schema --- subgraph/schema.graphql | 19 ++++++++++++++-- subgraph/src/KlerosCore.ts | 16 ++++++++++++-- subgraph/src/PolicyRegistry.ts | 37 ++++++++++++++++++++++++++++++++ subgraph/src/entities/Dispute.ts | 18 +++++++++++++--- subgraph/src/entities/Draw.ts | 17 ++++++++++++++- subgraph/src/entities/Round.ts | 1 + subgraph/src/entities/User.ts | 14 ++++++++++-- subgraph/subgraph.yaml | 2 ++ 8 files changed, 114 insertions(+), 10 deletions(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index b904baccc..bd0b9375d 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -66,6 +66,7 @@ type User @entity { shifts: [TokenAndETHShift!]! @derivedFrom(field: "juror") draws: [Draw!]! @derivedFrom(field: "juror") activeDisputes: BigInt! + rounds: [Round!]! disputes: [Dispute!]! resolvedDisputes: [Dispute!]! totalResolvedDisputes: BigInt! @@ -118,6 +119,9 @@ type Court @entity { id: ID! policy: String name: String + description: String + summary: String + requiredSkills: String parent: Court hiddenVotes: Boolean! children: [Court!]! @derivedFrom(field: "parent") @@ -142,6 +146,7 @@ type Court @entity { type Dispute @entity { id: ID! + disputeID: BigInt! court: Court! arbitrated: Arbitrable! period: Period! @@ -149,9 +154,12 @@ type Dispute @entity { currentRuling: BigInt! tied: Boolean! overridden: Boolean! - lastPeriodChange: BigInt! + periodDeadline: BigInt! # uint256j + periodNotificationIndex: BigInt! + lastPeriodChangeTs: BigInt! + users: [User!]! + lastPeriodChangeBlock: BigInt! lastPeriodChangeBlockNumber: BigInt! - periodDeadline: BigInt! rounds: [Round!]! @derivedFrom(field: "dispute") currentRound: Round! currentRoundIndex: BigInt! @@ -160,12 +168,18 @@ type Dispute @entity { disputeKitDispute: DisputeKitDispute @derivedFrom(field: "coreDispute") } +type PeriodIndexCounter @entity { + id: String! + counter: BigInt! +} + type Round @entity { id: ID! # dispute.id-dispute.rounds.length disputeKit: DisputeKit! tokensAtStakePerJuror: BigInt! totalFeesForJurors: BigInt! nbVotes: BigInt! + isCurrentRound: Boolean! repartitions: BigInt! penalties: BigInt! drawnJurors: [Draw!]! @derivedFrom(field: "round") @@ -181,6 +195,7 @@ type Draw @entity(immutable: true) { juror: User! voteID: BigInt! vote: Vote @derivedFrom(field: "draw") + drawNotificationIndex: BigInt } type DisputeKit @entity { diff --git a/subgraph/src/KlerosCore.ts b/subgraph/src/KlerosCore.ts index 3c0efc480..ab1b303e3 100644 --- a/subgraph/src/KlerosCore.ts +++ b/subgraph/src/KlerosCore.ts @@ -25,7 +25,7 @@ import { updateJurorDelayedStake, updateJurorStake } from "./entities/JurorToken import { createDrawFromEvent } from "./entities/Draw"; import { updateTokenAndEthShiftFromEvent } from "./entities/TokenAndEthShift"; import { updateArbitrableCases } from "./entities/Arbitrable"; -import { Court, Dispute, User } from "../generated/schema"; +import { Court, Dispute, User, PeriodIndexCounter } from "../generated/schema"; import { BigInt } from "@graphprotocol/graph-ts"; import { updatePenalty } from "./entities/Penalty"; import { ensureFeeToken } from "./entities/FeeToken"; @@ -126,7 +126,19 @@ export function handleNewPeriod(event: NewPeriod): void { } dispute.period = newPeriod; - dispute.lastPeriodChange = event.block.timestamp; + dispute.lastPeriodChangeTs = event.block.timestamp; + dispute.lastPeriodChangeBlock = event.block.number; + let counter = PeriodIndexCounter.load(newPeriod); + if (!counter) { + counter = new PeriodIndexCounter(newPeriod); + counter.counter = BigInt.fromI32(0); + } + dispute.periodNotificationIndex = counter.counter; + const contract = KlerosCore.bind(event.address); + const courtContractState = contract.getTimesPerPeriod(BigInt.fromString(dispute.court)); + dispute.periodDeadline = event.block.timestamp.plus(courtContractState[event.params._period]); + counter.counter = counter.counter.plus(ONE); + counter.save(); dispute.lastPeriodChangeBlockNumber = event.block.number; if (newPeriod !== "execution") { dispute.periodDeadline = event.block.timestamp.plus(court.timesPerPeriod[event.params._period]); diff --git a/subgraph/src/PolicyRegistry.ts b/subgraph/src/PolicyRegistry.ts index 6820698e3..8a9a56707 100644 --- a/subgraph/src/PolicyRegistry.ts +++ b/subgraph/src/PolicyRegistry.ts @@ -1,5 +1,6 @@ import { PolicyUpdate } from "../generated/PolicyRegistry/PolicyRegistry"; import { Court } from "../generated/schema"; +import { ipfs, log, json, Bytes } from "@graphprotocol/graph-ts"; export function handlePolicyUpdate(event: PolicyUpdate): void { const courtID = event.params._courtID.toString(); @@ -7,6 +8,42 @@ export function handlePolicyUpdate(event: PolicyUpdate): void { if (court) { court.policy = event.params._policy; court.name = event.params._courtName; + + let jsonStr = ipfs.cat(event.params._policy); + if (!jsonStr) { + log.error("Failed to fetch policy #{} SubcourtID: {}", [event.params._policy, event.params._courtID.toString()]); + court.save(); + return; + } + + let jsonObjValueAndSuccess = json.try_fromBytes(jsonStr as Bytes); + if (!jsonObjValueAndSuccess.isOk) { + log.error(`Error getting json object value for policy #{} SubcourtID: {}`, [ + event.params._policy, + event.params._courtID.toString(), + ]); + court.save(); + return; + } + + let jsonObj = jsonObjValueAndSuccess.value.toObject(); + if (!jsonObj) { + log.error(`Error converting object value for policy #{} SubcourtID: {}`, [ + event.params._policy, + event.params._courtID.toString(), + ]); + court.save(); + return; + } + + const name = jsonObj.get("name"); + court.name = name ? name.toString() : null; + + const description = jsonObj.get("description"); + court.description = description ? description.toString() : null; + + const requiredSkills = jsonObj.get("requiredSkills"); + court.requiredSkills = requiredSkills ? requiredSkills.toString() : null; court.save(); } } diff --git a/subgraph/src/entities/Dispute.ts b/subgraph/src/entities/Dispute.ts index 5fac58f69..678f56cbd 100644 --- a/subgraph/src/entities/Dispute.ts +++ b/subgraph/src/entities/Dispute.ts @@ -1,6 +1,7 @@ import { KlerosCore, DisputeCreation } from "../../generated/KlerosCore/KlerosCore"; -import { Court, Dispute } from "../../generated/schema"; -import { ZERO } from "../utils"; +import { Court, Dispute, PeriodIndexCounter } from "../../generated/schema"; +import { ZERO, ONE } from "../utils"; +import { BigInt } from "@graphprotocol/graph-ts"; export function createDisputeFromEvent(event: DisputeCreation): void { const contract = KlerosCore.bind(event.address); @@ -9,14 +10,25 @@ export function createDisputeFromEvent(event: DisputeCreation): void { const dispute = new Dispute(disputeID.toString()); const courtID = disputeContractState.value0.toString(); dispute.court = courtID; + dispute.disputeID = disputeID; dispute.arbitrated = event.params._arbitrable.toHexString(); dispute.period = "evidence"; dispute.ruled = false; dispute.currentRuling = ZERO; dispute.tied = true; dispute.overridden = false; - dispute.lastPeriodChange = event.block.timestamp; + dispute.users = []; + dispute.lastPeriodChangeTs = event.block.timestamp; + dispute.lastPeriodChangeBlock = event.block.timestamp; dispute.lastPeriodChangeBlockNumber = event.block.number; + let counter = PeriodIndexCounter.load("evidence"); + if (!counter) { + counter = new PeriodIndexCounter("evidence"); + counter.counter = BigInt.fromI32(0); + } + dispute.periodNotificationIndex = counter.counter; + counter.counter = counter.counter.plus(ONE); + counter.save(); const court = Court.load(courtID); if (!court) return; dispute.periodDeadline = event.block.timestamp.plus(court.timesPerPeriod[0]); diff --git a/subgraph/src/entities/Draw.ts b/subgraph/src/entities/Draw.ts index d5fd35946..e5f5e2ce2 100644 --- a/subgraph/src/entities/Draw.ts +++ b/subgraph/src/entities/Draw.ts @@ -1,5 +1,6 @@ import { Draw as DrawEvent } from "../../generated/KlerosCore/KlerosCore"; -import { Draw } from "../../generated/schema"; +import { Draw, PeriodIndexCounter, User } from "../../generated/schema"; +import { BigInt } from "@graphprotocol/graph-ts"; export function createDrawFromEvent(event: DrawEvent): void { const disputeID = event.params._disputeID.toString(); @@ -9,6 +10,20 @@ export function createDrawFromEvent(event: DrawEvent): void { const drawID = `${disputeID}-${roundIndex.toString()}-${voteID.toString()}`; const draw = new Draw(drawID); draw.blockNumber = event.block.number; + let counter = PeriodIndexCounter.load("draw"); + if (!counter) { + counter = new PeriodIndexCounter("draw"); + counter.counter = BigInt.fromI32(0); + } + const user = User.load(event.params._address.toHexString()); + if (user) { + const duplicateNotification = user.disputes.includes(disputeID); + if (!duplicateNotification) { + draw.drawNotificationIndex = counter.counter; + counter.counter = counter.counter.plus(BigInt.fromI32(1)); + counter.save(); + } + } draw.dispute = disputeID; draw.round = roundID; draw.juror = event.params._address.toHexString(); diff --git a/subgraph/src/entities/Round.ts b/subgraph/src/entities/Round.ts index 8c67b1082..5ffb518e6 100644 --- a/subgraph/src/entities/Round.ts +++ b/subgraph/src/entities/Round.ts @@ -9,6 +9,7 @@ export function createRoundFromRoundInfo( ): void { const roundID = `${disputeID.toString()}-${roundIndex.toString()}`; const round = new Round(roundID); + round.isCurrentRound = true; const feeToken = roundInfo.feeToken.toHexString(); round.feeToken = feeToken === "0x0000000000000000000000000000000000000000" ? null : feeToken; round.disputeKit = roundInfo.disputeKitID.toString(); diff --git a/subgraph/src/entities/User.ts b/subgraph/src/entities/User.ts index a1b0ed340..e5a871508 100644 --- a/subgraph/src/entities/User.ts +++ b/subgraph/src/entities/User.ts @@ -1,5 +1,5 @@ -import { BigInt } from "@graphprotocol/graph-ts"; -import { User } from "../../generated/schema"; +import { BigInt, log } from "@graphprotocol/graph-ts"; +import { User, Dispute } from "../../generated/schema"; import { ONE, ZERO } from "../utils"; export function ensureUser(id: string): User { @@ -18,6 +18,7 @@ export function createUserFromAddress(id: string): User { user.totalDelayed = ZERO; user.activeDisputes = ZERO; user.disputes = []; + user.rounds = []; user.resolvedDisputes = []; user.totalResolvedDisputes = ZERO; user.totalAppealingDisputes = ZERO; @@ -34,6 +35,15 @@ export function addUserActiveDispute(id: string, disputeID: string): void { return; } user.disputes = user.disputes.concat([disputeID]); + const dispute = Dispute.load(disputeID); + if (!dispute) { + log.error("Dispute {} not found", [disputeID]); + return; + } else { + dispute.users.push(id); + dispute.save(); + } + user.activeDisputes = user.activeDisputes.plus(ONE); user.totalDisputes = user.totalDisputes.plus(ONE); user.save(); diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index a9c38f627..f736e3bae 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -1,6 +1,8 @@ specVersion: 0.0.4 schema: file: ./schema.graphql +features: + - ipfsOnEthereumContracts dataSources: - kind: ethereum name: KlerosCore From 8c48d81b24c83313dbe314753c1020400848de0a Mon Sep 17 00:00:00 2001 From: shotaronowhere Date: Tue, 17 Oct 2023 15:32:30 -0700 Subject: [PATCH 02/12] chore: update subgraph notification schema --- subgraph/schema.graphql | 3 +-- subgraph/src/KlerosCore.ts | 7 +++---- subgraph/src/entities/Dispute.ts | 1 - subgraph/src/entities/Draw.ts | 2 +- subgraph/src/entities/User.ts | 9 --------- 5 files changed, 5 insertions(+), 17 deletions(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index bd0b9375d..9f4d5ff06 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -157,7 +157,6 @@ type Dispute @entity { periodDeadline: BigInt! # uint256j periodNotificationIndex: BigInt! lastPeriodChangeTs: BigInt! - users: [User!]! lastPeriodChangeBlock: BigInt! lastPeriodChangeBlockNumber: BigInt! rounds: [Round!]! @derivedFrom(field: "dispute") @@ -193,7 +192,7 @@ type Draw @entity(immutable: true) { dispute: Dispute! round: Round! juror: User! - voteID: BigInt! + voteIDNum: BigInt! vote: Vote @derivedFrom(field: "draw") drawNotificationIndex: BigInt } diff --git a/subgraph/src/KlerosCore.ts b/subgraph/src/KlerosCore.ts index ab1b303e3..2348d3f16 100644 --- a/subgraph/src/KlerosCore.ts +++ b/subgraph/src/KlerosCore.ts @@ -134,14 +134,13 @@ export function handleNewPeriod(event: NewPeriod): void { counter.counter = BigInt.fromI32(0); } dispute.periodNotificationIndex = counter.counter; - const contract = KlerosCore.bind(event.address); - const courtContractState = contract.getTimesPerPeriod(BigInt.fromString(dispute.court)); - dispute.periodDeadline = event.block.timestamp.plus(courtContractState[event.params._period]); counter.counter = counter.counter.plus(ONE); counter.save(); dispute.lastPeriodChangeBlockNumber = event.block.number; if (newPeriod !== "execution") { - dispute.periodDeadline = event.block.timestamp.plus(court.timesPerPeriod[event.params._period]); + const contract = KlerosCore.bind(event.address); + const courtContractState = contract.getTimesPerPeriod(BigInt.fromString(dispute.court)); + dispute.periodDeadline = event.block.timestamp.plus(courtContractState[event.params._period]); } else { dispute.periodDeadline = BigInt.fromU64(U64.MAX_VALUE); } diff --git a/subgraph/src/entities/Dispute.ts b/subgraph/src/entities/Dispute.ts index 678f56cbd..55ce45daf 100644 --- a/subgraph/src/entities/Dispute.ts +++ b/subgraph/src/entities/Dispute.ts @@ -17,7 +17,6 @@ export function createDisputeFromEvent(event: DisputeCreation): void { dispute.currentRuling = ZERO; dispute.tied = true; dispute.overridden = false; - dispute.users = []; dispute.lastPeriodChangeTs = event.block.timestamp; dispute.lastPeriodChangeBlock = event.block.timestamp; dispute.lastPeriodChangeBlockNumber = event.block.number; diff --git a/subgraph/src/entities/Draw.ts b/subgraph/src/entities/Draw.ts index e5f5e2ce2..ab58dd87d 100644 --- a/subgraph/src/entities/Draw.ts +++ b/subgraph/src/entities/Draw.ts @@ -27,6 +27,6 @@ export function createDrawFromEvent(event: DrawEvent): void { draw.dispute = disputeID; draw.round = roundID; draw.juror = event.params._address.toHexString(); - draw.voteID = voteID; + draw.voteIDNum = voteID; draw.save(); } diff --git a/subgraph/src/entities/User.ts b/subgraph/src/entities/User.ts index e5a871508..8951f4137 100644 --- a/subgraph/src/entities/User.ts +++ b/subgraph/src/entities/User.ts @@ -35,15 +35,6 @@ export function addUserActiveDispute(id: string, disputeID: string): void { return; } user.disputes = user.disputes.concat([disputeID]); - const dispute = Dispute.load(disputeID); - if (!dispute) { - log.error("Dispute {} not found", [disputeID]); - return; - } else { - dispute.users.push(id); - dispute.save(); - } - user.activeDisputes = user.activeDisputes.plus(ONE); user.totalDisputes = user.totalDisputes.plus(ONE); user.save(); From e7783ffb334cedceea3feca75fcd01de113fba08 Mon Sep 17 00:00:00 2001 From: shotaronowhere Date: Tue, 17 Oct 2023 18:47:37 -0700 Subject: [PATCH 03/12] chore: subgraph refactor --- subgraph/schema.graphql | 3 +-- subgraph/src/entities/Dispute.ts | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index 9f4d5ff06..b82f1f6ea 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -154,10 +154,9 @@ type Dispute @entity { currentRuling: BigInt! tied: Boolean! overridden: Boolean! - periodDeadline: BigInt! # uint256j + periodDeadline: BigInt! periodNotificationIndex: BigInt! lastPeriodChangeTs: BigInt! - lastPeriodChangeBlock: BigInt! lastPeriodChangeBlockNumber: BigInt! rounds: [Round!]! @derivedFrom(field: "dispute") currentRound: Round! diff --git a/subgraph/src/entities/Dispute.ts b/subgraph/src/entities/Dispute.ts index 55ce45daf..bc2459946 100644 --- a/subgraph/src/entities/Dispute.ts +++ b/subgraph/src/entities/Dispute.ts @@ -18,7 +18,6 @@ export function createDisputeFromEvent(event: DisputeCreation): void { dispute.tied = true; dispute.overridden = false; dispute.lastPeriodChangeTs = event.block.timestamp; - dispute.lastPeriodChangeBlock = event.block.timestamp; dispute.lastPeriodChangeBlockNumber = event.block.number; let counter = PeriodIndexCounter.load("evidence"); if (!counter) { From ad9a27059a265b6df4bcf3e5b8b784b55830cd7d Mon Sep 17 00:00:00 2001 From: shotaronowhere Date: Tue, 17 Oct 2023 19:06:03 -0700 Subject: [PATCH 04/12] chore: refactor subgraph --- subgraph/src/PolicyRegistry.ts | 47 +++++++-------------- subgraph/src/entities/Dispute.ts | 13 +++--- subgraph/src/entities/Draw.ts | 13 +++--- subgraph/src/entities/PeriodIndexCounter.ts | 11 +++++ 4 files changed, 36 insertions(+), 48 deletions(-) create mode 100644 subgraph/src/entities/PeriodIndexCounter.ts diff --git a/subgraph/src/PolicyRegistry.ts b/subgraph/src/PolicyRegistry.ts index 8a9a56707..73fb4a3db 100644 --- a/subgraph/src/PolicyRegistry.ts +++ b/subgraph/src/PolicyRegistry.ts @@ -1,6 +1,6 @@ import { PolicyUpdate } from "../generated/PolicyRegistry/PolicyRegistry"; import { Court } from "../generated/schema"; -import { ipfs, log, json, Bytes } from "@graphprotocol/graph-ts"; +import { ipfs, log, json, Bytes, TypedMap, JSONValue } from "@graphprotocol/graph-ts"; export function handlePolicyUpdate(event: PolicyUpdate): void { const courtID = event.params._courtID.toString(); @@ -8,42 +8,25 @@ export function handlePolicyUpdate(event: PolicyUpdate): void { if (court) { court.policy = event.params._policy; court.name = event.params._courtName; + court.save(); let jsonStr = ipfs.cat(event.params._policy); - if (!jsonStr) { - log.error("Failed to fetch policy #{} SubcourtID: {}", [event.params._policy, event.params._courtID.toString()]); - court.save(); - return; - } - - let jsonObjValueAndSuccess = json.try_fromBytes(jsonStr as Bytes); - if (!jsonObjValueAndSuccess.isOk) { - log.error(`Error getting json object value for policy #{} SubcourtID: {}`, [ - event.params._policy, - event.params._courtID.toString(), - ]); - court.save(); - return; - } - - let jsonObj = jsonObjValueAndSuccess.value.toObject(); - if (!jsonObj) { - log.error(`Error converting object value for policy #{} SubcourtID: {}`, [ - event.params._policy, - event.params._courtID.toString(), - ]); - court.save(); - return; - } + if (!jsonStr) return; - const name = jsonObj.get("name"); - court.name = name ? name.toString() : null; + const jsonObjValueAndSuccess = json.try_fromBytes(jsonStr as Bytes); + if (!jsonObjValueAndSuccess.isOk) return; - const description = jsonObj.get("description"); - court.description = description ? description.toString() : null; + const jsonObj = jsonObjValueAndSuccess.value.toObject(); + if (!jsonObj) return; - const requiredSkills = jsonObj.get("requiredSkills"); - court.requiredSkills = requiredSkills ? requiredSkills.toString() : null; + court.name = tryGetValue(jsonObj, "name"); + court.description = tryGetValue(jsonObj, "description"); + court.requiredSkills = tryGetValue(jsonObj, "requiredSkills"); court.save(); } } + +function tryGetValue(jsonObj: TypedMap, key: string): string | null { + const value = jsonObj.get(key); + return value ? value.toString() : null; +} diff --git a/subgraph/src/entities/Dispute.ts b/subgraph/src/entities/Dispute.ts index bc2459946..1eddb118d 100644 --- a/subgraph/src/entities/Dispute.ts +++ b/subgraph/src/entities/Dispute.ts @@ -2,6 +2,7 @@ import { KlerosCore, DisputeCreation } from "../../generated/KlerosCore/KlerosCo import { Court, Dispute, PeriodIndexCounter } from "../../generated/schema"; import { ZERO, ONE } from "../utils"; import { BigInt } from "@graphprotocol/graph-ts"; +import { ensurePeriodIndexCounter } from "./PeriodIndexCounter"; export function createDisputeFromEvent(event: DisputeCreation): void { const contract = KlerosCore.bind(event.address); @@ -19,14 +20,10 @@ export function createDisputeFromEvent(event: DisputeCreation): void { dispute.overridden = false; dispute.lastPeriodChangeTs = event.block.timestamp; dispute.lastPeriodChangeBlockNumber = event.block.number; - let counter = PeriodIndexCounter.load("evidence"); - if (!counter) { - counter = new PeriodIndexCounter("evidence"); - counter.counter = BigInt.fromI32(0); - } - dispute.periodNotificationIndex = counter.counter; - counter.counter = counter.counter.plus(ONE); - counter.save(); + const PeriodIndexCounter = ensurePeriodIndexCounter(dispute.period); + dispute.periodNotificationIndex = PeriodIndexCounter.counter; + PeriodIndexCounter.counter = PeriodIndexCounter.counter.plus(ONE); + PeriodIndexCounter.save(); const court = Court.load(courtID); if (!court) return; dispute.periodDeadline = event.block.timestamp.plus(court.timesPerPeriod[0]); diff --git a/subgraph/src/entities/Draw.ts b/subgraph/src/entities/Draw.ts index ab58dd87d..dffc11f33 100644 --- a/subgraph/src/entities/Draw.ts +++ b/subgraph/src/entities/Draw.ts @@ -1,6 +1,7 @@ import { Draw as DrawEvent } from "../../generated/KlerosCore/KlerosCore"; import { Draw, PeriodIndexCounter, User } from "../../generated/schema"; import { BigInt } from "@graphprotocol/graph-ts"; +import { ensurePeriodIndexCounter } from "./PeriodIndexCounter"; export function createDrawFromEvent(event: DrawEvent): void { const disputeID = event.params._disputeID.toString(); @@ -10,18 +11,14 @@ export function createDrawFromEvent(event: DrawEvent): void { const drawID = `${disputeID}-${roundIndex.toString()}-${voteID.toString()}`; const draw = new Draw(drawID); draw.blockNumber = event.block.number; - let counter = PeriodIndexCounter.load("draw"); - if (!counter) { - counter = new PeriodIndexCounter("draw"); - counter.counter = BigInt.fromI32(0); - } const user = User.load(event.params._address.toHexString()); if (user) { const duplicateNotification = user.disputes.includes(disputeID); if (!duplicateNotification) { - draw.drawNotificationIndex = counter.counter; - counter.counter = counter.counter.plus(BigInt.fromI32(1)); - counter.save(); + const periodIndex = ensurePeriodIndexCounter("draw"); + draw.drawNotificationIndex = periodIndex.counter; + periodIndex.counter = periodIndex.counter.plus(BigInt.fromI32(1)); + periodIndex.save(); } } draw.dispute = disputeID; diff --git a/subgraph/src/entities/PeriodIndexCounter.ts b/subgraph/src/entities/PeriodIndexCounter.ts new file mode 100644 index 000000000..2ee82b388 --- /dev/null +++ b/subgraph/src/entities/PeriodIndexCounter.ts @@ -0,0 +1,11 @@ +import { PeriodIndexCounter } from "../../generated/schema"; +import { BigInt } from "@graphprotocol/graph-ts"; + +export function ensurePeriodIndexCounter(id: string): PeriodIndexCounter { + let counter = PeriodIndexCounter.load(id); + if (!counter) { + counter = new PeriodIndexCounter(id); + counter.counter = BigInt.fromI32(0); + } + return counter; +} From 3d9eaa5ff5fd81e2c02bf8f7182791becc530191 Mon Sep 17 00:00:00 2001 From: shotaronowhere Date: Tue, 17 Oct 2023 19:11:41 -0700 Subject: [PATCH 05/12] chore: subgraph refactor --- subgraph/src/entities/Dispute.ts | 15 +++++---------- subgraph/src/entities/Draw.ts | 15 ++++----------- subgraph/src/entities/PeriodIndexCounter.ts | 7 +++++-- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/subgraph/src/entities/Dispute.ts b/subgraph/src/entities/Dispute.ts index 1eddb118d..94088f14c 100644 --- a/subgraph/src/entities/Dispute.ts +++ b/subgraph/src/entities/Dispute.ts @@ -1,13 +1,11 @@ import { KlerosCore, DisputeCreation } from "../../generated/KlerosCore/KlerosCore"; -import { Court, Dispute, PeriodIndexCounter } from "../../generated/schema"; -import { ZERO, ONE } from "../utils"; -import { BigInt } from "@graphprotocol/graph-ts"; -import { ensurePeriodIndexCounter } from "./PeriodIndexCounter"; +import { Court, Dispute } from "../../generated/schema"; +import { ZERO } from "../utils"; +import { getAndIncrementCounter } from "./PeriodIndexCounter"; export function createDisputeFromEvent(event: DisputeCreation): void { - const contract = KlerosCore.bind(event.address); const disputeID = event.params._disputeID; - const disputeContractState = contract.disputes(disputeID); + const disputeContractState = KlerosCore.bind(event.address).disputes(disputeID); const dispute = new Dispute(disputeID.toString()); const courtID = disputeContractState.value0.toString(); dispute.court = courtID; @@ -20,10 +18,7 @@ export function createDisputeFromEvent(event: DisputeCreation): void { dispute.overridden = false; dispute.lastPeriodChangeTs = event.block.timestamp; dispute.lastPeriodChangeBlockNumber = event.block.number; - const PeriodIndexCounter = ensurePeriodIndexCounter(dispute.period); - dispute.periodNotificationIndex = PeriodIndexCounter.counter; - PeriodIndexCounter.counter = PeriodIndexCounter.counter.plus(ONE); - PeriodIndexCounter.save(); + dispute.periodNotificationIndex = getAndIncrementCounter(dispute.period); const court = Court.load(courtID); if (!court) return; dispute.periodDeadline = event.block.timestamp.plus(court.timesPerPeriod[0]); diff --git a/subgraph/src/entities/Draw.ts b/subgraph/src/entities/Draw.ts index dffc11f33..19e9f5aad 100644 --- a/subgraph/src/entities/Draw.ts +++ b/subgraph/src/entities/Draw.ts @@ -1,7 +1,6 @@ import { Draw as DrawEvent } from "../../generated/KlerosCore/KlerosCore"; -import { Draw, PeriodIndexCounter, User } from "../../generated/schema"; -import { BigInt } from "@graphprotocol/graph-ts"; -import { ensurePeriodIndexCounter } from "./PeriodIndexCounter"; +import { Draw, User } from "../../generated/schema"; +import { getAndIncrementCounter } from "./PeriodIndexCounter"; export function createDrawFromEvent(event: DrawEvent): void { const disputeID = event.params._disputeID.toString(); @@ -12,14 +11,8 @@ export function createDrawFromEvent(event: DrawEvent): void { const draw = new Draw(drawID); draw.blockNumber = event.block.number; const user = User.load(event.params._address.toHexString()); - if (user) { - const duplicateNotification = user.disputes.includes(disputeID); - if (!duplicateNotification) { - const periodIndex = ensurePeriodIndexCounter("draw"); - draw.drawNotificationIndex = periodIndex.counter; - periodIndex.counter = periodIndex.counter.plus(BigInt.fromI32(1)); - periodIndex.save(); - } + if (user && !user.disputes.includes(disputeID)) { + draw.drawNotificationIndex = getAndIncrementCounter("draw"); } draw.dispute = disputeID; draw.round = roundID; diff --git a/subgraph/src/entities/PeriodIndexCounter.ts b/subgraph/src/entities/PeriodIndexCounter.ts index 2ee82b388..86d9b5e82 100644 --- a/subgraph/src/entities/PeriodIndexCounter.ts +++ b/subgraph/src/entities/PeriodIndexCounter.ts @@ -1,11 +1,14 @@ import { PeriodIndexCounter } from "../../generated/schema"; import { BigInt } from "@graphprotocol/graph-ts"; -export function ensurePeriodIndexCounter(id: string): PeriodIndexCounter { +export function getAndIncrementCounter(id: string): BigInt { let counter = PeriodIndexCounter.load(id); if (!counter) { counter = new PeriodIndexCounter(id); counter.counter = BigInt.fromI32(0); } - return counter; + const counterOld = counter.counter; + counter.counter = counter.counter.plus(BigInt.fromI32(1)); + counter.save(); + return counterOld; } From 9f3a289cd09bfb964ef8b135444b4db25ca859ee Mon Sep 17 00:00:00 2001 From: shotaronowhere Date: Tue, 17 Oct 2023 19:21:03 -0700 Subject: [PATCH 06/12] chore: subgraph refactor --- subgraph/src/PolicyRegistry.ts | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/subgraph/src/PolicyRegistry.ts b/subgraph/src/PolicyRegistry.ts index 73fb4a3db..e6e8c5373 100644 --- a/subgraph/src/PolicyRegistry.ts +++ b/subgraph/src/PolicyRegistry.ts @@ -1,6 +1,6 @@ import { PolicyUpdate } from "../generated/PolicyRegistry/PolicyRegistry"; import { Court } from "../generated/schema"; -import { ipfs, log, json, Bytes, TypedMap, JSONValue } from "@graphprotocol/graph-ts"; +import { ipfs, json, Bytes, TypedMap, JSONValue } from "@graphprotocol/graph-ts"; export function handlePolicyUpdate(event: PolicyUpdate): void { const courtID = event.params._courtID.toString(); @@ -10,13 +10,7 @@ export function handlePolicyUpdate(event: PolicyUpdate): void { court.name = event.params._courtName; court.save(); - let jsonStr = ipfs.cat(event.params._policy); - if (!jsonStr) return; - - const jsonObjValueAndSuccess = json.try_fromBytes(jsonStr as Bytes); - if (!jsonObjValueAndSuccess.isOk) return; - - const jsonObj = jsonObjValueAndSuccess.value.toObject(); + const jsonObj = getJsonObj(event.params._policy); if (!jsonObj) return; court.name = tryGetValue(jsonObj, "name"); @@ -30,3 +24,16 @@ function tryGetValue(jsonObj: TypedMap, key: string): string const value = jsonObj.get(key); return value ? value.toString() : null; } + +function getJsonObj(CID: string): TypedMap | null { + const jsonStr = ipfs.cat(CID); + if (!jsonStr) return null; + + const jsonObjValueAndSuccess = json.try_fromBytes(jsonStr as Bytes); + if (!jsonObjValueAndSuccess.isOk) return null; + + const jsonObj = jsonObjValueAndSuccess.value.toObject(); + if (!jsonObj) return null; + + return jsonObj; +} From fb14bf21ba1974110e7a4ae786ddd42147b80a42 Mon Sep 17 00:00:00 2001 From: shotaronowhere Date: Tue, 17 Oct 2023 19:53:24 -0700 Subject: [PATCH 07/12] fix: subgraph mapping typo --- subgraph/src/KlerosCore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subgraph/src/KlerosCore.ts b/subgraph/src/KlerosCore.ts index 2348d3f16..ce7ce18ed 100644 --- a/subgraph/src/KlerosCore.ts +++ b/subgraph/src/KlerosCore.ts @@ -127,7 +127,7 @@ export function handleNewPeriod(event: NewPeriod): void { dispute.period = newPeriod; dispute.lastPeriodChangeTs = event.block.timestamp; - dispute.lastPeriodChangeBlock = event.block.number; + dispute.lastPeriodChangeBlockNumber = event.block.number; let counter = PeriodIndexCounter.load(newPeriod); if (!counter) { counter = new PeriodIndexCounter(newPeriod); From d405d385e8aff9a1206532654de6a36bfbce3ea9 Mon Sep 17 00:00:00 2001 From: shotaronowhere Date: Wed, 18 Oct 2023 13:50:47 -0700 Subject: [PATCH 08/12] feat(subgraph): handle court jump and refactor --- subgraph/schema.graphql | 8 ++------ subgraph/src/KlerosCore.ts | 27 ++++++++++++------------- subgraph/src/PolicyRegistry.ts | 27 ------------------------- subgraph/src/entities/ClassicDispute.ts | 1 - subgraph/src/entities/Dispute.ts | 2 +- subgraph/subgraph.yaml | 4 ++-- 6 files changed, 18 insertions(+), 51 deletions(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index b82f1f6ea..ad646bee1 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -119,9 +119,6 @@ type Court @entity { id: ID! policy: String name: String - description: String - summary: String - requiredSkills: String parent: Court hiddenVotes: Boolean! children: [Court!]! @derivedFrom(field: "parent") @@ -156,14 +153,14 @@ type Dispute @entity { overridden: Boolean! periodDeadline: BigInt! periodNotificationIndex: BigInt! - lastPeriodChangeTs: BigInt! + lastPeriodChange: BigInt! lastPeriodChangeBlockNumber: BigInt! rounds: [Round!]! @derivedFrom(field: "dispute") currentRound: Round! currentRoundIndex: BigInt! jurors: [User!]! @derivedFrom(field: "disputes") shifts: [TokenAndETHShift!]! @derivedFrom(field: "dispute") - disputeKitDispute: DisputeKitDispute @derivedFrom(field: "coreDispute") + disputeKitDispute: [DisputeKitDispute!]! @derivedFrom(field: "coreDispute") } type PeriodIndexCounter @entity { @@ -241,7 +238,6 @@ type ClassicDispute implements DisputeKitDispute @entity { currentLocalRoundIndex: BigInt! numberOfChoices: BigInt! - jumped: Boolean! extraData: Bytes! } diff --git a/subgraph/src/KlerosCore.ts b/subgraph/src/KlerosCore.ts index ce7ce18ed..71bb78fc4 100644 --- a/subgraph/src/KlerosCore.ts +++ b/subgraph/src/KlerosCore.ts @@ -10,6 +10,7 @@ import { NewPeriod, StakeSet, TokenAndETHShift as TokenAndETHShiftEvent, + CourtJump, Ruling, StakeDelayed, AcceptedFeeToken, @@ -25,10 +26,11 @@ import { updateJurorDelayedStake, updateJurorStake } from "./entities/JurorToken import { createDrawFromEvent } from "./entities/Draw"; import { updateTokenAndEthShiftFromEvent } from "./entities/TokenAndEthShift"; import { updateArbitrableCases } from "./entities/Arbitrable"; -import { Court, Dispute, User, PeriodIndexCounter } from "../generated/schema"; +import { Court, Dispute, User } from "../generated/schema"; import { BigInt } from "@graphprotocol/graph-ts"; import { updatePenalty } from "./entities/Penalty"; import { ensureFeeToken } from "./entities/FeeToken"; +import { getAndIncrementCounter } from "./entities/PeriodIndexCounter"; function getPeriodName(index: i32): string { const periodArray = ["evidence", "commit", "vote", "appeal", "execution"]; @@ -126,21 +128,11 @@ export function handleNewPeriod(event: NewPeriod): void { } dispute.period = newPeriod; - dispute.lastPeriodChangeTs = event.block.timestamp; - dispute.lastPeriodChangeBlockNumber = event.block.number; - let counter = PeriodIndexCounter.load(newPeriod); - if (!counter) { - counter = new PeriodIndexCounter(newPeriod); - counter.counter = BigInt.fromI32(0); - } - dispute.periodNotificationIndex = counter.counter; - counter.counter = counter.counter.plus(ONE); - counter.save(); + dispute.lastPeriodChange = event.block.timestamp; dispute.lastPeriodChangeBlockNumber = event.block.number; + dispute.periodNotificationIndex = getAndIncrementCounter(newPeriod); if (newPeriod !== "execution") { - const contract = KlerosCore.bind(event.address); - const courtContractState = contract.getTimesPerPeriod(BigInt.fromString(dispute.court)); - dispute.periodDeadline = event.block.timestamp.plus(courtContractState[event.params._period]); + dispute.periodDeadline = event.block.timestamp.plus(court.timesPerPeriod[event.params._period]); } else { dispute.periodDeadline = BigInt.fromU64(U64.MAX_VALUE); } @@ -175,6 +167,13 @@ export function handleAppealDecision(event: AppealDecision): void { createRoundFromRoundInfo(disputeID, newRoundIndex, roundInfo); } +export function handleCourtJump(event: CourtJump): void { + const dispute = Dispute.load(event.params._disputeID.toString()); + if (!dispute) return; + dispute.court = event.params._toCourtID.toString(); + dispute.save(); +} + export function handleDraw(event: DrawEvent): void { createDrawFromEvent(event); const disputeID = event.params._disputeID.toString(); diff --git a/subgraph/src/PolicyRegistry.ts b/subgraph/src/PolicyRegistry.ts index e6e8c5373..6820698e3 100644 --- a/subgraph/src/PolicyRegistry.ts +++ b/subgraph/src/PolicyRegistry.ts @@ -1,6 +1,5 @@ import { PolicyUpdate } from "../generated/PolicyRegistry/PolicyRegistry"; import { Court } from "../generated/schema"; -import { ipfs, json, Bytes, TypedMap, JSONValue } from "@graphprotocol/graph-ts"; export function handlePolicyUpdate(event: PolicyUpdate): void { const courtID = event.params._courtID.toString(); @@ -9,31 +8,5 @@ export function handlePolicyUpdate(event: PolicyUpdate): void { court.policy = event.params._policy; court.name = event.params._courtName; court.save(); - - const jsonObj = getJsonObj(event.params._policy); - if (!jsonObj) return; - - court.name = tryGetValue(jsonObj, "name"); - court.description = tryGetValue(jsonObj, "description"); - court.requiredSkills = tryGetValue(jsonObj, "requiredSkills"); - court.save(); } } - -function tryGetValue(jsonObj: TypedMap, key: string): string | null { - const value = jsonObj.get(key); - return value ? value.toString() : null; -} - -function getJsonObj(CID: string): TypedMap | null { - const jsonStr = ipfs.cat(CID); - if (!jsonStr) return null; - - const jsonObjValueAndSuccess = json.try_fromBytes(jsonStr as Bytes); - if (!jsonObjValueAndSuccess.isOk) return null; - - const jsonObj = jsonObjValueAndSuccess.value.toObject(); - if (!jsonObj) return null; - - return jsonObj; -} diff --git a/subgraph/src/entities/ClassicDispute.ts b/subgraph/src/entities/ClassicDispute.ts index 30d49bf60..9d49c7210 100644 --- a/subgraph/src/entities/ClassicDispute.ts +++ b/subgraph/src/entities/ClassicDispute.ts @@ -8,7 +8,6 @@ export function createClassicDisputeFromEvent(event: DisputeCreation): void { classicDispute.coreDispute = coreDisputeID; classicDispute.currentLocalRoundIndex = ZERO; classicDispute.numberOfChoices = event.params._numberOfChoices; - classicDispute.jumped = false; classicDispute.extraData = event.params._extraData; classicDispute.save(); } diff --git a/subgraph/src/entities/Dispute.ts b/subgraph/src/entities/Dispute.ts index 94088f14c..a34a289f8 100644 --- a/subgraph/src/entities/Dispute.ts +++ b/subgraph/src/entities/Dispute.ts @@ -16,7 +16,7 @@ export function createDisputeFromEvent(event: DisputeCreation): void { dispute.currentRuling = ZERO; dispute.tied = true; dispute.overridden = false; - dispute.lastPeriodChangeTs = event.block.timestamp; + dispute.lastPeriodChange = event.block.timestamp; dispute.lastPeriodChangeBlockNumber = event.block.number; dispute.periodNotificationIndex = getAndIncrementCounter(dispute.period); const court = Court.load(courtID); diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index f736e3bae..385cec12c 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -1,8 +1,6 @@ specVersion: 0.0.4 schema: file: ./schema.graphql -features: - - ipfsOnEthereumContracts dataSources: - kind: ethereum name: KlerosCore @@ -58,6 +56,8 @@ dataSources: handler: handleRuling - event: AcceptedFeeToken(indexed address,indexed bool) handler: handleAcceptedFeeToken + - event: CourtJump(indexed uint256,indexed uint256,indexed uint96,uint96) + handler: handleCourtJump file: ./src/KlerosCore.ts - kind: ethereum name: PolicyRegistry From 5d18a33da63da0cc7e8f9dec925526a808180e84 Mon Sep 17 00:00:00 2001 From: shotaronowhere Date: Wed, 18 Oct 2023 13:54:39 -0700 Subject: [PATCH 09/12] chore(subgraph): refactor counter disambiguation --- subgraph/src/KlerosCore.ts | 4 ++-- subgraph/src/entities/Dispute.ts | 4 ++-- subgraph/src/entities/Draw.ts | 4 ++-- subgraph/src/entities/PeriodIndexCounter.ts | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/subgraph/src/KlerosCore.ts b/subgraph/src/KlerosCore.ts index 71bb78fc4..deb9fbba8 100644 --- a/subgraph/src/KlerosCore.ts +++ b/subgraph/src/KlerosCore.ts @@ -30,7 +30,7 @@ import { Court, Dispute, User } from "../generated/schema"; import { BigInt } from "@graphprotocol/graph-ts"; import { updatePenalty } from "./entities/Penalty"; import { ensureFeeToken } from "./entities/FeeToken"; -import { getAndIncrementCounter } from "./entities/PeriodIndexCounter"; +import { getAndIncrementPeriodCounter } from "./entities/PeriodIndexCounter"; function getPeriodName(index: i32): string { const periodArray = ["evidence", "commit", "vote", "appeal", "execution"]; @@ -130,7 +130,7 @@ export function handleNewPeriod(event: NewPeriod): void { dispute.period = newPeriod; dispute.lastPeriodChange = event.block.timestamp; dispute.lastPeriodChangeBlockNumber = event.block.number; - dispute.periodNotificationIndex = getAndIncrementCounter(newPeriod); + dispute.periodNotificationIndex = getAndIncrementPeriodCounter(newPeriod); if (newPeriod !== "execution") { dispute.periodDeadline = event.block.timestamp.plus(court.timesPerPeriod[event.params._period]); } else { diff --git a/subgraph/src/entities/Dispute.ts b/subgraph/src/entities/Dispute.ts index a34a289f8..3cbcbcbb6 100644 --- a/subgraph/src/entities/Dispute.ts +++ b/subgraph/src/entities/Dispute.ts @@ -1,7 +1,7 @@ import { KlerosCore, DisputeCreation } from "../../generated/KlerosCore/KlerosCore"; import { Court, Dispute } from "../../generated/schema"; import { ZERO } from "../utils"; -import { getAndIncrementCounter } from "./PeriodIndexCounter"; +import { getAndIncrementPeriodCounter } from "./PeriodIndexCounter"; export function createDisputeFromEvent(event: DisputeCreation): void { const disputeID = event.params._disputeID; @@ -18,7 +18,7 @@ export function createDisputeFromEvent(event: DisputeCreation): void { dispute.overridden = false; dispute.lastPeriodChange = event.block.timestamp; dispute.lastPeriodChangeBlockNumber = event.block.number; - dispute.periodNotificationIndex = getAndIncrementCounter(dispute.period); + dispute.periodNotificationIndex = getAndIncrementPeriodCounter(dispute.period); const court = Court.load(courtID); if (!court) return; dispute.periodDeadline = event.block.timestamp.plus(court.timesPerPeriod[0]); diff --git a/subgraph/src/entities/Draw.ts b/subgraph/src/entities/Draw.ts index 19e9f5aad..a62567b32 100644 --- a/subgraph/src/entities/Draw.ts +++ b/subgraph/src/entities/Draw.ts @@ -1,6 +1,6 @@ import { Draw as DrawEvent } from "../../generated/KlerosCore/KlerosCore"; import { Draw, User } from "../../generated/schema"; -import { getAndIncrementCounter } from "./PeriodIndexCounter"; +import { getAndIncrementPeriodCounter } from "./PeriodIndexCounter"; export function createDrawFromEvent(event: DrawEvent): void { const disputeID = event.params._disputeID.toString(); @@ -12,7 +12,7 @@ export function createDrawFromEvent(event: DrawEvent): void { draw.blockNumber = event.block.number; const user = User.load(event.params._address.toHexString()); if (user && !user.disputes.includes(disputeID)) { - draw.drawNotificationIndex = getAndIncrementCounter("draw"); + draw.drawNotificationIndex = getAndIncrementPeriodCounter("draw"); } draw.dispute = disputeID; draw.round = roundID; diff --git a/subgraph/src/entities/PeriodIndexCounter.ts b/subgraph/src/entities/PeriodIndexCounter.ts index 86d9b5e82..c685f8904 100644 --- a/subgraph/src/entities/PeriodIndexCounter.ts +++ b/subgraph/src/entities/PeriodIndexCounter.ts @@ -1,7 +1,7 @@ import { PeriodIndexCounter } from "../../generated/schema"; import { BigInt } from "@graphprotocol/graph-ts"; -export function getAndIncrementCounter(id: string): BigInt { +export function getAndIncrementPeriodCounter(id: string): BigInt { let counter = PeriodIndexCounter.load(id); if (!counter) { counter = new PeriodIndexCounter(id); From d15b62de33f048dcb2be6c50e5e1705092466f8e Mon Sep 17 00:00:00 2001 From: Aleix <80388279+alcercu@users.noreply.github.com> Date: Thu, 19 Oct 2023 16:14:41 +0200 Subject: [PATCH 10/12] chore(subgraph): remove unused imports on User.ts --- subgraph/src/entities/User.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subgraph/src/entities/User.ts b/subgraph/src/entities/User.ts index 8951f4137..918878bcb 100644 --- a/subgraph/src/entities/User.ts +++ b/subgraph/src/entities/User.ts @@ -1,5 +1,5 @@ -import { BigInt, log } from "@graphprotocol/graph-ts"; -import { User, Dispute } from "../../generated/schema"; +import { BigInt } from "@graphprotocol/graph-ts"; +import { User } from "../../generated/schema"; import { ONE, ZERO } from "../utils"; export function ensureUser(id: string): User { From 7d42f962ee0fac37e0b95ecd642e6c6687f44af4 Mon Sep 17 00:00:00 2001 From: alcercu <333aleix333@gmail.com> Date: Thu, 19 Oct 2023 16:36:23 +0200 Subject: [PATCH 11/12] chore(web): update voteID subgraph variable name to voteIDNum --- web/src/hooks/queries/useDrawQuery.ts | 4 ++-- web/src/pages/Cases/CaseDetails/Voting/index.tsx | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/web/src/hooks/queries/useDrawQuery.ts b/web/src/hooks/queries/useDrawQuery.ts index b152b5070..b94802abc 100644 --- a/web/src/hooks/queries/useDrawQuery.ts +++ b/web/src/hooks/queries/useDrawQuery.ts @@ -7,14 +7,14 @@ export type { DrawQuery }; const drawQuery = graphql(` query Draw($address: String, $disputeID: String, $roundID: String) { draws(where: { dispute: $disputeID, juror: $address, round: $roundID }) { - voteID + voteIDNum } } `); export const useDrawQuery = (address?: string | null, disputeID?: string, roundID?: string) => { const isEnabled = !!(address && disputeID && roundID); - return useQuery({ + return useQuery({ queryKey: [`drawQuery${[address, disputeID, roundID]}`], enabled: isEnabled, queryFn: async () => await graphqlQueryFnHelper(drawQuery, { address, disputeID, roundID }), diff --git a/web/src/pages/Cases/CaseDetails/Voting/index.tsx b/web/src/pages/Cases/CaseDetails/Voting/index.tsx index 751f73481..650b9e74a 100644 --- a/web/src/pages/Cases/CaseDetails/Voting/index.tsx +++ b/web/src/pages/Cases/CaseDetails/Voting/index.tsx @@ -48,7 +48,7 @@ const Voting: React.FC = ({ arbitrable, currentPeriodIndex }) => { const { data: appealCost } = useAppealCost(id); const { data: drawData } = useDrawQuery(address?.toLowerCase(), id, disputeData?.dispute?.currentRound.id); const roundId = disputeData?.dispute?.currentRoundIndex; - const voteId = drawData?.draws?.[0]?.voteID; + const voteId = drawData?.draws?.[0]?.voteIDNum; const { data: voted } = useDisputeKitClassicIsVoteActive({ enabled: !isUndefined(roundId) && !isUndefined(voteId), args: [BigInt(id ?? 0), roundId, voteId], @@ -101,7 +101,11 @@ const Voting: React.FC = ({ arbitrable, currentPeriodIndex }) => { !voted ? ( <> - draw.voteID)} /> + draw.voteIDNum)} + /> ) : ( From 7cce1c7c932bbd2fd7388e2fb229c5fefb712ce7 Mon Sep 17 00:00:00 2001 From: alcercu <333aleix333@gmail.com> Date: Thu, 19 Oct 2023 17:14:21 +0200 Subject: [PATCH 12/12] chore(web): add getLocalRounds function to work with the fact that disputeKitDispute is now an array --- web/src/components/DisputeCard/index.tsx | 3 ++- .../components/Verdict/DisputeTimeline.tsx | 11 +++++----- .../hooks/queries/useClassicAppealQuery.ts | 2 +- web/src/hooks/useClassicAppealContext.tsx | 3 ++- web/src/pages/Cases/CaseDetails/Overview.tsx | 3 ++- .../CaseDetails/Voting/VotingHistory.tsx | 7 ++++--- web/src/utils/getLocalRounds.ts | 20 +++++++++++++++++++ 7 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 web/src/utils/getLocalRounds.ts diff --git a/web/src/components/DisputeCard/index.tsx b/web/src/components/DisputeCard/index.tsx index b9eaf5d7a..39895673c 100644 --- a/web/src/components/DisputeCard/index.tsx +++ b/web/src/components/DisputeCard/index.tsx @@ -14,6 +14,7 @@ import { useVotingHistory } from "queries/useVotingHistory"; import DisputeInfo from "./DisputeInfo"; import PeriodBanner from "./PeriodBanner"; import { isUndefined } from "utils/index"; +import { getLocalRounds } from "utils/getLocalRounds"; const StyledCard = styled(Card)` width: 100%; @@ -104,7 +105,7 @@ const DisputeCard: React.FC = ({ id, arbitrated, period, lastPerio const courtName = courtPolicy?.name; const category = disputeTemplate ? disputeTemplate.category : undefined; const { data: votingHistory } = useVotingHistory(id); - const localRounds = votingHistory?.dispute?.disputeKitDispute?.localRounds; + const localRounds = getLocalRounds(votingHistory?.dispute?.disputeKitDispute); const navigate = useNavigate(); return ( <> diff --git a/web/src/components/Verdict/DisputeTimeline.tsx b/web/src/components/Verdict/DisputeTimeline.tsx index 2daad4db0..05a24b52e 100644 --- a/web/src/components/Verdict/DisputeTimeline.tsx +++ b/web/src/components/Verdict/DisputeTimeline.tsx @@ -2,15 +2,16 @@ import React, { useMemo } from "react"; import { useParams } from "react-router-dom"; import styled, { useTheme } from "styled-components"; import { _TimelineItem1, CustomTimeline } from "@kleros/ui-components-library"; +import CalendarIcon from "assets/svgs/icons/calendar.svg"; +import ClosedCaseIcon from "assets/svgs/icons/check-circle-outline.svg"; +import AppealedCaseIcon from "assets/svgs/icons/close-circle.svg"; import { Periods } from "consts/periods"; import { ClassicRound } from "src/graphql/graphql"; -import { getVoteChoice } from "pages/Cases/CaseDetails/Voting/VotingHistory"; import { DisputeDetailsQuery, useDisputeDetailsQuery } from "queries/useDisputeDetailsQuery"; import { useDisputeTemplate } from "queries/useDisputeTemplate"; import { useVotingHistory } from "queries/useVotingHistory"; -import CalendarIcon from "assets/svgs/icons/calendar.svg"; -import ClosedCaseIcon from "assets/svgs/icons/check-circle-outline.svg"; -import AppealedCaseIcon from "assets/svgs/icons/close-circle.svg"; +import { getVoteChoice } from "pages/Cases/CaseDetails/Voting/VotingHistory"; +import { getLocalRounds } from "utils/getLocalRounds"; const Container = styled.div` display: flex; @@ -63,7 +64,7 @@ const useItems = (disputeDetails?: DisputeDetailsQuery, arbitrable?: `0x${string const { id } = useParams(); const { data: votingHistory } = useVotingHistory(id); const { data: disputeTemplate } = useDisputeTemplate(id, arbitrable); - const localRounds: ClassicRound[] = votingHistory?.dispute?.disputeKitDispute?.localRounds as ClassicRound[]; + const localRounds: ClassicRound[] = getLocalRounds(votingHistory?.dispute?.disputeKitDispute) as ClassicRound[]; const theme = useTheme(); diff --git a/web/src/hooks/queries/useClassicAppealQuery.ts b/web/src/hooks/queries/useClassicAppealQuery.ts index ebf833961..bcdce6ebb 100644 --- a/web/src/hooks/queries/useClassicAppealQuery.ts +++ b/web/src/hooks/queries/useClassicAppealQuery.ts @@ -34,7 +34,7 @@ const classicAppealQuery = graphql(` export const useClassicAppealQuery = (id?: string | number) => { const isEnabled = id !== undefined; - return useQuery({ + return useQuery({ queryKey: ["refetchOnBlock", `classicAppealQuery${id}`], enabled: isEnabled, queryFn: async () => await graphqlQueryFnHelper(classicAppealQuery, { disputeID: id?.toString() }), diff --git a/web/src/hooks/useClassicAppealContext.tsx b/web/src/hooks/useClassicAppealContext.tsx index 1a549fee4..2e1c22cf8 100644 --- a/web/src/hooks/useClassicAppealContext.tsx +++ b/web/src/hooks/useClassicAppealContext.tsx @@ -7,6 +7,7 @@ import { useAppealCost } from "queries/useAppealCost"; import { useDisputeKitClassicMultipliers } from "queries/useDisputeKitClassicMultipliers"; import { useClassicAppealQuery, ClassicAppealQuery } from "queries/useClassicAppealQuery"; import { useCountdown } from "hooks/useCountdown"; +import { getLocalRounds } from "utils/getLocalRounds"; const LoserSideCountdownContext = createContext(undefined); @@ -100,7 +101,7 @@ export const useOptionsContext = () => useContext(OptionsContext); const getCurrentLocalRound = (dispute?: ClassicAppealQuery["dispute"]) => { const period = dispute?.period; const currentLocalRoundIndex = dispute?.disputeKitDispute?.currentLocalRoundIndex; - return dispute?.disputeKitDispute?.localRounds[ + return getLocalRounds(dispute?.disputeKitDispute)[ ["appeal", "execution"].includes(period ?? "") ? currentLocalRoundIndex : currentLocalRoundIndex - 1 ]; }; diff --git a/web/src/pages/Cases/CaseDetails/Overview.tsx b/web/src/pages/Cases/CaseDetails/Overview.tsx index 470c328cf..e0a80d2bc 100644 --- a/web/src/pages/Cases/CaseDetails/Overview.tsx +++ b/web/src/pages/Cases/CaseDetails/Overview.tsx @@ -15,6 +15,7 @@ import { StyledSkeleton } from "components/StyledSkeleton"; import DisputeInfo from "components/DisputeCard/DisputeInfo"; import Verdict from "components/Verdict/index"; import { useVotingHistory } from "hooks/queries/useVotingHistory"; +import { getLocalRounds } from "utils/getLocalRounds"; const Container = styled.div` width: 100%; @@ -117,7 +118,7 @@ const Overview: React.FC = ({ arbitrable, courtID, currentPeriodIndex const { data: disputeDetails } = useDisputeDetailsQuery(id); const { data: courtPolicy } = useCourtPolicy(courtID); const { data: votingHistory } = useVotingHistory(id); - const localRounds = votingHistory?.dispute?.disputeKitDispute?.localRounds; + const localRounds = getLocalRounds(votingHistory?.dispute?.disputeKitDispute); const courtName = courtPolicy?.name; const court = disputeDetails?.dispute?.court; const rewards = court ? `≥ ${formatEther(court.feeForJuror)} ETH` : undefined; diff --git a/web/src/pages/Cases/CaseDetails/Voting/VotingHistory.tsx b/web/src/pages/Cases/CaseDetails/Voting/VotingHistory.tsx index f53602a23..9aed8c3c4 100644 --- a/web/src/pages/Cases/CaseDetails/Voting/VotingHistory.tsx +++ b/web/src/pages/Cases/CaseDetails/Voting/VotingHistory.tsx @@ -9,6 +9,7 @@ import { useVotingHistory } from "queries/useVotingHistory"; import { useDisputeTemplate } from "queries/useDisputeTemplate"; import { shortenAddress } from "utils/shortenAddress"; import { isUndefined } from "utils/index"; +import { getLocalRounds } from "utils/getLocalRounds"; const Container = styled.div``; @@ -87,7 +88,7 @@ const AccordionContent: React.FC<{ ); }; -export const getVoteChoice = (vote, answers) => { +export const getVoteChoice = (vote: number, answers: { title: string }[]) => { const selectedAnswer = answers?.[vote - 1]?.title; if (vote === 0) { return "Refuse to arbitrate"; @@ -104,7 +105,7 @@ const VotingHistory: React.FC<{ arbitrable?: `0x${string}`; isQuestion: boolean const [currentTab, setCurrentTab] = useState(0); const { data: disputeTemplate } = useDisputeTemplate(id, arbitrable); const rounds = votingHistory?.dispute?.rounds; - const localRounds = votingHistory?.dispute?.disputeKitDispute?.localRounds; + const localRounds = getLocalRounds(votingHistory?.dispute?.disputeKitDispute); const answers = disputeTemplate?.answers; return ( @@ -115,7 +116,7 @@ const VotingHistory: React.FC<{ arbitrable?: `0x${string}`; isQuestion: boolean {isQuestion && disputeTemplate.question ? ( {disputeTemplate.question} ) : ( - The dispute's template is not correct please vote refuse to arbitrate + {"The dispute's template is not correct please vote refuse to arbitrate"} )} ["disputeKitDispute"] +>["localRounds"]; + +type IClassicAppealQueryLocalRounds = NonNullable< + NonNullable["disputeKitDispute"] +>["localRounds"]; + +type ILocalRounds = IClassicAppealQueryLocalRounds | IVotingHistoryLocalRounds; + +interface IDisputeKitDisputes { + localRounds: ILocalRounds; +} + +export const getLocalRounds = (disputeKitDisputes: IDisputeKitDisputes | undefined | null) => { + return disputeKitDisputes?.reduce((acc: ILocalRounds, { localRounds }) => acc.concat(localRounds), []); +};