Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Feat/dispute dates and hashes link #1816

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