Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion web-devtools/.env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
export NEXT_PUBLIC_ALCHEMY_API_KEY=
export NEXT_PUBLIC_DEPLOYMENT=devnet
export NEXT_PUBLIC_CORE_SUBGRAPH=https://api.studio.thegraph.com/query/61738/kleros-v2-core-devnet/version/latest
export NEXT_PUBLIC_DRT_ARBSEPOLIA_SUBGRAPH=https://api.studio.thegraph.com/query/61738/kleros-v2-drt-arbisep-devnet/version/latest
export NEXT_PUBLIC_DRT_ARBSEPOLIA_SUBGRAPH=https://api.studio.thegraph.com/query/61738/kleros-v2-drt-arbisep-devnet/version/latest
export NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=
9 changes: 9 additions & 0 deletions web-devtools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,16 @@
"@types/node": "^20",
"@types/react": "18.2.0",
"@types/react-dom": "^18.2.18",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"@typescript-eslint/utils": "^5.62.0",
"@wagmi/cli": "^2.0.3",
"eslint": "^8.56.0",
"eslint-config-next": "^14.2.5",
"eslint-config-prettier": "^8.10.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"ts-node": "^10.9.2",
"typescript": "^5.5.3"
},
Expand All @@ -43,6 +51,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-markdown": "^8.0.7",
"react-toastify": "^10.0.5",
"typewriter-effect": "^2.21.0",
"vanilla-jsoneditor": "^0.21.4",
"viem": "^2.1.0",
Expand Down
23 changes: 18 additions & 5 deletions web-devtools/src/app/(main)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,35 @@
import React from "react";
import styled from "styled-components";

import "react-toastify/dist/ReactToastify.css";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ToastContainer } from "react-toastify";

import GraphqlBatcherProvider from "context/GraphqlBatcher";
import Web3Provider from "context/Web3Provider";

const Main = styled.main`
min-height: calc(100vh - 130px);
`;
const queryClient = new QueryClient();

const StyledToastContainer = styled(ToastContainer)`
padding: 16px;
padding-top: 70px;
`;

const Layout = ({ children }: Readonly<{ children: React.ReactNode }>) => {
return (
<QueryClientProvider client={queryClient}>
<GraphqlBatcherProvider>
<Main>{children}</Main>
</GraphqlBatcherProvider>
</QueryClientProvider>
<Web3Provider>
<QueryClientProvider client={queryClient}>
<GraphqlBatcherProvider>
<Main>
<StyledToastContainer />
{children}
</Main>
</GraphqlBatcherProvider>
</QueryClientProvider>
</Web3Provider>
);
};

Expand Down
57 changes: 53 additions & 4 deletions web-devtools/src/app/(main)/ruler/ChangeDeveloper.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import React from "react";
import React, { useCallback, useMemo, useState } from "react";
import styled from "styled-components";

import { Address, isAddress } from "viem";
import { usePublicClient } from "wagmi";

import { Button } from "@kleros/ui-components-library";

import { useRulerContext } from "context/RulerContext";
import { useSimulateKlerosCoreRulerChangeRuler, useWriteKlerosCoreRulerChangeRuler } from "hooks/contracts/generated";
import { isUndefined } from "utils/isUndefined";
import { wrapWithToast } from "utils/wrapWithToast";

import { EnsureChain } from "components/EnsureChain";
import LabeledInput from "components/LabeledInput";

import Header from "./Header";
Expand All @@ -25,14 +34,54 @@ const StyledLabel = styled.label`
`;

const ChangeDeveloper: React.FC = () => {
const { arbitrable, currentDeveloper, refetchData } = useRulerContext();
const [newDeveloper, setNewDeveloper] = useState("");
const [isChanging, setIsChanging] = useState(false);
const publicClient = usePublicClient();

const isValid = useMemo(() => newDeveloper === "" || isAddress(newDeveloper), [newDeveloper]);

const {
data: changeRulerConfig,
isLoading,
isError,
} = useSimulateKlerosCoreRulerChangeRuler({
query: {
enabled: !isUndefined(arbitrable) && !isUndefined(newDeveloper) && isAddress(newDeveloper),
},
args: [(arbitrable ?? "") as Address, newDeveloper as Address],
});

const { writeContractAsync: changeRuler } = useWriteKlerosCoreRulerChangeRuler();

const handleClick = useCallback(() => {
if (!publicClient || !changeRulerConfig) return;
setIsChanging(true);
wrapWithToast(async () => changeRuler(changeRulerConfig.request), publicClient)
.then(() => refetchData())
.finally(() => setIsChanging(false));
}, [publicClient, changeRulerConfig, changeRuler, refetchData]);

return (
<Container>
<Header text="Developer" />
<InputContainer>
<StyledLabel>Current Developer : 0xbe8d95497E53aB41d5A45CC8def90d0e59b49f99</StyledLabel>
<LabeledInput label="New Developer" />
<StyledLabel>Current Developer : {currentDeveloper ?? "None"}</StyledLabel>
<LabeledInput
label="New Developer"
onChange={(e) => setNewDeveloper(e.target.value)}
message={isValid ? "" : "Invalid Address"}
variant={isValid ? "" : "error"}
/>
</InputContainer>
<Button text="Update" />
<EnsureChain>
<Button
text="Update"
onClick={handleClick}
isLoading={isLoading || isChanging}
disabled={!changeRulerConfig || isError || isLoading || isChanging || isUndefined(arbitrable) || !isValid}
/>
</EnsureChain>
</Container>
);
};
Expand Down
84 changes: 78 additions & 6 deletions web-devtools/src/app/(main)/ruler/ManualRuling.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
import React, { useState } from "react";
"use client";
import React, { useCallback, useMemo, useState } from "react";
import styled from "styled-components";

import { RULING_MODE } from "consts";
import { usePublicClient } from "wagmi";

import { Button } from "@kleros/ui-components-library";

import { useRulerContext } from "context/RulerContext";
import {
useSimulateKlerosCoreRulerChangeRulingModeToManual,
useSimulateKlerosCoreRulerExecuteRuling,
useWriteKlerosCoreRulerChangeRulingModeToManual,
useWriteKlerosCoreRulerExecuteRuling,
} from "hooks/contracts/generated";
import { isUndefined } from "utils/isUndefined";
import { wrapWithToast } from "utils/wrapWithToast";

import { EnsureChain } from "components/EnsureChain";
import LabeledInput from "components/LabeledInput";

import Header from "./Header";
Expand All @@ -22,10 +37,61 @@ const SelectContainer = styled.div`
`;

const ManualRuling: React.FC = () => {
const [tie, setTie] = useState<boolean>(false);
const [overriden, setOverriden] = useState<boolean>(false);
const [isSending, setIsSending] = useState<boolean>(false);
const { arbitrable, arbitrableSettings } = useRulerContext();
const [tie, setTie] = useState(arbitrableSettings?.tied ?? false);
const [overriden, setOverriden] = useState(arbitrableSettings?.overridden ?? false);
const [ruling, setRuling] = useState(arbitrableSettings?.ruling);
const [disputeId, setDisputeId] = useState<number>();
const [ruling, setRuling] = useState<number>();

const publicClient = usePublicClient();

const { data: manualModeConfig } = useSimulateKlerosCoreRulerChangeRulingModeToManual({
query: {
enabled: arbitrableSettings?.rulingMode !== RULING_MODE.Manual && !isUndefined(arbitrable),
},
args: [arbitrable as `0x${string}`],
});
const { writeContractAsync: changeToManualMode } = useWriteKlerosCoreRulerChangeRulingModeToManual();

const isDisabled = useMemo(() => {
return isUndefined(disputeId) || isUndefined(ruling) || isUndefined(arbitrable);
}, [disputeId, ruling, arbitrable]);

const {
data: executeConfig,
isLoading: isLoadingExecuteConfig,
isError,
} = useSimulateKlerosCoreRulerExecuteRuling({
query: {
enabled: arbitrableSettings?.rulingMode === RULING_MODE.Manual && !isUndefined(arbitrable) && !isDisabled,
},
args: [BigInt(disputeId ?? 0), BigInt(ruling ?? 0), tie, overriden],
});

const { writeContractAsync: executeRuling } = useWriteKlerosCoreRulerExecuteRuling();

const handleRuling = useCallback(async () => {
if (!publicClient) return;
if (arbitrableSettings?.rulingMode !== RULING_MODE.Manual) {
if (!manualModeConfig) return;
setIsSending(true);

wrapWithToast(async () => await changeToManualMode(manualModeConfig.request), publicClient)
.then(async (res) => {
if (res.status && executeConfig) {
wrapWithToast(async () => await executeRuling(executeConfig.request), publicClient);
}
})
.finally(() => setIsSending(false));
} else if (executeConfig) {
setIsSending(true);

wrapWithToast(async () => await executeRuling(executeConfig.request), publicClient).finally(() =>
setIsSending(false)
);
}
}, [publicClient, executeConfig, manualModeConfig, arbitrableSettings, changeToManualMode, executeRuling]);

return (
<Container>
Expand All @@ -47,8 +113,14 @@ const ManualRuling: React.FC = () => {
onChange={() => setOverriden((prev) => !prev)}
/>
</SelectContainer>

<Button text="Rule" />
<EnsureChain>
<Button
text="Rule"
onClick={handleRuling}
isLoading={isLoadingExecuteConfig || isSending}
disabled={isDisabled || isError || isSending || isLoadingExecuteConfig}
/>
</EnsureChain>
</Container>
);
};
Expand Down
Loading