Skip to content

Commit 38030e1

Browse files
authored
Merge branch 'web/dk-support-improvement' into chore/token-gated-dispute-kit-subgraph
2 parents bc76907 + 4d0c513 commit 38030e1

File tree

24 files changed

+526
-67
lines changed

24 files changed

+526
-67
lines changed

contracts/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@
156156
"@chainlink/contracts": "^1.4.0",
157157
"@kleros/vea-contracts": "^0.6.0",
158158
"@openzeppelin/contracts": "^5.4.0",
159-
"@shutter-network/shutter-sdk": "0.0.1",
159+
"@shutter-network/shutter-sdk": "0.0.2",
160160
"isomorphic-fetch": "^3.0.0",
161161
"viem": "^2.24.1"
162162
}

subgraph/core/src/KlerosCore.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,10 @@ export function handleNewPeriod(event: NewPeriod): void {
166166
continue;
167167
}
168168

169-
if (vote.choice === null) continue;
169+
if (vote.choice === null) {
170+
juror.save();
171+
continue;
172+
}
170173

171174
// Check if the vote choice matches the final ruling
172175
if (vote.choice!.equals(dispute.currentRuling)) {

subgraph/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@kleros/kleros-v2-subgraph",
3-
"version": "0.17.0",
3+
"version": "0.17.1",
44
"drtVersion": "0.13.0",
55
"license": "MIT",
66
"scripts": {

web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
"@reown/appkit-adapter-wagmi": "^1.7.1",
9696
"@sentry/react": "^7.120.0",
9797
"@sentry/tracing": "^7.120.0",
98-
"@shutter-network/shutter-sdk": "0.0.1",
98+
"@shutter-network/shutter-sdk": "0.0.2",
9999
"@solana/wallet-adapter-react": "^0.15.36",
100100
"@solana/web3.js": "^1.98.0",
101101
"@tanstack/react-query": "^5.69.0",

web/src/consts/index.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,9 @@ export const RPC_ERROR = `RPC Error: Unable to fetch dispute data. Please avoid
4343

4444
export const spamEvidencesIds: string[] = (import.meta.env.REACT_APP_SPAM_EVIDENCES_IDS ?? "").split(",");
4545

46-
export const getDisputeKitName = (id: number): string | undefined => {
47-
const universityDisputeKits: Record<number, string> = { 1: "Classic Dispute Kit" };
48-
const neoDisputeKits: Record<number, string> = { 1: "Classic Dispute Kit" };
49-
const testnetDisputeKits: Record<number, string> = { 1: "Classic Dispute Kit" };
50-
const devnetDisputeKits: Record<number, string> = { 1: "Classic Dispute Kit", 2: "Shutter Dispute Kit" };
51-
52-
if (isKlerosUniversity()) return universityDisputeKits[id];
53-
if (isKlerosNeo()) return neoDisputeKits[id];
54-
if (isTestnetDeployment()) return testnetDisputeKits[id];
55-
return devnetDisputeKits[id];
56-
};
46+
export enum DisputeKits {
47+
Classic = "Classic Dispute Kit",
48+
Shutter = "Shutter Dispute Kit",
49+
Gated = "Gated Dispute Kit",
50+
GatedShutter = "Gated Shutter Dispute Kit",
51+
}

web/src/context/NewDisputeContext.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,22 @@ interface IDisputeData extends IDisputeTemplate {
5151
arbitrationCost?: string;
5252
aliasesArray?: AliasArray[];
5353
disputeKitId?: number;
54+
disputeKitData?: IDisputeKitData;
55+
}
56+
57+
export type IDisputeKitData = IGatedDisputeData | ISomeFutureDisputeData;
58+
59+
export interface IGatedDisputeData {
60+
type: "gated";
61+
isERC1155: boolean;
62+
tokenGate: string;
63+
tokenId: string;
64+
}
65+
66+
// Placeholder
67+
export interface ISomeFutureDisputeData {
68+
type: "future";
69+
contract: string;
5470
}
5571

5672
interface INewDisputeContext {

web/src/hooks/queries/useDisputeDetailsQuery.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const disputeDetailsQuery = graphql(`
3030
nbVotes
3131
disputeKit {
3232
id
33+
address
3334
}
3435
}
3536
currentRoundIndex

web/src/hooks/queries/useRoundDetailsQuery.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ const roundDetailsQuery = graphql(`
1717
disputeKit {
1818
id
1919
}
20+
dispute {
21+
disputeKitDispute {
22+
... on ClassicDispute {
23+
extraData
24+
}
25+
}
26+
}
2027
}
2128
}
2229
`);

web/src/hooks/queries/useSupportedDisputeKits.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { useQuery } from "@tanstack/react-query";
2+
23
import { useGraphqlBatcher } from "context/GraphqlBatcher";
4+
35
import { graphql } from "src/graphql";
46
import { SupportedDisputeKitsQuery } from "src/graphql/graphql";
57

@@ -8,6 +10,7 @@ const supportedDisputeKitsQuery = graphql(`
810
court(id: $id) {
911
supportedDisputeKits {
1012
id
13+
address
1114
}
1215
}
1316
}
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
import { useEffect, useState } from "react";
2+
3+
import { useChainId } from "wagmi";
4+
5+
import { DisputeKits } from "consts/index";
6+
7+
interface UseDisputeKitAddressesParams {
8+
disputeKitAddress?: string;
9+
}
10+
11+
interface UseDisputeKitAddressesAllReturn {
12+
availableDisputeKits: Record<string, DisputeKits>;
13+
isLoading: boolean;
14+
error: string | null;
15+
}
16+
17+
const DISPUTE_KIT_CONFIG = {
18+
[DisputeKits.Classic]: "disputeKitClassicAddress",
19+
[DisputeKits.Shutter]: "disputeKitShutterAddress",
20+
[DisputeKits.Gated]: "disputeKitGatedAddress",
21+
[DisputeKits.GatedShutter]: "disputeKitGatedShutterAddress",
22+
} as const;
23+
24+
/**
25+
* Hook to get dispute kit name based on address
26+
* @param disputeKitAddress - Optional specific dispute kit address to identify
27+
* @returns The human-readable name of the dispute kit and loading state
28+
*/
29+
export const useDisputeKitAddresses = ({ disputeKitAddress }: UseDisputeKitAddressesParams = {}) => {
30+
const chainId = useChainId();
31+
const [disputeKitName, setDisputeKitName] = useState<DisputeKits | undefined>(undefined);
32+
const [isLoading, setIsLoading] = useState(true);
33+
const [error, setError] = useState<string | null>(null);
34+
35+
useEffect(() => {
36+
const loadDisputeKitName = async () => {
37+
try {
38+
setIsLoading(true);
39+
setError(null);
40+
41+
// If no dispute kit address is provided, we can't determine the type
42+
if (!disputeKitAddress) {
43+
setDisputeKitName(undefined);
44+
setIsLoading(false);
45+
return;
46+
}
47+
48+
// If no chainId, we can't look up from generated contracts
49+
if (!chainId) {
50+
setDisputeKitName(undefined);
51+
setIsLoading(false);
52+
return;
53+
}
54+
55+
// Dynamic import to handle cases where generated contracts might not be available
56+
try {
57+
const generatedContracts = await import("hooks/contracts/generated");
58+
59+
// Check each dispute kit to see if the address matches
60+
for (const [humanName, contractKey] of Object.entries(DISPUTE_KIT_CONFIG)) {
61+
const addressMapping = generatedContracts[contractKey as keyof typeof generatedContracts];
62+
63+
if (addressMapping && typeof addressMapping === "object" && chainId in addressMapping) {
64+
const contractAddress = addressMapping[chainId as keyof typeof addressMapping] as string;
65+
if (
66+
contractAddress &&
67+
typeof contractAddress === "string" &&
68+
contractAddress.toLowerCase() === disputeKitAddress.toLowerCase()
69+
) {
70+
setDisputeKitName(humanName as DisputeKits);
71+
return;
72+
}
73+
}
74+
}
75+
76+
// If no address matches, return undefined
77+
setDisputeKitName(undefined);
78+
} catch {
79+
// If we can't import generated contracts, return undefined
80+
setDisputeKitName(undefined);
81+
}
82+
} catch (err) {
83+
console.error("Failed to determine dispute kit name:", err);
84+
setError("Failed to determine dispute kit type");
85+
setDisputeKitName(undefined);
86+
} finally {
87+
setIsLoading(false);
88+
}
89+
};
90+
91+
loadDisputeKitName();
92+
}, [chainId, disputeKitAddress]);
93+
94+
return {
95+
disputeKitName,
96+
isLoading,
97+
error,
98+
};
99+
};
100+
101+
/**
102+
* Hook to get all dispute kit addresses for the current chain
103+
* @returns All dispute kit addresses, loading state, and error state
104+
*/
105+
export const useDisputeKitAddressesAll = (): UseDisputeKitAddressesAllReturn => {
106+
const chainId = useChainId();
107+
const [availableDisputeKits, setAvailableDisputeKits] = useState<Record<string, DisputeKits>>({});
108+
const [isLoading, setIsLoading] = useState(true);
109+
const [error, setError] = useState<string | null>(null);
110+
111+
useEffect(() => {
112+
const loadAllDisputeKitAddresses = async () => {
113+
try {
114+
setIsLoading(true);
115+
setError(null);
116+
117+
// If no chainId, we can't look up from generated contracts
118+
if (!chainId) {
119+
setAvailableDisputeKits({});
120+
setIsLoading(false);
121+
return;
122+
}
123+
124+
// Dynamic import to handle cases where generated contracts might not be available
125+
try {
126+
const generatedContracts = await import("hooks/contracts/generated");
127+
const newAvailableDisputeKits: Record<string, DisputeKits> = {};
128+
129+
// Iterate through all dispute kits and get their addresses
130+
for (const [humanName, contractKey] of Object.entries(DISPUTE_KIT_CONFIG)) {
131+
const addressMapping = generatedContracts[contractKey as keyof typeof generatedContracts];
132+
133+
if (addressMapping && typeof addressMapping === "object" && chainId in addressMapping) {
134+
const contractAddress = addressMapping[chainId as keyof typeof addressMapping] as string;
135+
if (contractAddress && typeof contractAddress === "string") {
136+
newAvailableDisputeKits[contractAddress.toLowerCase()] = humanName as DisputeKits;
137+
}
138+
}
139+
}
140+
141+
setAvailableDisputeKits(newAvailableDisputeKits);
142+
} catch {
143+
// If we can't import generated contracts, return empty object
144+
setAvailableDisputeKits({});
145+
}
146+
} catch (err) {
147+
console.error("Failed to load dispute kit addresses:", err);
148+
setError("Failed to load dispute kit addresses");
149+
setAvailableDisputeKits({});
150+
} finally {
151+
setIsLoading(false);
152+
}
153+
};
154+
155+
loadAllDisputeKitAddresses();
156+
}, [chainId]);
157+
158+
return {
159+
availableDisputeKits,
160+
isLoading,
161+
error,
162+
};
163+
};

0 commit comments

Comments
 (0)