From 19e277d7c95a19adee716933abcb0819bf144291 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Fri, 18 Apr 2025 15:23:25 +0100 Subject: [PATCH 1/3] fix(web): contract arbitrators in wagmi hook generation --- contracts/package.json | 2 +- web/package.json | 1 + web/src/consts/arbitration.ts | 11 ---- .../useArbitrationCostFromKlerosCore.ts | 22 -------- .../TransactionDetails/index.tsx | 4 +- web/wagmi.config.ts | 54 +++++++++++++++++-- yarn.lock | 11 ++-- 7 files changed, 61 insertions(+), 44 deletions(-) delete mode 100644 web/src/consts/arbitration.ts delete mode 100644 web/src/hooks/queries/useArbitrationCostFromKlerosCore.ts diff --git a/contracts/package.json b/contracts/package.json index d3ab0dda..14d9ab6b 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -83,7 +83,7 @@ "typescript": "^5.7.3" }, "dependencies": { - "@kleros/kleros-v2-contracts": "^0.9.2", + "@kleros/kleros-v2-contracts": "^0.9.3", "@openzeppelin/contracts": "^5.3.0" } } diff --git a/web/package.json b/web/package.json index fa6a007d..5bfd06ba 100644 --- a/web/package.json +++ b/web/package.json @@ -45,6 +45,7 @@ "devDependencies": { "@graphql-codegen/cli": "^4.0.1", "@graphql-codegen/client-preset": "^4.6.2", + "@kleros/kleros-v2-contracts": "^0.9.3", "@types/react": "^18.2.59", "@types/react-dom": "^18.2.18", "@types/react-modal": "^3.16.3", diff --git a/web/src/consts/arbitration.ts b/web/src/consts/arbitration.ts deleted file mode 100644 index a31937af..00000000 --- a/web/src/consts/arbitration.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { DEFAULT_CHAIN } from "./chains"; - -import arbitrumSepoliaDevnet from "@kleros/kleros-v2-contracts/deployments/arbitrumSepoliaDevnet"; -import arbitrum from "@kleros/kleros-v2-contracts/deployments/arbitrum"; - -const deploymentsByChainId: Record = { - 421614: arbitrumSepoliaDevnet, - 42161: arbitrum, -}; - -export const KLEROS_CORE_ADDRESS = deploymentsByChainId[DEFAULT_CHAIN].contracts.KlerosCore.address; diff --git a/web/src/hooks/queries/useArbitrationCostFromKlerosCore.ts b/web/src/hooks/queries/useArbitrationCostFromKlerosCore.ts deleted file mode 100644 index 37cbc850..00000000 --- a/web/src/hooks/queries/useArbitrationCostFromKlerosCore.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { useReadContract } from "wagmi"; -import { parseAbi } from "viem"; -import { KLEROS_CORE_ADDRESS } from "consts/arbitration"; - -const KLEROS_CORE_ABI = parseAbi([ - "function arbitrationCost(bytes _extraData) view returns (uint256 cost)", -]); - -export const useArbitrationCost = (arbitratorExtraData: string) => { - const { data, isError, isLoading } = useReadContract({ - address: KLEROS_CORE_ADDRESS, - abi: KLEROS_CORE_ABI, - functionName: "arbitrationCost", - args: [arbitratorExtraData], - }); - - return { - arbitrationCost: data !== undefined ? data : null, - isLoading, - isError, - }; -}; \ No newline at end of file diff --git a/web/src/pages/MyTransactions/TransactionDetails/index.tsx b/web/src/pages/MyTransactions/TransactionDetails/index.tsx index 75328b74..6e6df50a 100644 --- a/web/src/pages/MyTransactions/TransactionDetails/index.tsx +++ b/web/src/pages/MyTransactions/TransactionDetails/index.tsx @@ -10,7 +10,7 @@ import WasItFulfilled from "./WasItFulfilled"; import InfoCards from "./InfoCards"; import { useEscrowParametersQuery } from "queries/useEscrowParametersQuery"; import { useTransactionDetailsQuery } from "queries/useTransactionsQuery"; -import { useArbitrationCost } from "queries/useArbitrationCostFromKlerosCore"; +import { useReadKlerosCoreArbitrationCost } from "hooks/contracts/generated"; import { useNativeTokenSymbol } from "hooks/useNativeTokenSymbol"; import useFetchIpfsJson from "hooks/useFetchIpfsJson"; import { useTokenMetadata } from "hooks/useTokenMetadata"; @@ -32,7 +32,7 @@ const TransactionDetails: React.FC = () => { const { id } = useParams(); const { data: transactionDetails } = useTransactionDetailsQuery(id); const { data: escrowParameters } = useEscrowParametersQuery(); - const { arbitrationCost } = useArbitrationCost(escrowParameters?.escrowParameters?.arbitratorExtraData); + const arbitrationCost = useReadKlerosCoreArbitrationCost(escrowParameters?.escrowParameters?.arbitratorExtraData); const nativeTokenSymbol = useNativeTokenSymbol(); const { tokenMetadata } = useTokenMetadata(transactionDetails?.escrow?.token); const erc20TokenSymbol = tokenMetadata?.symbol; diff --git a/web/wagmi.config.ts b/web/wagmi.config.ts index d70a3c40..b8dcba49 100644 --- a/web/wagmi.config.ts +++ b/web/wagmi.config.ts @@ -4,17 +4,57 @@ import { readdir, readFile } from "fs/promises"; import { parse, join } from "path"; import { Chain } from "wagmi/chains"; import dotenv from "dotenv"; +import { + arbitrumSepoliaDevnet as arbitratorDevnet, + arbitrumSepolia as arbitratorTestnet, + arbitrum as arbitratorMainnet, +} from "@kleros/kleros-v2-contracts/cjs/deployments"; dotenv.config(); -const readArtifacts = async (viemChainName: string, hardhatChainName?: string) => { +type ArbitratorContracts = { + default: { + contracts: { + KlerosCore: { + address: `0x${string}`; + abi: any[]; + }; + }; + }; +}; + +const addArbitratorContract = ({ + results, + chain, + name, + contract, +}: { + results: ContractConfig[]; + chain: Chain; + name: string; + contract: { address: `0x${string}`; abi: any[] }; +}) => { + results.push({ + name, + address: { + [chain.id]: contract.address as `0x{string}`, + }, + abi: contract.abi, + }); +}; + +const readArtifacts = async ( + viemChainName: string, + hardhatChainName: string, + arbitratorContracts: ArbitratorContracts +) => { const chains = await import("wagmi/chains"); const chain = chains[viemChainName] as Chain; if (!chain) { throw new Error(`Viem chain ${viemChainName} not found`); } - const directoryPath = `../contracts/deployments/${hardhatChainName ?? viemChainName}`; + const directoryPath = `../contracts/deployments/${hardhatChainName}`; const files = await readdir(directoryPath); const results: ContractConfig[] = []; @@ -33,6 +73,10 @@ const readArtifacts = async (viemChainName: string, hardhatChainName?: string) = }); } } + + const { KlerosCore } = arbitratorContracts.default.contracts; + const arbitratorContractConfigs = [{ name: "KlerosCore", contract: KlerosCore }]; + arbitratorContractConfigs.forEach(({ name, contract }) => addArbitratorContract({ results, chain, name, contract })); return results; }; @@ -41,24 +85,28 @@ const getConfig = async (): Promise => { let viemNetwork: string; let hardhatNetwork: string; + let arbitratorContracts; switch (deployment) { case "devnet": viemNetwork = "arbitrumSepolia"; hardhatNetwork = "arbitrumSepoliaDevnet"; + arbitratorContracts = arbitratorDevnet; break; case "testnet": viemNetwork = "arbitrumSepolia"; hardhatNetwork = "arbitrumSepolia"; + arbitratorContracts = arbitratorTestnet; break; case "mainnet": viemNetwork = "arbitrum"; hardhatNetwork = "arbitrum"; + arbitratorContracts = arbitratorMainnet; break; default: throw new Error(`Unknown deployment ${deployment}`); } - const deploymentContracts = await readArtifacts(viemNetwork, hardhatNetwork); + const deploymentContracts = await readArtifacts(viemNetwork, hardhatNetwork, arbitratorContracts); return { out: "src/hooks/contracts/generated.ts", diff --git a/yarn.lock b/yarn.lock index 9de06e72..d9c86379 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4956,7 +4956,7 @@ __metadata: "@kleros/escrow-v2-eslint-config": "workspace:^" "@kleros/escrow-v2-prettier-config": "workspace:^" "@kleros/escrow-v2-tsconfig": "workspace:^" - "@kleros/kleros-v2-contracts": "npm:^0.9.2" + "@kleros/kleros-v2-contracts": "npm:^0.9.3" "@logtail/pino": "npm:^0.4.0" "@nomicfoundation/hardhat-chai-matchers": "npm:^2.0.8" "@nomicfoundation/hardhat-ethers": "npm:^3.0.8" @@ -5050,6 +5050,7 @@ __metadata: "@graphql-codegen/cli": "npm:^4.0.1" "@graphql-codegen/client-preset": "npm:^4.6.2" "@kleros/kleros-app": "npm:^2.1.0" + "@kleros/kleros-v2-contracts": "npm:^0.9.3" "@kleros/ui-components-library": "npm:^2.19.0" "@reown/appkit": "npm:^1.6.6" "@reown/appkit-adapter-wagmi": "npm:^1.6.6" @@ -5121,15 +5122,15 @@ __metadata: languageName: node linkType: hard -"@kleros/kleros-v2-contracts@npm:^0.9.2": - version: 0.9.2 - resolution: "@kleros/kleros-v2-contracts@npm:0.9.2" +"@kleros/kleros-v2-contracts@npm:^0.9.3": + version: 0.9.3 + resolution: "@kleros/kleros-v2-contracts@npm:0.9.3" dependencies: "@chainlink/contracts": "npm:^1.3.0" "@kleros/vea-contracts": "npm:^0.6.0" "@openzeppelin/contracts": "npm:^5.2.0" viem: "npm:^2.24.1" - checksum: 10/8774811f7f49a25739e679ca7dc4fb10d86b635406473488f912d1445ed95107d46995b979882e8acdb762faad037c17b305007997cf70158aa6f95ae79bdd00 + checksum: 10/39862f09fc516f24e1ec2fc3bdde22aa83f58bada40c58e83ca15c8422b713cb8eac666673c67daf4873f4ca3d7c80ca3b7448d56936165847298b93ca2a9478 languageName: node linkType: hard From ae9a0272dd4258a1d8a7bdc5ed3f47a446155087 Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Fri, 18 Apr 2025 19:41:04 +0200 Subject: [PATCH 2/3] fix: attachmentdisplay fix --- web/src/components/ScrollTop.tsx | 33 +++++++++++++++++++++ web/src/hooks/useScrollTop.ts | 15 ++++++++++ web/src/pages/AttachmentDisplay/index.tsx | 35 ++++++++++++++++------- 3 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 web/src/components/ScrollTop.tsx create mode 100644 web/src/hooks/useScrollTop.ts diff --git a/web/src/components/ScrollTop.tsx b/web/src/components/ScrollTop.tsx new file mode 100644 index 00000000..77e4706d --- /dev/null +++ b/web/src/components/ScrollTop.tsx @@ -0,0 +1,33 @@ +import React, { useEffect, useRef } from "react"; +import { useLocation, useNavigate } from "react-router-dom"; + +import { useScrollTop } from "hooks/useScrollTop"; + +const ScrollTop: React.FC = () => { + const scrollTop = useScrollTop(); + const { search, pathname } = useLocation(); + const navigate = useNavigate(); + const hasScrolled = useRef(false); + + useEffect(() => { + if (hasScrolled.current) return; + const params = new URLSearchParams(search); + const section = params.get("section"); + + if (section) { + const targetElement = document.getElementById(section); + if (targetElement) { + targetElement.scrollIntoView({ behavior: "smooth" }); + hasScrolled.current = true; + navigate(pathname, { replace: true }); + return; + } + } + + scrollTop(); + }, []); + + return null; +}; + +export default ScrollTop; \ No newline at end of file diff --git a/web/src/hooks/useScrollTop.ts b/web/src/hooks/useScrollTop.ts new file mode 100644 index 00000000..004f8824 --- /dev/null +++ b/web/src/hooks/useScrollTop.ts @@ -0,0 +1,15 @@ +import { useContext } from "react"; +import { OverlayScrollContext } from "context/OverlayScrollContext"; + +export const useScrollTop = () => { + const osInstanceRef = useContext(OverlayScrollContext); + + const scrollTop = (smooth = false) => { + osInstanceRef?.current + ?.osInstance() + ?.elements() + ?.viewport.scroll({ top: 0, behavior: smooth ? "smooth" : "auto" }); + }; + + return scrollTop; +}; \ No newline at end of file diff --git a/web/src/pages/AttachmentDisplay/index.tsx b/web/src/pages/AttachmentDisplay/index.tsx index d387c211..c224291a 100644 --- a/web/src/pages/AttachmentDisplay/index.tsx +++ b/web/src/pages/AttachmentDisplay/index.tsx @@ -1,11 +1,15 @@ import React, { lazy, Suspense } from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; +import { responsiveSize } from "styles/responsiveSize"; +import { landscapeStyle, MAX_WIDTH_LANDSCAPE } from "styles/landscapeStyle"; import { useSearchParams } from "react-router-dom"; import NewTabIcon from "svgs/icons/new-tab.svg"; import Loader from "components/Loader"; +import ScrollTop from "components/ScrollTop"; +import { ExternalLink } from "components/ExternalLink"; import Header from "./Header"; @@ -13,22 +17,32 @@ const FileViewer = lazy(() => import("components/FileViewer")); const Container = styled.div` display: flex; - flex-direction: column; width: 100%; - gap: 8px; + background-color: ${({ theme }) => theme.lightBackground}; + padding: 32px 16px 40px; + max-width: ${MAX_WIDTH_LANDSCAPE}; + flex-direction: column; + margin: 0 auto; + + ${landscapeStyle( + () => css` + padding: 48px ${responsiveSize(0, 132)} 60px; + ` + )} `; const LoaderContainer = styled.div` - width: 100%; display: flex; justify-content: center; + width: 100%; `; -const NewTabInfo = styled.a` - align-self: flex-end; +const StyledExternalLink = styled(ExternalLink)` display: flex; - gap: 8px; align-items: center; + gap: 8px; + align-self: flex-end; + margin-bottom: 8px; `; const StyledNewTabIcon = styled(NewTabIcon)` @@ -39,16 +53,16 @@ const StyledNewTabIcon = styled(NewTabIcon)` const AttachmentDisplay: React.FC = () => { const [searchParams] = useSearchParams(); - const url = searchParams.get("url"); + return (
{url ? ( <> - + Open in new tab - + @@ -60,6 +74,7 @@ const AttachmentDisplay: React.FC = () => { ) : null} + ); }; From 75d36f722b6f1c07dfcda7e74459565fdea9f1bf Mon Sep 17 00:00:00 2001 From: kemuru <102478601+kemuru@users.noreply.github.com> Date: Fri, 18 Apr 2025 20:20:40 +0200 Subject: [PATCH 3/3] fix: hook fix --- web/src/pages/MyTransactions/TransactionDetails/index.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/web/src/pages/MyTransactions/TransactionDetails/index.tsx b/web/src/pages/MyTransactions/TransactionDetails/index.tsx index 6e6df50a..96303d08 100644 --- a/web/src/pages/MyTransactions/TransactionDetails/index.tsx +++ b/web/src/pages/MyTransactions/TransactionDetails/index.tsx @@ -32,7 +32,9 @@ const TransactionDetails: React.FC = () => { const { id } = useParams(); const { data: transactionDetails } = useTransactionDetailsQuery(id); const { data: escrowParameters } = useEscrowParametersQuery(); - const arbitrationCost = useReadKlerosCoreArbitrationCost(escrowParameters?.escrowParameters?.arbitratorExtraData); + const arbitrationCost = useReadKlerosCoreArbitrationCost({ + args: [escrowParameters?.escrowParameters?.arbitratorExtraData], + }); const nativeTokenSymbol = useNativeTokenSymbol(); const { tokenMetadata } = useTokenMetadata(transactionDetails?.escrow?.token); const erc20TokenSymbol = tokenMetadata?.symbol; @@ -88,6 +90,7 @@ const TransactionDetails: React.FC = () => { isPreview={false} feeTimeout={escrowParameters?.escrowParameters.feeTimeout} settlementTimeout={escrowParameters?.escrowParameters.settlementTimeout} + arbitrationCost={arbitrationCost?.data} {...{ status, token, @@ -96,7 +99,6 @@ const TransactionDetails: React.FC = () => { hasToPayFees, disputeRequest, resolvedEvents, - arbitrationCost, assetSymbol, transactionHash, }}