Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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=
1 change: 1 addition & 0 deletions web-devtools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,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,16 @@
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 LabeledInput from "components/LabeledInput";

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

const ChangeDeveloper: React.FC = () => {
const { arbitrable, currentDeveloper, refetchData, isRulerOfArbitrable } = useRulerContext();
const [newDeveloper, setNewDeveloper] = useState<Address>("" as `0x${string}`);
const [isChanging, setIsChanging] = useState(false);
const publicClient = usePublicClient();

const isValid = useMemo(
() => !isUndefined(newDeveloper) && (newDeveloper === ("" as `0x${string}`) || isAddress(newDeveloper)),
[newDeveloper]
);

const {
data: changeRulerConfig,
isLoading,
isError,
} = useSimulateKlerosCoreRulerChangeRuler({
query: {
enabled: !isUndefined(arbitrable) && !isUndefined(newDeveloper) && isRulerOfArbitrable,
},
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 as Address)}
message={isValid ? "" : "Invalid Address"}
variant={isValid ? "" : "error"}
/>
</InputContainer>
<Button text="Update" />
<Button
text="Update"
onClick={handleClick}
isLoading={isLoading || isChanging}
disabled={isError || isLoading || isChanging || isUndefined(arbitrable) || !isRulerOfArbitrable}
/>
</Container>
);
};
Expand Down
76 changes: 71 additions & 5 deletions web-devtools/src/app/(main)/ruler/ManualRuling.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
import React, { useState } from "react";
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 LabeledInput from "components/LabeledInput";

import Header from "./Header";
Expand All @@ -22,10 +35,58 @@ 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?.overidden ?? 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;
setIsSending(true);
if (arbitrableSettings?.rulingMode !== RULING_MODE.Manual) {
if (!manualModeConfig) return;
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) {
wrapWithToast(async () => await executeRuling(executeConfig.request), publicClient).finally(() =>
setIsSending(false)
);
}
}, [publicClient, executeConfig, manualModeConfig, arbitrableSettings, changeToManualMode, executeRuling]);

return (
<Container>
Expand All @@ -48,7 +109,12 @@ const ManualRuling: React.FC = () => {
/>
</SelectContainer>

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