Skip to content

Feat/dispute dates and hashes link #1816

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 9 commits into from
Jan 7, 2025
20 changes: 10 additions & 10 deletions subgraph/core-neo/subgraph.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ dataSources:
name: KlerosCore
network: arbitrum-one
source:
address: "0xCd415C03dfa85B02646C7e2977F22a480c4354F1"
address: "0x991d2df165670b9cac3B022f4B68D65b664222ea"
abi: KlerosCore
startBlock: 190274596
startBlock: 272063254
mapping:
kind: ethereum/events
apiVersion: 0.0.7
Expand Down Expand Up @@ -64,9 +64,9 @@ dataSources:
name: PolicyRegistry
network: arbitrum-one
source:
address: "0x26c1980120F1C82cF611D666CE81D2b54d018547"
address: "0x553dcbF6aB3aE06a1064b5200Df1B5A9fB403d3c"
abi: PolicyRegistry
startBlock: 190274403
startBlock: 272063037
mapping:
kind: ethereum/events
apiVersion: 0.0.7
Expand All @@ -84,9 +84,9 @@ dataSources:
name: DisputeKitClassic
network: arbitrum-one
source:
address: "0xb7c292cD9Fd3d20De84a71AE1caF054eEB6374A9"
address: "0x70B464be85A547144C72485eBa2577E5D3A45421"
abi: DisputeKitClassic
startBlock: 190274518
startBlock: 272063168
mapping:
kind: ethereum/events
apiVersion: 0.0.7
Expand Down Expand Up @@ -119,9 +119,9 @@ dataSources:
name: EvidenceModule
network: arbitrum-one
source:
address: "0xe62B776498F48061ef9425fCEf30F3d1370DB005"
address: "0x48e052B4A6dC4F30e90930F1CeaAFd83b3981EB3"
abi: EvidenceModule
startBlock: 190274441
startBlock: 272063086
mapping:
kind: ethereum/events
apiVersion: 0.0.7
Expand All @@ -140,9 +140,9 @@ dataSources:
name: SortitionModule
network: arbitrum-one
source:
address: "0x614498118850184c62f82d08261109334bFB050f"
address: "0x21A9402aDb818744B296e1d1BE58C804118DC03D"
abi: SortitionModule
startBlock: 190274557
startBlock: 272063201
mapping:
kind: ethereum/events
apiVersion: 0.0.7
Expand Down
5 changes: 5 additions & 0 deletions subgraph/core/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ type Dispute @entity {
disputeID: BigInt!
court: Court!
createdAt: BigInt
transactionHash: String!
arbitrated: Arbitrable!
period: Period!
ruled: Boolean!
Expand All @@ -180,6 +181,8 @@ type Dispute @entity {
arbitrableChainId:BigInt
externalDisputeId:BigInt
templateId:BigInt
rulingTimestamp:BigInt
rulingTransactionHash:String
}

type PeriodIndexCounter @entity {
Expand Down Expand Up @@ -303,6 +306,8 @@ type ClassicJustification @entity {
choice: BigInt!
votes: [ClassicVote!]! @derivedFrom(field: "justification")
reference: String!
transactionHash: String!
timestamp: BigInt!
}

type ClassicEvidenceGroup implements EvidenceGroup @entity {
Expand Down
2 changes: 2 additions & 0 deletions subgraph/core/src/DisputeKitClassic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ export function handleVoteCast(event: VoteCast): void {
justification.localRound = currentLocalRoundID;
justification.choice = choice;
justification.reference = event.params._justification;
justification.transactionHash = event.transaction.hash.toHexString();
justification.timestamp = event.block.timestamp;
justification.save();
const currentRulingInfo = updateCountsAndGetCurrentRuling(
currentLocalRoundID,
Expand Down
2 changes: 2 additions & 0 deletions subgraph/core/src/KlerosCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ export function handleRuling(event: Ruling): void {
const dispute = Dispute.load(disputeID.toString());
if (!dispute) return;
dispute.ruled = true;
dispute.rulingTransactionHash = event.transaction.hash.toHexString();
dispute.rulingTimestamp = event.block.timestamp;
dispute.save();
const court = Court.load(dispute.court);
if (!court) return;
Expand Down
1 change: 1 addition & 0 deletions subgraph/core/src/entities/Dispute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function createDisputeFromEvent(event: DisputeCreation): void {
dispute.lastPeriodChange = event.block.timestamp;
dispute.lastPeriodChangeBlockNumber = event.block.number;
dispute.periodNotificationIndex = getAndIncrementPeriodCounter(dispute.period);
dispute.transactionHash = event.transaction.hash.toHexString();
const court = Court.load(courtID);
if (!court) return;
dispute.periodDeadline = event.block.timestamp.plus(court.timesPerPeriod[0]);
Expand Down
2 changes: 1 addition & 1 deletion subgraph/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@kleros/kleros-v2-subgraph",
"version": "0.9.1",
"version": "0.10.1",
"license": "MIT",
"scripts": {
"update:core:arbitrum-sepolia-devnet": "./scripts/update.sh arbitrumSepoliaDevnet arbitrum-sepolia core/subgraph.yaml",
Expand Down
3 changes: 2 additions & 1 deletion web/src/components/EvidenceCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { getIpfsUrl } from "utils/getIpfsUrl";
import { shortenAddress } from "utils/shortenAddress";

import { type Evidence } from "src/graphql/graphql";
import { getTxnExplorerLink } from "src/utils";

import { hoverShortTransitionTiming } from "styles/commonStyles";
import { landscapeStyle } from "styles/landscapeStyle";
Expand Down Expand Up @@ -225,7 +226,7 @@ const EvidenceCard: React.FC<IEvidenceCard> = ({
}, [sender]);

const transactionExplorerLink = useMemo(() => {
return `${getChain(DEFAULT_CHAIN)?.blockExplorers?.default.url}/tx/${transactionHash}`;
return getTxnExplorerLink(transactionHash ?? "");
}, [transactionHash]);

return (
Expand Down
4 changes: 2 additions & 2 deletions web/src/components/TxnHash.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import styled from "styled-components";

import NewTabIcon from "svgs/icons/new-tab.svg";

import { DEFAULT_CHAIN, getChain } from "consts/chains";
import { getTxnExplorerLink } from "src/utils";

import { ExternalLink } from "./ExternalLink";

Expand All @@ -23,7 +23,7 @@ interface ITxnHash {
}
const TxnHash: React.FC<ITxnHash> = ({ hash, variant }) => {
const transactionExplorerLink = useMemo(() => {
return `${getChain(DEFAULT_CHAIN)?.blockExplorers?.default.url}/tx/${hash}`;
return getTxnExplorerLink(hash);
}, [hash]);

return (
Expand Down
51 changes: 45 additions & 6 deletions web/src/components/Verdict/DisputeTimeline.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React, { useMemo } from "react";
import styled, { useTheme } from "styled-components";

import { responsiveSize } from "styles/responsiveSize";

import Skeleton from "react-loading-skeleton";
import { useParams } from "react-router-dom";

import { _TimelineItem1, CustomTimeline } from "@kleros/ui-components-library";

import CalendarIcon from "svgs/icons/calendar.svg";
import ClosedCaseIcon from "svgs/icons/check-circle-outline.svg";
import NewTabIcon from "svgs/icons/new-tab.svg";

import { Periods } from "consts/periods";
import { usePopulatedDisputeData } from "hooks/queries/usePopulatedDisputeData";
Expand All @@ -19,9 +19,14 @@ import { DisputeDetailsQuery, useDisputeDetailsQuery } from "queries/useDisputeD
import { useVotingHistory } from "queries/useVotingHistory";

import { ClassicRound } from "src/graphql/graphql";
import { getTxnExplorerLink } from "src/utils";

import { responsiveSize } from "styles/responsiveSize";

import { StyledClosedCircle } from "components/StyledIcons/ClosedCircleIcon";

import { ExternalLink } from "../ExternalLink";

const Container = styled.div`
display: flex;
position: relative;
Expand Down Expand Up @@ -50,6 +55,18 @@ const StyledCalendarIcon = styled(CalendarIcon)`
height: 14px;
`;

const StyledNewTabIcon = styled(NewTabIcon)`
margin-bottom: 2px;
path {
fill: ${({ theme }) => theme.primaryBlue};
}
:hover {
path {
fill: ${({ theme }) => theme.secondaryBlue};
}
}
`;

const formatDate = (date: string) => {
const options: Intl.DateTimeFormatOptions = { year: "numeric", month: "long", day: "numeric" };
const startingDate = new Date(parseInt(date) * 1000);
Expand All @@ -67,6 +84,9 @@ const useItems = (disputeDetails?: DisputeDetailsQuery, arbitrable?: `0x${string
const localRounds: ClassicRound[] = getLocalRounds(votingHistory?.dispute?.disputeKitDispute) as ClassicRound[];
const rounds = votingHistory?.dispute?.rounds;
const theme = useTheme();
const txnExplorerLink = useMemo(() => {
return getTxnExplorerLink(votingHistory?.dispute?.transactionHash ?? "");
}, [votingHistory]);

return useMemo<TimelineItems | undefined>(() => {
const dispute = disputeDetails?.dispute;
Expand Down Expand Up @@ -119,7 +139,11 @@ const useItems = (disputeDetails?: DisputeDetailsQuery, arbitrable?: `0x${string
[
{
title: "Dispute created",
party: "",
party: (
<ExternalLink to={txnExplorerLink} rel="noopener noreferrer" target="_blank">
<StyledNewTabIcon />
</ExternalLink>
),
subtitle: formatDate(votingHistory?.dispute?.createdAt),
rightSided: true,
variant: theme.secondaryPurple,
Expand All @@ -128,7 +152,7 @@ const useItems = (disputeDetails?: DisputeDetailsQuery, arbitrable?: `0x${string
);
}
return;
}, [disputeDetails, disputeData, localRounds, theme]);
}, [disputeDetails, disputeData, localRounds, theme, rounds, votingHistory, txnExplorerLink]);
};

interface IDisputeTimeline {
Expand All @@ -138,15 +162,30 @@ interface IDisputeTimeline {
const DisputeTimeline: React.FC<IDisputeTimeline> = ({ arbitrable }) => {
const { id } = useParams();
const { data: disputeDetails } = useDisputeDetailsQuery(id);
const { data: votingHistory } = useVotingHistory(id);
const items = useItems(disputeDetails, arbitrable);

const transactionExplorerLink = useMemo(() => {
return getTxnExplorerLink(disputeDetails?.dispute?.rulingTransactionHash ?? "");
}, [disputeDetails]);

return (
<Container>
{items && <StyledTimeline {...{ items }} />}
{disputeDetails?.dispute?.ruled && items && (
{disputeDetails?.dispute?.ruled && (
<EnforcementContainer>
<StyledCalendarIcon />
<small>Enforcement: {items.at(-1)?.subtitle}</small>
<small>
Enforcement:{" "}
{disputeDetails.dispute.rulingTimestamp ? (
<ExternalLink to={transactionExplorerLink} rel="noopener noreferrer" target="_blank">
{formatDate(disputeDetails.dispute.rulingTimestamp)}
</ExternalLink>
) : (
<Skeleton height={16} width={56} />
)}{" "}
/ {votingHistory?.dispute?.rounds.at(-1)?.court.name}
</small>
</EnforcementContainer>
)}
</Container>
Expand Down
2 changes: 2 additions & 0 deletions web/src/hooks/queries/useDisputeDetailsQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ const disputeDetailsQuery = graphql(`
arbitrableChainId
externalDisputeId
templateId
rulingTimestamp
rulingTransactionHash
}
}
`);
Expand Down
3 changes: 3 additions & 0 deletions web/src/hooks/queries/useVotingHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const votingHistoryQuery = graphql(`
dispute(id: $disputeID) {
id
createdAt
transactionHash
ruled
rounds {
nbVotes
Expand All @@ -29,6 +30,8 @@ const votingHistoryQuery = graphql(`
... on ClassicVote {
commited
justification {
transactionHash
timestamp
choice
reference
}
Expand Down
Loading
Loading