feat: pre-commit type checking and lint - web#2279
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds web pre-commit typechecks and lint-staged, tightens web TypeScript and package scripts, converts many runtime/prop types to ChangesWeb Development Tooling
Chain/address typing and builders
Types: viem Address/Hash, bigint, and hook typing
UI / import / lint / logging edits
Sequence Diagram(s)(Conditions for sequence diagrams not met for a single coherent multi-component new feature beyond tooling and typing churn; none generated.) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly Related Issues
Possibly Related PRs
Suggested labels
Suggested reviewers
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
web/src/layout/Header/navbar/Product.tsx (2)
61-61:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAvoid exposing the raw URL as alt text.
At Line 61,
alt={Icon}reads the image URL to assistive tech. Usealt=""(decorative image) oralt={text}instead.Proposed fix
- <StyledImg alt={Icon} src={Icon} isLoaded={isImgLoaded} onLoad={() => setIsImgLoaded(true)} /> + <StyledImg alt="" src={Icon} isLoaded={isImgLoaded} onLoad={() => setIsImgLoaded(true)} />🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/layout/Header/navbar/Product.tsx` at line 61, The alt prop for the image currently passes the raw URL (alt={Icon}) which exposes the image URL to assistive tech; update the <StyledImg> usage in Product.tsx to use a meaningful accessible label or mark it decorative: replace alt={Icon} with either a descriptive string prop (e.g., alt={productName} or alt={label}) if the image conveys content, or alt="" if purely decorative, and keep the existing src={Icon}, isLoaded={isImgLoaded} and onLoad={() => setIsImgLoaded(true)} unchanged.
54-61:⚠️ Potential issue | 🟠 Major | ⚡ Quick winLoading state can get stuck on broken URLs and won't reset on source changes.
At line 61, the skeleton is cleared only by
onLoad. A failed image request leaves the placeholder forever, and changing theIconprop won't resetisImgLoaded, so the skeleton won't show during loading of a new image.Proposed fix
-import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; ... const Product: React.FC<IProduct> = ({ text, url, Icon }) => { const [isImgLoaded, setIsImgLoaded] = useState(false); + + useEffect(() => { + if (typeof Icon === "string") setIsImgLoaded(false); + }, [Icon]); return ( ... - <StyledImg alt={Icon} src={Icon} isLoaded={isImgLoaded} onLoad={() => setIsImgLoaded(true)} /> + <StyledImg + alt={Icon} + src={Icon} + isLoaded={isImgLoaded} + onLoad={() => setIsImgLoaded(true)} + onError={() => setIsImgLoaded(true)} + />🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/layout/Header/navbar/Product.tsx` around lines 54 - 61, The image loading state can get stuck because isImgLoaded is only set true in StyledImg's onLoad and never reset on failures or when Icon changes; update the component to handle both onError (call setIsImgLoaded(false) and optionally mark a failed state) and reset isImgLoaded when the Icon prop changes (use a useEffect that calls setIsImgLoaded(false) when Icon changes) so the Skeleton shows for new sources and broken URLs don't leave the placeholder permanently; update references to isImgLoaded, setIsImgLoaded, StyledImg and Icon accordingly.
🧹 Nitpick comments (1)
web/src/hooks/queries/useUser.ts (1)
61-70: ⚡ Quick winConditionally pass
wherevariable only when using the filtered query.Currently,
variablesalways includeswhere: sanitizedWhereregardless of whetheruserQueryoruserQueryDisputeFilteris selected. When usinguserQuery(which only declares$address: ID!), thewherefield is unnecessary. Passing it is harmless at runtime since GraphQL ignores undeclared variables, but it's inefficient and unclear.More importantly,
address?.toLowerCase()is computed twice (lines 62 and 69). Extract it to a variable to avoid redundant evaluation.Suggested refactor
+ const lowerAddress = address?.toLowerCase(); return useQuery<UserQuery | UserDisputeFilterQuery>({ - queryKey: ["userQuery", address?.toLowerCase(), sanitizedWhere], + queryKey: ["userQuery", lowerAddress, sanitizedWhere], enabled: isEnabled, staleTime: STALE_TIME, queryFn: async () => await graphqlBatcher.fetch({ id: crypto.randomUUID(), document: query, - variables: { address: address?.toLowerCase(), where: sanitizedWhere }, + variables: sanitizedWhere + ? { address: lowerAddress, where: sanitizedWhere } + : { address: lowerAddress }, }), });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/hooks/queries/useUser.ts` around lines 61 - 70, Compute address.toLowerCase() once into a local const (e.g., lowerAddress) and use that in queryKey and in graphqlBatcher.fetch variables; then build the variables object starting with { address: lowerAddress } and only add the where: sanitizedWhere property when the filtered document is being used (refer to the query document identifier userQueryDisputeFilter or another flag you already use to pick the filtered query). Update the useQuery call to use lowerAddress instead of address?.toLowerCase() twice and pass the conditionally constructed variables object to graphqlBatcher.fetch in the queryFn.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@web/src/layout/Header/navbar/Product.tsx`:
- Line 61: The alt prop for the image currently passes the raw URL (alt={Icon})
which exposes the image URL to assistive tech; update the <StyledImg> usage in
Product.tsx to use a meaningful accessible label or mark it decorative: replace
alt={Icon} with either a descriptive string prop (e.g., alt={productName} or
alt={label}) if the image conveys content, or alt="" if purely decorative, and
keep the existing src={Icon}, isLoaded={isImgLoaded} and onLoad={() =>
setIsImgLoaded(true)} unchanged.
- Around line 54-61: The image loading state can get stuck because isImgLoaded
is only set true in StyledImg's onLoad and never reset on failures or when Icon
changes; update the component to handle both onError (call setIsImgLoaded(false)
and optionally mark a failed state) and reset isImgLoaded when the Icon prop
changes (use a useEffect that calls setIsImgLoaded(false) when Icon changes) so
the Skeleton shows for new sources and broken URLs don't leave the placeholder
permanently; update references to isImgLoaded, setIsImgLoaded, StyledImg and
Icon accordingly.
---
Nitpick comments:
In `@web/src/hooks/queries/useUser.ts`:
- Around line 61-70: Compute address.toLowerCase() once into a local const
(e.g., lowerAddress) and use that in queryKey and in graphqlBatcher.fetch
variables; then build the variables object starting with { address: lowerAddress
} and only add the where: sanitizedWhere property when the filtered document is
being used (refer to the query document identifier userQueryDisputeFilter or
another flag you already use to pick the filtered query). Update the useQuery
call to use lowerAddress instead of address?.toLowerCase() twice and pass the
conditionally constructed variables object to graphqlBatcher.fetch in the
queryFn.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3b45ab75-7268-49b4-853a-0f3f2b1f3b76
📒 Files selected for processing (38)
web/src/components/BlueIconTextButtonContainer.tsxweb/src/components/DottedMenuButton.tsxweb/src/components/ExtraStatsDisplay.tsxweb/src/components/InternalLink.tsxweb/src/components/LightButton.tsxweb/src/components/OverlayPortal.tsxweb/src/components/ScrollTop.tsxweb/src/components/StyledIcons/ClosedCircleIcon.tsxweb/src/components/Verdict/index.tsxweb/src/consts/socialmedia.tsweb/src/hooks/queries/useHomePageBlockQuery.tsweb/src/hooks/queries/useHomePageExtraStats.tsweb/src/hooks/queries/useJurorsByCoherenceScore.tsweb/src/hooks/queries/useTopStakedJurorsByCourt.tsweb/src/hooks/queries/useUser.tsweb/src/hooks/useFundAppeal.tsweb/src/hooks/useNavigateAndScrollTop.tsweb/src/hooks/useScrollTop.tsweb/src/hooks/useSortitionModule.tsweb/src/hooks/useToggleThemeContext.tsxweb/src/layout/Footer/index.tsxweb/src/layout/Header/navbar/Product.tsxweb/src/pages/Cases/CaseDetails/index.tsxweb/src/pages/Courts/CourtDetails/StakingHistoryByCourt/DisplayStakes/StakeEventCard/DesktopCard.tsxweb/src/pages/Courts/CourtDetails/StakingHistoryByCourt/DisplayStakes/StakeEventCard/MobileCard.tsxweb/src/pages/Courts/index.tsxweb/src/pages/GetPnk/index.tsxweb/src/pages/Home/CourtOverview/CasesByCourtsChart.tsxweb/src/pages/Home/CourtOverview/StakedPNKByCourtsChart.tsxweb/src/pages/Home/TopJurors/JurorCard/Coherence.tsxweb/src/pages/Home/TopJurors/JurorCard/JurorLevel.tsxweb/src/pages/Home/TopJurors/JurorCard/MobileCard.tsxweb/src/pages/Home/TopJurors/JurorCard/Score.tsxweb/src/pages/Home/index.tsxweb/src/pages/Profile/JurorCard/BottomContent/index.tsxweb/src/pages/Settings/index.tsxweb/src/styles/customScrollbar.tsweb/src/utils/getVoteChoice.ts
💤 Files with no reviewable changes (2)
- web/src/pages/Home/TopJurors/JurorCard/Score.tsx
- web/src/hooks/useSortitionModule.ts
✅ Files skipped from review due to trivial changes (30)
- web/src/pages/Cases/CaseDetails/index.tsx
- web/src/components/BlueIconTextButtonContainer.tsx
- web/src/components/Verdict/index.tsx
- web/src/pages/GetPnk/index.tsx
- web/src/pages/Courts/CourtDetails/StakingHistoryByCourt/DisplayStakes/StakeEventCard/MobileCard.tsx
- web/src/pages/Courts/index.tsx
- web/src/components/InternalLink.tsx
- web/src/components/StyledIcons/ClosedCircleIcon.tsx
- web/src/pages/Home/TopJurors/JurorCard/JurorLevel.tsx
- web/src/pages/Home/index.tsx
- web/src/layout/Footer/index.tsx
- web/src/utils/getVoteChoice.ts
- web/src/pages/Home/TopJurors/JurorCard/MobileCard.tsx
- web/src/hooks/useToggleThemeContext.tsx
- web/src/consts/socialmedia.ts
- web/src/hooks/useFundAppeal.ts
- web/src/hooks/useNavigateAndScrollTop.ts
- web/src/components/LightButton.tsx
- web/src/components/ExtraStatsDisplay.tsx
- web/src/pages/Home/TopJurors/JurorCard/Coherence.tsx
- web/src/styles/customScrollbar.ts
- web/src/pages/Courts/CourtDetails/StakingHistoryByCourt/DisplayStakes/StakeEventCard/DesktopCard.tsx
- web/src/pages/Profile/JurorCard/BottomContent/index.tsx
- web/src/pages/Settings/index.tsx
- web/src/hooks/queries/useTopStakedJurorsByCourt.ts
- web/src/components/OverlayPortal.tsx
- web/src/hooks/queries/useJurorsByCoherenceScore.ts
- web/src/components/ScrollTop.tsx
- web/src/components/DottedMenuButton.tsx
- web/src/hooks/queries/useHomePageExtraStats.ts
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
web/src/pages/Resolver/Parameters/Court/FeatureSelection/index.tsx (1)
61-79:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAvoid suppressing
exhaustive-depsfor initialization logicThe effect reads
disputeData.disputeKitIdbut has an empty dependency array with the lint rule suppressed at line 78. SincedisputeKitIdis assigned after mount (e.g., when dispute data is fetched in Landing.tsx or when the court selection changes), the empty deps array with suppression can skip initialization ifdisputeKitIdbecomes available after the initial render. Use a one-time guard withuseRefinstead to preserve the initialization intent while handling post-mount updates:Suggested refactor pattern
-import React, { Fragment, useEffect, useMemo } from "react"; +import React, { Fragment, useEffect, useMemo, useRef } from "react"; ... + const initializedFromKitRef = useRef(false); + // DEV: initial feature selection logic, included hardcoded logic useEffect(() => { - if (!isUndefined(disputeData?.disputeKitId)) { - const defaultKit = disputeKitsForDeployment.find((dk) => dk.id === disputeData.disputeKitId); - if (!defaultKit) return; + if (initializedFromKitRef.current) return; + if (isUndefined(disputeData?.disputeKitId)) return; + + const defaultKit = disputeKitsForDeployment.find((dk) => dk.id === disputeData.disputeKitId); + if (!defaultKit) return; - // some kits like gated can have two feature sets, one for gatedERC20 and other for ERC1155 - if (defaultKit?.featureSets.length > 1) { - if ((disputeData?.disputeKitData as IGatedDisputeData)?.isERC1155) { - // defaultKit.featureSets[0][0] - is either Classic or Shutter - setSelected([defaultKit.featureSets[0][0], Features.GatedErc1155]); - } else { - setSelected([defaultKit.featureSets[0][0], Features.GatedErc20]); - } + // some kits like gated can have two feature sets, one for gatedERC20 and other for ERC1155 + if (defaultKit.featureSets.length > 1) { + if ((disputeData?.disputeKitData as IGatedDisputeData)?.isERC1155) { + setSelected([defaultKit.featureSets[0][0], Features.GatedErc1155]); + } else { + setSelected([defaultKit.featureSets[0][0], Features.GatedErc20]); } - } else if (defaultKit.featureSets.length === 1) { - setSelected(defaultKit.featureSets[0]); - } + } else if (defaultKit.featureSets.length === 1) { + setSelected(defaultKit.featureSets[0]); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + initializedFromKitRef.current = true; + }, [disputeData?.disputeKitId, disputeData?.disputeKitData, disputeKitsForDeployment, setSelected]);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/pages/Resolver/Parameters/Court/FeatureSelection/index.tsx` around lines 61 - 79, The effect currently suppresses exhaustive-deps and only runs on mount, so if disputeData.disputeKitId is set after mount the initialization will be skipped; update the useEffect in FeatureSelection to remove the eslint-disable and instead depend on disputeData?.disputeKitId and disputeKitsForDeployment, but guard execution with a useRef "initialized" flag so the initialization logic (finding defaultKit and calling setSelected) runs only once when disputeKitId first becomes defined; reference the existing symbols useEffect, disputeData.disputeKitId, disputeKitsForDeployment, setSelected and the new useRef flag to implement this one-time, post-mount initialization.web/src/pages/Home/CourtOverview/Chart.tsx (1)
136-149:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winGuard empty tooltip elements before coordinate math.
When
elementsis empty,elements[0]?.element.xandelements[0]?.element.yareundefined. Lines 142–143 then compute arithmetic with undefined values (e.g.,undefined + this.height), producingNaNand causing incorrect conditional logic. Per Chart.js 3.9.1 API documentation, custom positioners should returnfalsewhen no valid elements exist.Add an early guard to return
falsewhen no active element is present.Proposed fix
Tooltip.positioners.custom = function (this: TooltipModel<ChartType>, elements: readonly ActiveElement[]) { + const first = elements[0]; + if (!first) return false; + const height = this.chart.chartArea.height; const width = this.chart.chartArea.width; - const x = elements[0]?.element.x; - const y = elements[0]?.element.y; + const x = first.element.x; + const y = first.element.y; const isAtTop = height > y + this.height; const isAtEnd = width < x + this.width; return { - x: elements[0]?.element.x, - y: elements[0]?.element.y, + x, + y, xAlign: isAtTop ? (isAtEnd ? "right" : "left") : "center", yAlign: isAtTop ? "center" : "bottom", }; };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/pages/Home/CourtOverview/Chart.tsx` around lines 136 - 149, The custom tooltip positioner (Tooltip.positioners.custom) does not guard for an empty elements array and then performs arithmetic on undefined (e.g., elements[0]?.element.x + this.height), causing NaN; add an early check in Tooltip.positioners.custom to return false when elements is empty or elements[0]?.element is falsy, before computing height/width/x/y and the isAtTop/isAtEnd logic, so the positioner returns false per Chart.js expectations when no active element exists.web/src/pages/Resolver/Parameters/NotablePersons/PersonFields.tsx (1)
68-80:⚠️ Potential issue | 🟠 Major | ⚡ Quick winRemove eslint-disable-next-line react-hooks/exhaustive-deps and add proper dependencies.
This effect reads
publicClientanddisputeData.aliasesArraybut with an empty dependency array, it runs only once at mount. If these values are populated after the initial render, validation never runs, breaking the pre-populated alias scenario described in the comment. Additionally, line 70 uses.map(async ...)without awaiting, creating fire-and-forget async callbacks that can cause stale state issues.Suggested fix for exhaustive-deps suppression
- // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, [disputeData.aliasesArray, publicClient]);Also consider wrapping the map with
Promise.all()to ensure all validations complete before moving on.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/pages/Resolver/Parameters/NotablePersons/PersonFields.tsx` around lines 68 - 80, Remove the eslint-disable comment and update the useEffect that references useEffect, publicClient, disputeData.aliasesArray, validateAddress and setDisputeData so it properly lists publicClient and disputeData.aliasesArray in its dependency array; replace the .map(async ...) fire-and-forget pattern with a Promise.all over disputeData.aliasesArray.map to await all validateAddress(alias.address, publicClient) calls, build a new aliases array immutably (do not mutate disputeData.aliasesArray in place) updating each .isValid based on the awaited results, then call setDisputeData once with the new disputeData object; ensure you handle the case where publicClient or aliasesArray is undefined to avoid unnecessary runs.web/src/components/DisputeFeatures/Features/GatedErc1155.tsx (1)
56-71:⚠️ Potential issue | 🟠 Major | ⚡ Quick winLine 70: Dependency list is missing
disputeData, risking stale-state overwrites when both ERC20 and ERC1155 validations update concurrently.The effect spreads
disputeData(line 65) but omits it from dependencies. If the context is updated elsewhere before this effect executes, the spread will use a stale snapshot and overwrite newer values. The comment on line 57 acknowledges potential conflicts with the parallel ERC20 validation effect.Suggested fix
- // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isValid, setDisputeData, props.checked]); + }, [isValid, props.checked, disputeData, setDisputeData]);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/components/DisputeFeatures/Features/GatedErc1155.tsx` around lines 56 - 71, The effect currently spreads disputeData directly and can overwrite concurrent updates; instead use a functional state updater inside the useEffect so you always operate on the latest disputeData: in the useEffect that references isValid, props.checked and calls setDisputeData, replace the setDisputeData({ ...disputeData, disputeKitData: { ...currentData, isTokenGateValid: isValid } }) call with setDisputeData(prev => ({ ...prev, disputeKitData: { ...(prev.disputeKitData as IGatedDisputeData), isTokenGateValid: isValid } })), and keep the dependency list to [isValid, setDisputeData, props.checked] (or if you prefer to keep the original pattern instead, add disputeData to the deps); this ensures useEffect, currentData, disputeData and setDisputeData are updated safely without stale overwrites.
🧹 Nitpick comments (1)
web/src/components/Popup/Description/SwapSuccess.tsx (1)
60-68: ⚡ Quick winAlign
ISwapSuccesswith the props actually used.
from/toremain in the interface but are no longer consumed after Line 68. Either remove them from the type or wire them back into rendering to keep the component contract unambiguous.Suggested cleanup
-import { Token } from "pages/GetPnk/Swap/TokenSelect"; - interface ISwapSuccess { hash: string; amount: string; - from?: Token; - to?: Token; isClaim?: boolean; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/components/Popup/Description/SwapSuccess.tsx` around lines 60 - 68, The ISwapSuccess interface declares optional from and to Token props that the SwapSuccess component no longer uses; either remove these unused properties from ISwapSuccess to match the actual props consumed by the SwapSuccess component, or reintroduce them into the component’s JSX/logic (e.g., display token icons/names or include them in the success message) and update the SwapSuccess prop destructuring to accept from and to; make the change in the ISwapSuccess declaration and the SwapSuccess component signature so the type and implementation stay consistent (references: ISwapSuccess, SwapSuccess).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@web/src/components/DisputeFeatures/Features/GatedErc1155.tsx`:
- Around line 56-71: The effect currently spreads disputeData directly and can
overwrite concurrent updates; instead use a functional state updater inside the
useEffect so you always operate on the latest disputeData: in the useEffect that
references isValid, props.checked and calls setDisputeData, replace the
setDisputeData({ ...disputeData, disputeKitData: { ...currentData,
isTokenGateValid: isValid } }) call with setDisputeData(prev => ({ ...prev,
disputeKitData: { ...(prev.disputeKitData as IGatedDisputeData),
isTokenGateValid: isValid } })), and keep the dependency list to [isValid,
setDisputeData, props.checked] (or if you prefer to keep the original pattern
instead, add disputeData to the deps); this ensures useEffect, currentData,
disputeData and setDisputeData are updated safely without stale overwrites.
In `@web/src/pages/Home/CourtOverview/Chart.tsx`:
- Around line 136-149: The custom tooltip positioner
(Tooltip.positioners.custom) does not guard for an empty elements array and then
performs arithmetic on undefined (e.g., elements[0]?.element.x + this.height),
causing NaN; add an early check in Tooltip.positioners.custom to return false
when elements is empty or elements[0]?.element is falsy, before computing
height/width/x/y and the isAtTop/isAtEnd logic, so the positioner returns false
per Chart.js expectations when no active element exists.
In `@web/src/pages/Resolver/Parameters/Court/FeatureSelection/index.tsx`:
- Around line 61-79: The effect currently suppresses exhaustive-deps and only
runs on mount, so if disputeData.disputeKitId is set after mount the
initialization will be skipped; update the useEffect in FeatureSelection to
remove the eslint-disable and instead depend on disputeData?.disputeKitId and
disputeKitsForDeployment, but guard execution with a useRef "initialized" flag
so the initialization logic (finding defaultKit and calling setSelected) runs
only once when disputeKitId first becomes defined; reference the existing
symbols useEffect, disputeData.disputeKitId, disputeKitsForDeployment,
setSelected and the new useRef flag to implement this one-time, post-mount
initialization.
In `@web/src/pages/Resolver/Parameters/NotablePersons/PersonFields.tsx`:
- Around line 68-80: Remove the eslint-disable comment and update the useEffect
that references useEffect, publicClient, disputeData.aliasesArray,
validateAddress and setDisputeData so it properly lists publicClient and
disputeData.aliasesArray in its dependency array; replace the .map(async ...)
fire-and-forget pattern with a Promise.all over disputeData.aliasesArray.map to
await all validateAddress(alias.address, publicClient) calls, build a new
aliases array immutably (do not mutate disputeData.aliasesArray in place)
updating each .isValid based on the awaited results, then call setDisputeData
once with the new disputeData object; ensure you handle the case where
publicClient or aliasesArray is undefined to avoid unnecessary runs.
---
Nitpick comments:
In `@web/src/components/Popup/Description/SwapSuccess.tsx`:
- Around line 60-68: The ISwapSuccess interface declares optional from and to
Token props that the SwapSuccess component no longer uses; either remove these
unused properties from ISwapSuccess to match the actual props consumed by the
SwapSuccess component, or reintroduce them into the component’s JSX/logic (e.g.,
display token icons/names or include them in the success message) and update the
SwapSuccess prop destructuring to accept from and to; make the change in the
ISwapSuccess declaration and the SwapSuccess component signature so the type and
implementation stay consistent (references: ISwapSuccess, SwapSuccess).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e7bac7b8-a921-4190-9425-ee18e7516241
📒 Files selected for processing (35)
web/eslint.config.mjsweb/src/components/ClaimPnkButton.tsxweb/src/components/DisputeFeatures/Features/GatedErc1155.tsxweb/src/components/DisputeFeatures/Features/GatedErc20.tsxweb/src/components/DisputePreview/DisputeContext.tsxweb/src/components/EnsureAuth.tsxweb/src/components/GradientTokenIcons.tsxweb/src/components/Popup/Description/SwapSuccess.tsxweb/src/components/Popup/MiniGuides/JurorLevels.tsxweb/src/components/Popup/index.tsxweb/src/components/ScrollTop.tsxweb/src/consts/index.tsweb/src/context/QueryClientProvider.tsxweb/src/hooks/queries/usePopulatedDisputeData.tsweb/src/hooks/useLocalStorage.tsweb/src/hooks/useSessionStorage.tsweb/src/layout/Footer/index.tsxweb/src/layout/Header/navbar/Menu/Settings/Notifications/FormContactDetails/EmailVerificationInfo.tsxweb/src/layout/Header/navbar/Menu/Settings/Notifications/FormContactDetails/index.tsxweb/src/layout/Header/navbar/Menu/Settings/Notifications/index.tsxweb/src/pages/Cases/CaseDetails/Appeal/Classic/Options/StageTwo.tsxweb/src/pages/Cases/CaseDetails/Appeal/Classic/StageExplainer.tsxweb/src/pages/Cases/CaseDetails/Voting/Shutter/Reveal.tsxweb/src/pages/Home/CourtOverview/Chart.tsxweb/src/pages/Home/TopJurors/Header/DesktopHeader.tsxweb/src/pages/Home/TopJurors/JurorCard/DesktopCard.tsxweb/src/pages/Profile/JurorCard/StakingRewards.tsxweb/src/pages/Resolver/Parameters/Court/FeatureSelection/index.tsxweb/src/pages/Resolver/Parameters/Jurors.tsxweb/src/pages/Resolver/Parameters/NotablePersons/PersonFields.tsxweb/src/pages/Resolver/Policy/index.tsxweb/src/styles/responsiveSize.tsweb/src/utils/crypto/hashJustification.tsweb/src/utils/fetchStakingEventsByCourt.tsweb/src/utils/getDisputeRequestParamsFromTxn.ts
💤 Files with no reviewable changes (4)
- web/src/components/DisputePreview/DisputeContext.tsx
- web/src/layout/Header/navbar/Menu/Settings/Notifications/index.tsx
- web/src/components/Popup/index.tsx
- web/src/pages/Cases/CaseDetails/Appeal/Classic/StageExplainer.tsx
✅ Files skipped from review due to trivial changes (21)
- web/src/pages/Cases/CaseDetails/Voting/Shutter/Reveal.tsx
- web/src/components/EnsureAuth.tsx
- web/src/pages/Resolver/Policy/index.tsx
- web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/StageTwo.tsx
- web/src/utils/getDisputeRequestParamsFromTxn.ts
- web/src/hooks/useSessionStorage.ts
- web/src/pages/Resolver/Parameters/Jurors.tsx
- web/src/pages/Home/TopJurors/JurorCard/DesktopCard.tsx
- web/src/components/Popup/MiniGuides/JurorLevels.tsx
- web/src/pages/Profile/JurorCard/StakingRewards.tsx
- web/src/styles/responsiveSize.ts
- web/src/context/QueryClientProvider.tsx
- web/src/consts/index.ts
- web/src/pages/Home/TopJurors/Header/DesktopHeader.tsx
- web/src/components/ScrollTop.tsx
- web/src/utils/crypto/hashJustification.ts
- web/src/components/GradientTokenIcons.tsx
- web/src/components/DisputeFeatures/Features/GatedErc20.tsx
- web/eslint.config.mjs
- web/src/hooks/queries/usePopulatedDisputeData.ts
- web/src/hooks/useLocalStorage.ts
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
web/src/pages/Cases/CaseDetails/MaintenanceButtons/ExecuteRuling.tsx (1)
45-50:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winDisable the button when
publicClientis unavailable.Line 50 now no-ops without
publicClient, but the button can still appear enabled. Include!publicClientinisDisabledso users don’t hit a silent click.Proposed fix
const isDisabled = useMemo( - () => isUndefined(id) || isError || isLoading || period !== Period.Execution || ruled, - [id, isError, isLoading, period, ruled] + () => isUndefined(id) || isError || isLoading || period !== Period.Execution || ruled || !publicClient, + [id, isError, isLoading, period, ruled, publicClient] );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/pages/Cases/CaseDetails/MaintenanceButtons/ExecuteRuling.tsx` around lines 45 - 50, The isDisabled memo currently omits publicClient so the button can be clickable while publicClient is missing; update the isDisabled condition to include !publicClient (e.g. () => isUndefined(id) || isError || isLoading || !publicClient || period !== Period.Execution || ruled) and add publicClient to the dependency array so the memo updates when publicClient becomes available; this aligns isDisabled with the early return in handleClick.web/src/components/JurorLink.tsx (1)
55-57:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winType
IJurorLink.addressasAddressand remove local assertions.
IdenticonOrAvatarandAddressOrNameboth expect0x${string}(Address type), but JurorLink acceptsstringand casts at use sites. Move the type constraint to the prop interface and make the import type-only sinceAddressis only needed for type annotations.Suggested refactor
-import { Address } from "viem"; +import type { Address } from "viem"; @@ interface IJurorLink { - address: string; + address: Address; isInternalLink?: boolean; smallDisplay?: boolean; } @@ - <IdenticonOrAvatar address={address as Address} /> + <IdenticonOrAvatar address={address} /> @@ - <AddressOrName address={address as Address} smallDisplay={smallDisplay} /> + <AddressOrName address={address} smallDisplay={smallDisplay} />🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/components/JurorLink.tsx` around lines 55 - 57, Change IJurorLink.address from string to the Address type and remove any local "0x" casts/assertions at usage sites: update the interface declaration IJurorLink { address: Address; ... } (import Address as a type-only import) and then remove the runtime casts where IdenticonOrAvatar and AddressOrName are passed the address so they receive the correctly typed Address directly; ensure the Address import uses import type { Address } to avoid emitting runtime code.web/src/components/DisputeFeatures/Features/GatedErc20.tsx (1)
56-70:⚠️ Potential issue | 🟠 Major | ⚡ Quick winThe proposed refactor is incompatible with the actual
setDisputeDataAPI.The stale closure concern is valid—the effect reads
disputeDatawithout including it in dependencies. However, the suggested refactor uses a functional updater pattern(prev) => { ... }whichsetDisputeDatadoes not support. TheuseLocalStoragehook returns a setter with signature(newValue: T) => void, not(prev: T) => T.To fix the stale closure safely, either:
- Add
disputeDatato the dependency array (verify this doesn't cause loops), or- Use a ref-based approach to access the current value while keeping deps stable.
The current eslint suppression addresses a real issue but needs a compatible solution.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/components/DisputeFeatures/Features/GatedErc20.tsx` around lines 56 - 70, The effect reads disputeData but the setDisputeData setter from useLocalStorage does not accept a functional updater, so replace the eslint suppression with a compatible fix: either add disputeData to the dependency list of the useEffect (so the effect uses the latest disputeData when updating disputeKitData on isValid change) or keep deps stable and introduce a mutable ref (e.g., disputeDataRef) that you update whenever disputeData changes and then read disputeDataRef.current inside the useEffect; ensure you update disputeKitData only when props.checked is true and when currentData.isTokenGateValid differs from isValid, and reference IGatedDisputeData/currentData and setDisputeData exactly as in the existing block.web/src/hooks/queries/usePopulatedDisputeData.ts (1)
33-38:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAvoid unsafe non-null assertion on
templateId.The enabled guard only excludes
undefined, but Line 50 force-unwrapstemplateId. IftemplateIdisnull, this throws at runtime before the query call.Suggested fix
- const isEnabled = + const templateId = disputeData?.dispute?.templateId; + const isEnabled = !isUndefined(disputeID) && !isUndefined(disputeData) && !isUndefined(disputeData?.dispute) && !isUndefined(disputeData.dispute?.arbitrableChainId) && - !isUndefined(disputeData.dispute?.templateId); + templateId != null; ... - variables: { id: disputeData.dispute!.templateId!.toString() }, + variables: { id: templateId.toString() },Also applies to: 50-50
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/hooks/queries/usePopulatedDisputeData.ts` around lines 33 - 38, The current isEnabled guard only excludes undefined but not null, yet later code force-unwraps disputeData.dispute.templateId causing a runtime throw if templateId === null; update the guard for isEnabled to use a nullish check (e.g., disputeData?.dispute?.templateId != null or !== null && !== undefined) so templateId is guaranteed non-null before any non-null assertion, and remove any unnecessary non-null assertions where templateId is used (or use a safe access/early return) in the query invocation that currently force-unwraps templateId.web/src/components/Popup/MiniGuides/PageContentsTemplate.tsx (1)
100-107:⚠️ Potential issue | 🟠 Major | ⚡ Quick winGuard missing right-page component before rendering.
RightPageComponentcan beundefinedwhen page counts diverge, which causes an invalid element render crash.Suggested fix
const RightContent: React.FC<{ currentPage: number; rightPageComponents: React.FC[] }> = ({ currentPage, rightPageComponents, }) => { const RightPageComponent = rightPageComponents[currentPage - 1]; + if (!RightPageComponent) return null; return <RightPageComponent />; };Also applies to: 117-117
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/components/Popup/MiniGuides/PageContentsTemplate.tsx` around lines 100 - 107, RightContent currently grabs RightPageComponent = rightPageComponents[currentPage - 1] and renders it directly, which can be undefined if page counts diverge; update RightContent to check that RightPageComponent is a valid component (and that currentPage is in range) before rendering and return a safe fallback (null or a placeholder) when undefined. Specifically, in the RightContent component, validate rightPageComponents and index (currentPage - 1) and only render <RightPageComponent /> when it exists, otherwise render null or an explicit fallback to avoid invalid element render crashes; apply the same guard for the analogous usage at the other occurrence mentioned.
🧹 Nitpick comments (7)
web/src/tests/e2e/utils/contracts.ts (1)
18-22: 💤 Low valueConsider consolidating redundant type assertions.
SonarCloud correctly identifies that the type assertions on lines 20-22 may be redundant since
chainIdis already cast to a compatible key type on line 18. If all contract address maps share the same chain ID keys, a single cast should suffice:const chainId = DEFAULT_CHAIN.id as keyof typeof disputeResolverAddress; export const DISPUTE_RESOLVER_ADDRESS = disputeResolverAddress[chainId]; export const KLEROS_CORE_ADDRESS = klerosCoreAddress[chainId]; export const SORTITION_MODULE_ADDRESS = sortitionModuleAddress[chainId]; export const PNK_ADDRESS = pnkAddress[chainId];That said, the current approach is defensive and ensures type safety even if the maps diverge in the future. Given the PR's focus on stricter TypeScript configuration, this can be left as-is or refactored for cleaner code.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/tests/e2e/utils/contracts.ts` around lines 18 - 22, The code repeatedly casts chainId when indexing each address map even though chainId is already declared as DEFAULT_CHAIN.id as keyof typeof disputeResolverAddress; remove the redundant per-access assertions and use the single typed variable (chainId) for all lookups: update usages of disputeResolverAddress[chainId], klerosCoreAddress[chainId], sortitionModuleAddress[chainId], and pnkAddress[chainId] to rely on the initial cast (or if you prefer defensive typing, change the initial cast to a common union type shared by all maps) so the extra "as keyof typeof ..." on KLEROS_CORE_ADDRESS, SORTITION_MODULE_ADDRESS, and PNK_ADDRESS is eliminated.web/src/hooks/queries/useCourtTree.ts (1)
61-61: ⚖️ Poor tradeoffType cast in recursive mapping may hide type incompatibilities.
The cast
child as Courtassumes each child conforms to the fullCourttype structure. While functionally this is likely correct (GraphQL returns consistent nested court structures), TypeScript may not be able to prove that deeply nested children have the same type as the root court.This is a common limitation with recursive types. If the cast becomes problematic, consider:
- Using a more specific child type that reflects the actual GraphQL schema
- Structuring the query to ensure type uniformity
- Using a type guard instead of an assertion
For now, this cast is acceptable given TypeScript's limitations with recursive structures, but it's worth noting for future refactoring.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/hooks/queries/useCourtTree.ts` at line 61, The recursive cast "child as Court" in the rootCourtToItems call can hide mismatches between nested nodes and the Court type; replace the assertion with a proper type guard or a specific child type: implement an isCourt(value): value is Court guard and use court.children.filter(isCourt).map(child => rootCourtToItems(child, value)) (or adjust the GraphQL generated type to a recursive CourtNode used by rootCourtToItems) so TypeScript can verify nested shapes instead of relying on a blind cast; update references to rootCourtToItems, court.children, and the Court type accordingly.web/src/pages/Cases/CaseDetails/Voting/Classic/Vote.tsx (1)
7-8: ⚡ Quick winRemove the
ClassicVoteParamsassertion on the vote payload.The assertion suppresses type checking at the callsite; letting TypeScript infer here is safer and catches drift automatically. The
useVotemutation accepts the union typeVoteParams, and the object being passed has a dynamictypefield that may not narrow toClassicVoteParamsspecifically, making the assertion unnecessary and potentially hiding type mismatches.Suggested refactor
-import { ClassicVoteParams } from "~src/actions/vote/params"; @@ - await vote({ + await vote({ disputeId: parsedDisputeID, voteIds: parsedVoteIDs, choice: voteOption, salt: BigInt(currentRoundIndex), justification, type: disputeKitName ?? DisputeKits.Classic, - } as ClassicVoteParams); + });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/pages/Cases/CaseDetails/Voting/Classic/Vote.tsx` around lines 7 - 8, In the Vote component, remove the explicit cast to ClassicVoteParams when passing the payload into the useVote mutation: stop asserting the object as ClassicVoteParams and let TypeScript infer the union VoteParams instead; locate the callsite where you construct the vote payload (the variable/inline object passed to useVote) and delete the "as ClassicVoteParams" cast, or change the payload's declared type to VoteParams if an explicit annotation is required, ensuring the useVote(...) call accepts the inferred union without suppressing type checking.web/src/pages/Resolver/Preview/index.tsx (1)
83-85: ⚡ Quick winConsider consolidating types to eliminate the cast.
The comment notes that
IDisputeTemplateis a subset ofDisputeDetailsand that types should be consolidated. Consider creating a shared base type or adjusting the template type to matchDisputeDetailsto avoid the type assertion.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/pages/Resolver/Preview/index.tsx` around lines 83 - 85, The cast on disputeTemplate (used in <DisputeContext disputeDetails={disputeTemplate as DisputeDetails} />) hides a type mismatch between IDisputeTemplate and DisputeDetails; remove the assertion by consolidating types: either define a shared base interface (e.g., BaseDispute) that contains the common fields and have both IDisputeTemplate and DisputeDetails extend it, or widen the disputeTemplate/type of DisputeContext.disputeDetails to accept the template type (or make IDisputeTemplate extend DisputeDetails if appropriate). Update the relevant type declarations (IDisputeTemplate, DisputeDetails, and the DisputeContext prop type) so the cast is unnecessary and the compiler verifies compatibility.web/src/hooks/useHomePageContext.tsx (1)
22-23: ⚡ Quick winMemoize the context value to prevent unnecessary re-renders.
The context value object is recreated on every render, causing all consumers to re-render even when
dataanderrorhaven't changed.⚡ Proposed fix using useMemo
const { data, error } = useHomePageQuery(timeframe); - return <Context.Provider value={{ data, error }}>{children}</Context.Provider>; + const value = useMemo(() => ({ data, error }), [data, error]); + return <Context.Provider value={value}>{children}</Context.Provider>;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/hooks/useHomePageContext.tsx` around lines 22 - 23, The Context.Provider value is recreated on every render because the object literal { data, error } is not memoized; update useHomePageContext (the component using useHomePageQuery) to memoize the provider value with useMemo so it only changes when data or error change and pass that memoized value to Context.Provider to avoid unnecessary consumer re-renders.web/src/pages/Profile/JurorCard/StakingRewards.tsx (1)
6-8: ⚡ Quick winRemove the commented-out implementation block.
Keeping this inactive code in-place makes the file harder to maintain and keeps static-analysis noise around. Please delete it and rely on git history if it needs to be restored.
Also applies to: 20-50
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/pages/Profile/JurorCard/StakingRewards.tsx` around lines 6 - 8, Delete the inactive commented-out import and component code block that includes the commented imports "Box as _Box, Button" and "EnsureChain" and any other commented implementation lines in the same file (the commented block around those imports and the larger commented region spanning the earlier file area), leaving only live code; rely on git history if recovery is needed and ensure no other commented implementation remnants remain between the same surrounding identifiers (e.g., references to _Box, Button, EnsureChain) so static-analysis and maintenance noise are removed.web/src/pages/Cases/CaseDetails/Voting/Classic/Commit.tsx (1)
7-8: ⚡ Quick winRemove the unnecessary
ClassicCommitParamscast.The assertion is redundant here and weakens type feedback; inference should be kept as-is.
♻️ Proposed cleanup
-import { ClassicCommitParams } from "~src/actions/commit/params"; @@ - await castCommit({ + await castCommit({ type: disputeKitName ?? DisputeKits.Classic, disputeId: parsedDisputeID, choice, voteIds: parsedVoteIDs, roundIndex: Number(currentRoundIndex), - } as ClassicCommitParams); + });Please verify by running the web workspace typecheck after this change.
Also applies to: 53-53
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/src/pages/Cases/CaseDetails/Voting/Classic/Commit.tsx` around lines 7 - 8, Remove the unnecessary ClassicCommitParams type assertion used in this file: drop the explicit cast to ClassicCommitParams wherever it's applied (the import can remain) — locate usages in Commit.tsx (including the occurrence around line 53) and let TypeScript infer the type instead of using the assertion; after removing the casts, run the web workspace typecheck to ensure no errors remain.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@web/src/actions/commit/builders/classic.builder.ts`:
- Around line 20-25: The code uses a type assertion for chainKey and directly
indexes disputeKitClassicAddress, which can yield undefined at runtime for
unsupported chain IDs; update the builder (e.g., in classic.builder.ts where
chainKey and disputeKitClassicAddress are used) to first perform a runtime
guard: check that disputeKitClassicAddress hasOwnProperty(chain.id) or that
disputeKitClassicAddress[chain.id] is truthy, and if not reject/throw a clear
error or return a failed Result (consistent with other builders) before
proceeding to build the transaction; apply the same pattern to the other builder
files (commit, vote, reveal, fundAppeal) so they all validate the chain ID and
fail fast with a descriptive error instead of allowing an undefined address to
be returned.
In `@web/src/actions/commit/builders/gatedShutter.builder.ts`:
- Around line 38-43: The code uses a type assertion for chain.id when accessing
disputeKitGatedShutterAddress which can still yield an undefined address at
runtime; add a runtime guard in the builder (around where chain.id is used to
compute chainKey and the returned address) to check that
disputeKitGatedShutterAddress[chainKey] is defined, and if not throw a clear
error or return a safe failure (e.g., throw new Error or return null/undefined)
before proceeding to the write path so the returned object (account, address,
abi) never contains an undefined address.
In `@web/src/actions/fundAppeal/builders/classic.builder.ts`:
- Around line 11-15: The code unsafely casts chain.id to a key for
disputeKitClassicAddress (chainKey) which can yield undefined address at
runtime; update the builder to validate the lookup by checking that
disputeKitClassicAddress hasOwnProperty(chain.id) or that
disputeKitClassicAddress[chain.id] is truthy before returning, throw or return a
clear error if missing, and only set address to
disputeKitClassicAddress[chain.id] when present; reference the variables
chain.id, chainKey, disputeKitClassicAddress, and the returned properties
account/address to locate and modify the lookup logic.
In `@web/src/actions/fundAppeal/builders/classicUniversity.builder.ts`:
- Around line 11-15: The code currently asserts chain.id into chainKey and
directly indexes disputeKitClassicUniversityAddress, which can yield undefined
at runtime; replace that with a runtime guard: compute chainKey from chain.id,
look up const address = disputeKitClassicUniversityAddress[chainKey], and if
address is undefined (i.e., unsupported chain) throw or return an explicit
error/result instead of returning an object with an undefined address; update
the return in the builder (the block that returns account and address) to use
the validated address so invalid contract calls are prevented.
In `@web/src/actions/reveal/builders/classic.builder.ts`:
- Around line 11-15: The code currently casts chain.id to a key (chainKey) for
disputeKitClassicAddress and may return undefined at runtime; update the
function (around chain.id / chainKey in classic.builder) to validate that
disputeKitClassicAddress hasOwnProperty(chain.id) (or key in
disputeKitClassicAddress) before using it, and if missing either throw a clear
error or return a safe fallback instead of allowing address to be undefined;
ensure the returned object (account, address) uses the validated lookup so
transactions never receive an undefined address.
In `@web/src/actions/reveal/builders/classicUniversity.builder.ts`:
- Around line 11-15: The code currently casts chain.id to chainKey and directly
indexes disputeKitClassicUniversityAddress which can yield undefined for
unsupported chains; add a runtime guard in the builder before returning (use the
chainKey variable) that checks whether
disputeKitClassicUniversityAddress[chainKey] is defined and if not throw a clear
Error (include the offending chain.id in the message) so the function fails fast
instead of returning an undefined address in the transaction config.
In `@web/src/actions/vote/builders/argentinaConsumerProtection.builder.ts`:
- Around line 14-18: The code currently casts chain.id to a key (chainKey) and
directly indexes disputeKitGatedArgentinaConsumerProtectionAddress which can
yield undefined at runtime; update the builder to defensively check that
chain.id exists in disputeKitGatedArgentinaConsumerProtectionAddress (following
the pattern in useDisputeKitAddresses) before using it, and throw or return a
clear error if not found; apply this same runtime guard pattern to all dispute
kit builders referenced (functions/variables like chainKey,
disputeKitGatedArgentinaConsumerProtectionAddress, and the other dispute kit
address maps used in classic, gated, shutter, gatedShutter, classicUniversity
builders across vote and commit actions) so no builder dereferences an address
with an unchecked type assertion.
In `@web/src/hooks/queries/usePolicyRegistryEvent.ts`:
- Line 11: The enabled flag and runtime guard are inconsistent: change any
runtime guard in queryFn that uses falsy checks (e.g., if (!courtID ||
!publicClient)) to use isUndefined() consistently (e.g., isUndefined(courtID) ||
isUndefined(publicClient)) so courtID=0 is treated as valid, and replace the
incorrect throw Error; with throwing an actual Error instance (throw new
Error('descriptive message')) so queryFn throws a proper Error; update
references in usePolicyRegistryEvent.ts for isEnabled, queryFn, courtID and
publicClient accordingly.
In `@web/src/pages/Cases/CaseDetails/MaintenanceButtons/DistributeRewards.tsx`:
- Around line 48-52: The klerosCoreAddress lookup uses a cast but may be
undefined at runtime; in DistributeRewards.tsx validate that the resolved chain
key exists in klerosCoreAddress before building baseArgs: compute chainKey from
chainId/DEFAULT_CHAIN.id, check if chainKey is a valid key (e.g., using
Object.prototype.hasOwnProperty.call(klerosCoreAddress, chainKey) or chainKey in
klerosCoreAddress), and only set baseArgs.address = klerosCoreAddress[chainKey]
when defined; if not defined, handle the case (throw or return early, disable
the action UI, or use a safe fallback) so execute/contract config never receives
undefined address. Ensure you update the references to chainKey and baseArgs in
this component accordingly.
In `@web/src/pages/Resolver/Parameters/Jurors.tsx`:
- Around line 70-71: The effect mutates disputeData without including it in deps
causing a stale closure; change the setDisputeData call in the useEffect to use
the functional updater form so it reads the latest state (e.g.
setDisputeData(prev => ({ ...prev, arbitrationCost: data?.toString() }))) and
keep the dependency array as [data] (remove the eslint-disable comment so lint
stays valid).
In `@web/src/utils/getDrawnJurorsWithCount.ts`:
- Line 1: The cast of transactionHash to viem's Hash in getDrawnJurorsWithCount
(and similarly in Evidence/index.tsx and DisputeTimeline.tsx) accepts any
GraphQL string and bypasses type safety; fix by importing and using viem's
isHash to validate the string before casting (e.g., check
isHash(transactionHashString) and only then cast to Hash or handle invalid
values—throw, return null, or skip), updating the logic in the function that
produces transactionHash so invalid hashes don't propagate downstream.
In `@web/src/utils/getGraphqlUrl.ts`:
- Around line 17-19: The return logic for isDisputeTemplate uses an unsafe type
assertion for CHAINID_TO_DISPUTE_TEMPLATE_SUBGRAPH[chainId as keyof typeof
CHAINID_TO_DISPUTE_TEMPLATE_SUBGRAPH], which can yield undefined for unsupported
chainId values; update the getGraphqlUrl logic to first check whether chainId
exists as a key in CHAINID_TO_DISPUTE_TEMPLATE_SUBGRAPH (e.g., using
Object.prototype.hasOwnProperty.call or chainId in
CHAINID_TO_DISPUTE_TEMPLATE_SUBGRAPH) and only return the mapped URL when
present, otherwise fall back to coreUrl or throw a clear error; ensure you
reference the same symbols (chainId, isDisputeTemplate,
CHAINID_TO_DISPUTE_TEMPLATE_SUBGRAPH, coreUrl) so callers get a safe
deterministic URL.
---
Outside diff comments:
In `@web/src/components/DisputeFeatures/Features/GatedErc20.tsx`:
- Around line 56-70: The effect reads disputeData but the setDisputeData setter
from useLocalStorage does not accept a functional updater, so replace the eslint
suppression with a compatible fix: either add disputeData to the dependency list
of the useEffect (so the effect uses the latest disputeData when updating
disputeKitData on isValid change) or keep deps stable and introduce a mutable
ref (e.g., disputeDataRef) that you update whenever disputeData changes and then
read disputeDataRef.current inside the useEffect; ensure you update
disputeKitData only when props.checked is true and when
currentData.isTokenGateValid differs from isValid, and reference
IGatedDisputeData/currentData and setDisputeData exactly as in the existing
block.
In `@web/src/components/JurorLink.tsx`:
- Around line 55-57: Change IJurorLink.address from string to the Address type
and remove any local "0x" casts/assertions at usage sites: update the interface
declaration IJurorLink { address: Address; ... } (import Address as a type-only
import) and then remove the runtime casts where IdenticonOrAvatar and
AddressOrName are passed the address so they receive the correctly typed Address
directly; ensure the Address import uses import type { Address } to avoid
emitting runtime code.
In `@web/src/components/Popup/MiniGuides/PageContentsTemplate.tsx`:
- Around line 100-107: RightContent currently grabs RightPageComponent =
rightPageComponents[currentPage - 1] and renders it directly, which can be
undefined if page counts diverge; update RightContent to check that
RightPageComponent is a valid component (and that currentPage is in range)
before rendering and return a safe fallback (null or a placeholder) when
undefined. Specifically, in the RightContent component, validate
rightPageComponents and index (currentPage - 1) and only render
<RightPageComponent /> when it exists, otherwise render null or an explicit
fallback to avoid invalid element render crashes; apply the same guard for the
analogous usage at the other occurrence mentioned.
In `@web/src/hooks/queries/usePopulatedDisputeData.ts`:
- Around line 33-38: The current isEnabled guard only excludes undefined but not
null, yet later code force-unwraps disputeData.dispute.templateId causing a
runtime throw if templateId === null; update the guard for isEnabled to use a
nullish check (e.g., disputeData?.dispute?.templateId != null or !== null && !==
undefined) so templateId is guaranteed non-null before any non-null assertion,
and remove any unnecessary non-null assertions where templateId is used (or use
a safe access/early return) in the query invocation that currently force-unwraps
templateId.
In `@web/src/pages/Cases/CaseDetails/MaintenanceButtons/ExecuteRuling.tsx`:
- Around line 45-50: The isDisabled memo currently omits publicClient so the
button can be clickable while publicClient is missing; update the isDisabled
condition to include !publicClient (e.g. () => isUndefined(id) || isError ||
isLoading || !publicClient || period !== Period.Execution || ruled) and add
publicClient to the dependency array so the memo updates when publicClient
becomes available; this aligns isDisabled with the early return in handleClick.
---
Nitpick comments:
In `@web/src/hooks/queries/useCourtTree.ts`:
- Line 61: The recursive cast "child as Court" in the rootCourtToItems call can
hide mismatches between nested nodes and the Court type; replace the assertion
with a proper type guard or a specific child type: implement an isCourt(value):
value is Court guard and use court.children.filter(isCourt).map(child =>
rootCourtToItems(child, value)) (or adjust the GraphQL generated type to a
recursive CourtNode used by rootCourtToItems) so TypeScript can verify nested
shapes instead of relying on a blind cast; update references to
rootCourtToItems, court.children, and the Court type accordingly.
In `@web/src/hooks/useHomePageContext.tsx`:
- Around line 22-23: The Context.Provider value is recreated on every render
because the object literal { data, error } is not memoized; update
useHomePageContext (the component using useHomePageQuery) to memoize the
provider value with useMemo so it only changes when data or error change and
pass that memoized value to Context.Provider to avoid unnecessary consumer
re-renders.
In `@web/src/pages/Cases/CaseDetails/Voting/Classic/Commit.tsx`:
- Around line 7-8: Remove the unnecessary ClassicCommitParams type assertion
used in this file: drop the explicit cast to ClassicCommitParams wherever it's
applied (the import can remain) — locate usages in Commit.tsx (including the
occurrence around line 53) and let TypeScript infer the type instead of using
the assertion; after removing the casts, run the web workspace typecheck to
ensure no errors remain.
In `@web/src/pages/Cases/CaseDetails/Voting/Classic/Vote.tsx`:
- Around line 7-8: In the Vote component, remove the explicit cast to
ClassicVoteParams when passing the payload into the useVote mutation: stop
asserting the object as ClassicVoteParams and let TypeScript infer the union
VoteParams instead; locate the callsite where you construct the vote payload
(the variable/inline object passed to useVote) and delete the "as
ClassicVoteParams" cast, or change the payload's declared type to VoteParams if
an explicit annotation is required, ensuring the useVote(...) call accepts the
inferred union without suppressing type checking.
In `@web/src/pages/Profile/JurorCard/StakingRewards.tsx`:
- Around line 6-8: Delete the inactive commented-out import and component code
block that includes the commented imports "Box as _Box, Button" and
"EnsureChain" and any other commented implementation lines in the same file (the
commented block around those imports and the larger commented region spanning
the earlier file area), leaving only live code; rely on git history if recovery
is needed and ensure no other commented implementation remnants remain between
the same surrounding identifiers (e.g., references to _Box, Button, EnsureChain)
so static-analysis and maintenance noise are removed.
In `@web/src/pages/Resolver/Preview/index.tsx`:
- Around line 83-85: The cast on disputeTemplate (used in <DisputeContext
disputeDetails={disputeTemplate as DisputeDetails} />) hides a type mismatch
between IDisputeTemplate and DisputeDetails; remove the assertion by
consolidating types: either define a shared base interface (e.g., BaseDispute)
that contains the common fields and have both IDisputeTemplate and
DisputeDetails extend it, or widen the disputeTemplate/type of
DisputeContext.disputeDetails to accept the template type (or make
IDisputeTemplate extend DisputeDetails if appropriate). Update the relevant type
declarations (IDisputeTemplate, DisputeDetails, and the DisputeContext prop
type) so the cast is unnecessary and the compiler verifies compatibility.
In `@web/src/tests/e2e/utils/contracts.ts`:
- Around line 18-22: The code repeatedly casts chainId when indexing each
address map even though chainId is already declared as DEFAULT_CHAIN.id as keyof
typeof disputeResolverAddress; remove the redundant per-access assertions and
use the single typed variable (chainId) for all lookups: update usages of
disputeResolverAddress[chainId], klerosCoreAddress[chainId],
sortitionModuleAddress[chainId], and pnkAddress[chainId] to rely on the initial
cast (or if you prefer defensive typing, change the initial cast to a common
union type shared by all maps) so the extra "as keyof typeof ..." on
KLEROS_CORE_ADDRESS, SORTITION_MODULE_ADDRESS, and PNK_ADDRESS is eliminated.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: b8f3abb3-08cb-460e-8411-9db9ea314ab4
📒 Files selected for processing (160)
kleros-sdk/src/types/reality-eth-lib.d.tsweb/eslint.config.mjsweb/global.d.tsweb/package.jsonweb/src/actions/commit/builders/argentinaConsumerProtection.builder.tsweb/src/actions/commit/builders/classic.builder.tsweb/src/actions/commit/builders/classicUniversity.builder.tsweb/src/actions/commit/builders/gated.builder.tsweb/src/actions/commit/builders/gatedShutter.builder.tsweb/src/actions/commit/builders/shutter.builder.tsweb/src/actions/fundAppeal/builders/argentinaConsumerProtection.builder.tsweb/src/actions/fundAppeal/builders/classic.builder.tsweb/src/actions/fundAppeal/builders/classicUniversity.builder.tsweb/src/actions/fundAppeal/builders/gated.builder.tsweb/src/actions/fundAppeal/builders/gatedShutter.builder.tsweb/src/actions/fundAppeal/builders/shutter.builder.tsweb/src/actions/reveal/builders/argentinaConsumerProtection.builder.tsweb/src/actions/reveal/builders/classic.builder.tsweb/src/actions/reveal/builders/classicUniversity.builder.tsweb/src/actions/reveal/builders/gated.builder.tsweb/src/actions/reveal/builders/gatedShutter.builder.tsweb/src/actions/reveal/builders/shutter.builder.tsweb/src/actions/reveal/helpers/bruteForceChoice.test.tsweb/src/actions/vote/builders/argentinaConsumerProtection.builder.tsweb/src/actions/vote/builders/classic.builder.tsweb/src/actions/vote/builders/classicUniversity.builder.tsweb/src/actions/vote/builders/gated.builder.tsweb/src/actions/vote/builders/gatedShutter.builder.tsweb/src/actions/vote/builders/shutter.builder.tsweb/src/components/ClaimPnkButton.tsxweb/src/components/ConnectWallet/index.tsxweb/src/components/DisputeFeatures/Features/GatedErc1155.tsxweb/src/components/DisputeFeatures/Features/GatedErc20.tsxweb/src/components/DisputePreview/Alias.tsxweb/src/components/DisputePreview/DisputeContext.tsxweb/src/components/DisputeView/CardLabels/index.tsxweb/src/components/DisputeView/DisputeCardView.tsxweb/src/components/DisputeView/DisputeInfo/DisputeInfoCard.tsxweb/src/components/DisputeView/DisputeInfo/DisputeInfoList.tsxweb/src/components/DisputeView/DisputeListView.tsxweb/src/components/EnsureAuth.tsxweb/src/components/GradientTokenIcons.tsxweb/src/components/JurorLink.tsxweb/src/components/MarkdownRenderer.tsxweb/src/components/Popup/Description/SwapSuccess.tsxweb/src/components/Popup/MiniGuides/JurorLevels.tsxweb/src/components/Popup/MiniGuides/PageContentsTemplate.tsxweb/src/components/Popup/index.tsxweb/src/components/ScrollTop.tsxweb/src/components/TxnHash.tsxweb/src/components/Verdict/DisputeTimeline.tsxweb/src/components/Verdict/FinalDecision.tsxweb/src/components/Verdict/index.tsxweb/src/config/rpc.tsweb/src/config/wagmi.tsweb/src/consts/index.tsweb/src/context/GraphqlBatcher.tsxweb/src/context/NewDisputeContext.tsxweb/src/context/OverlayScrollContext.tsxweb/src/context/QueryClientProvider.tsxweb/src/hooks/queries/useAllUserDraws.tsweb/src/hooks/queries/useAppealCost.tsweb/src/hooks/queries/useCourtTree.tsweb/src/hooks/queries/useDisputeKitClassicMultipliers.tsweb/src/hooks/queries/useHomePageBlockQuery.tsweb/src/hooks/queries/usePolicyRegistryEvent.tsweb/src/hooks/queries/usePopulatedDisputeData.tsweb/src/hooks/queries/useTopStakedJurorsByCourt.tsweb/src/hooks/useCoinPrice.tsxweb/src/hooks/useHomePageContext.tsxweb/src/hooks/useLocalStorage.tsweb/src/hooks/useNavigateAndScrollTop.tsweb/src/hooks/usePNKData.tsxweb/src/hooks/useScrollTop.tsweb/src/hooks/useSessionStorage.tsweb/src/hooks/useStakingEventsByCourt.tsweb/src/layout/Footer/index.tsxweb/src/layout/Header/navbar/Explore.tsxweb/src/layout/Header/navbar/Menu/Settings/Notifications/FormContactDetails/EmailVerificationInfo.tsxweb/src/layout/Header/navbar/Menu/Settings/Notifications/FormContactDetails/index.tsxweb/src/layout/Header/navbar/Menu/Settings/Notifications/index.tsxweb/src/layout/Header/navbar/Menu/index.tsxweb/src/pages/Cases/CaseDetails/Appeal/Classic/Options/StageTwo.tsxweb/src/pages/Cases/CaseDetails/Appeal/Classic/Options/index.tsxweb/src/pages/Cases/CaseDetails/Appeal/Classic/StageExplainer.tsxweb/src/pages/Cases/CaseDetails/Appeal/OptionCard.tsxweb/src/pages/Cases/CaseDetails/Evidence/SubmitEvidenceModal.tsxweb/src/pages/Cases/CaseDetails/MaintenanceButtons/DistributeRewards.tsxweb/src/pages/Cases/CaseDetails/MaintenanceButtons/ExecuteRuling.tsxweb/src/pages/Cases/CaseDetails/MaintenanceButtons/WithdrawAppealFees.tsxweb/src/pages/Cases/CaseDetails/Tabs.tsxweb/src/pages/Cases/CaseDetails/Timeline.tsxweb/src/pages/Cases/CaseDetails/Voting/Classic/Commit.tsxweb/src/pages/Cases/CaseDetails/Voting/Classic/Vote.tsxweb/src/pages/Cases/CaseDetails/Voting/Shutter/Reveal.tsxweb/src/pages/Cases/CaseDetails/Voting/VotesDetails/AccordionTitle.tsxweb/src/pages/Cases/CaseDetails/Voting/VotesDetails/index.tsxweb/src/pages/Cases/CaseDetails/Voting/VotingHistory.tsxweb/src/pages/Cases/CaseDetails/Voting/index.tsxweb/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsxweb/src/pages/Courts/CourtDetails/StakingHistoryByCourt/DisplayStakes/StakeEventCard.tsxweb/src/pages/Courts/CourtDetails/StakingHistoryByCourt/DisplayStakes/index.tsxweb/src/pages/Courts/CourtDetails/TopSearch.tsxweb/src/pages/Courts/CourtDetails/index.tsxweb/src/pages/GetPnk/Widget.tsxweb/src/pages/Home/CourtOverview/BarChart.tsxweb/src/pages/Home/CourtOverview/Chart.tsxweb/src/pages/Home/CourtOverview/ExtraStats.tsxweb/src/pages/Home/CourtOverview/Stats.tsxweb/src/pages/Home/CourtOverview/TimeSeriesChart.tsxweb/src/pages/Home/TopJurors/Header/DesktopHeader.tsxweb/src/pages/Home/TopJurors/Header/Rewards.tsxweb/src/pages/Home/TopJurors/JurorCard/DesktopCard.tsxweb/src/pages/Home/TopJurors/JurorCard/MobileCard.tsxweb/src/pages/Home/TopJurors/JurorCard/Rewards.tsxweb/src/pages/Home/TopJurors/JurorCard/index.tsxweb/src/pages/Home/TopJurors/index.tsxweb/src/pages/Jurors/DisplayJurors.tsxweb/src/pages/Jurors/index.tsxweb/src/pages/Profile/Cases/index.tsxweb/src/pages/Profile/JurorCard/BottomContent/JurorRewards.tsxweb/src/pages/Profile/JurorCard/BottomContent/index.tsxweb/src/pages/Profile/JurorCard/Header.tsxweb/src/pages/Profile/JurorCard/StakingRewards.tsxweb/src/pages/Profile/JurorCard/TopContent/index.tsxweb/src/pages/Profile/JurorCard/index.tsxweb/src/pages/Profile/Stakes/CourtCard/Stake.tsxweb/src/pages/Profile/Stakes/CourtCard/index.tsxweb/src/pages/Profile/Stakes/CurrentStakes/Header.tsxweb/src/pages/Profile/Stakes/CurrentStakes/index.tsxweb/src/pages/Profile/Stakes/StakingHistory.tsxweb/src/pages/Profile/Votes/VoteCard/CaseStatus.tsxweb/src/pages/Profile/Votes/VoteCard/index.tsxweb/src/pages/Profile/Votes/index.tsxweb/src/pages/Profile/index.tsxweb/src/pages/Resolver/Landing/index.tsxweb/src/pages/Resolver/NavigationButtons/SubmitBatchDisputesButton.tsxweb/src/pages/Resolver/NavigationButtons/SubmitDisputeButton.tsxweb/src/pages/Resolver/Parameters/Court/FeatureSelection/index.tsxweb/src/pages/Resolver/Parameters/Jurors.tsxweb/src/pages/Resolver/Parameters/NotablePersons/PersonFields.tsxweb/src/pages/Resolver/Policy/index.tsxweb/src/pages/Resolver/Preview/BatchCreationCard.tsxweb/src/pages/Resolver/Preview/index.tsxweb/src/pages/Settings/EmailConfirmation/index.tsxweb/src/styles/responsiveSize.tsweb/src/tests/e2e/utils/contracts.tsweb/src/types/react-identicons.d.tsweb/src/types/reality-eth-lib.d.tsweb/src/utils/crypto/hashJustification.tsweb/src/utils/fetchStakingEventsByCourt.tsweb/src/utils/findCourtNameById.tsweb/src/utils/format.tsweb/src/utils/getDisputeRequestParamsFromTxn.tsweb/src/utils/getDrawnJurorsWithCount.tsweb/src/utils/getGraphqlUrl.tsweb/src/utils/index.tsweb/src/utils/jurorRewardConfig.tsweb/src/utils/retrieveDisputeId.tsweb/tsconfig.json
💤 Files with no reviewable changes (3)
- web/src/components/Popup/index.tsx
- web/src/pages/Cases/CaseDetails/Appeal/Classic/StageExplainer.tsx
- web/src/layout/Header/navbar/Menu/Settings/Notifications/index.tsx
✅ Files skipped from review due to trivial changes (51)
- web/global.d.ts
- web/eslint.config.mjs
- web/src/actions/commit/builders/gated.builder.ts
- web/src/components/Popup/MiniGuides/JurorLevels.tsx
- web/src/components/Verdict/FinalDecision.tsx
- web/src/components/MarkdownRenderer.tsx
- kleros-sdk/src/types/reality-eth-lib.d.ts
- web/src/actions/vote/builders/shutter.builder.ts
- web/src/actions/fundAppeal/builders/gated.builder.ts
- web/src/components/ScrollTop.tsx
- web/src/pages/Profile/JurorCard/TopContent/index.tsx
- web/src/actions/fundAppeal/builders/argentinaConsumerProtection.builder.ts
- web/src/pages/Profile/JurorCard/Header.tsx
- web/src/pages/Home/CourtOverview/BarChart.tsx
- web/src/components/Verdict/DisputeTimeline.tsx
- web/src/pages/Profile/Stakes/CourtCard/Stake.tsx
- web/src/context/GraphqlBatcher.tsx
- web/src/actions/reveal/builders/shutter.builder.ts
- web/src/actions/reveal/builders/gatedShutter.builder.ts
- web/src/actions/reveal/builders/gated.builder.ts
- web/src/actions/fundAppeal/builders/shutter.builder.ts
- web/src/types/react-identicons.d.ts
- web/package.json
- web/src/utils/format.ts
- web/src/actions/fundAppeal/builders/gatedShutter.builder.ts
- web/src/hooks/useLocalStorage.ts
- web/src/actions/reveal/helpers/bruteForceChoice.test.ts
- web/src/pages/Home/TopJurors/Header/Rewards.tsx
- web/src/types/reality-eth-lib.d.ts
- web/src/pages/Profile/JurorCard/BottomContent/JurorRewards.tsx
- web/src/actions/vote/builders/gatedShutter.builder.ts
- web/src/utils/jurorRewardConfig.ts
- web/src/hooks/useStakingEventsByCourt.ts
- web/src/pages/Cases/CaseDetails/Evidence/SubmitEvidenceModal.tsx
- web/src/pages/Resolver/Parameters/Court/FeatureSelection/index.tsx
- web/src/pages/Cases/CaseDetails/Appeal/OptionCard.tsx
- web/src/components/DisputeFeatures/Features/GatedErc1155.tsx
- web/src/pages/Cases/CaseDetails/Voting/index.tsx
- web/src/actions/reveal/builders/argentinaConsumerProtection.builder.ts
- web/src/styles/responsiveSize.ts
- web/src/pages/Cases/CaseDetails/Voting/VotesDetails/index.tsx
- web/src/layout/Header/navbar/Explore.tsx
- web/src/pages/Settings/EmailConfirmation/index.tsx
- web/src/components/EnsureAuth.tsx
- web/src/layout/Footer/index.tsx
- web/src/pages/Home/TopJurors/Header/DesktopHeader.tsx
- web/src/hooks/useCoinPrice.tsx
- web/src/context/QueryClientProvider.tsx
- web/src/pages/Resolver/Parameters/NotablePersons/PersonFields.tsx
- web/src/hooks/useSessionStorage.ts
- web/src/components/GradientTokenIcons.tsx
🚧 Files skipped from review as they are similar to previous changes (9)
- web/src/pages/Resolver/Policy/index.tsx
- web/src/components/DisputePreview/DisputeContext.tsx
- web/src/hooks/queries/useHomePageBlockQuery.ts
- web/src/utils/crypto/hashJustification.ts
- web/src/pages/Home/CourtOverview/Chart.tsx
- web/tsconfig.json
- web/src/layout/Header/navbar/Menu/Settings/Notifications/FormContactDetails/index.tsx
- web/src/pages/Cases/CaseDetails/Appeal/Classic/Options/StageTwo.tsx
- web/src/components/Popup/Description/SwapSuccess.tsx
b7879e1 to
b431026
Compare
tractorss
left a comment
There was a problem hiding this comment.
looks great, left a couple comments 🙌
…and adjust import paths
|
|
@coderabbitai, also create an issue for this. It was added as a shim to prevent type errors. However, soon we will be migrating the UI to Tailwind, at which point we should also replace this library. Create an issue for replacing this library, adding both why and when it should happen. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain
I'll share the issue link once the script executes. 🏁 Script executed: Length of output: 48
It captures:
|


Part of #2277, but isolates the
webworkspace changes for easier review.PR-Codex overview
This PR focuses on various code improvements, including type adjustments, error handling enhancements, and updates to the styling and structure of components. It aims to improve type safety, maintainability, and overall code quality.
Detailed summary
staketype fromstringtobigintin several components.catchstatements.clientconfiguration.Addresstypes across components.useCoinPriceto accept an array of coin IDs.numberOfJurorsis handled to avoid type issues.Summary by CodeRabbit
New Features
Chores