Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): new-stake-flow #1775

Merged
merged 12 commits into from
Dec 10, 2024
Merged

feat(web): new-stake-flow #1775

merged 12 commits into from
Dec 10, 2024

Conversation

Harman-singh-waraich
Copy link
Contributor

@Harman-singh-waraich Harman-singh-waraich commented Dec 6, 2024

WIP


PR-Codex overview

This PR introduces several enhancements and bug fixes across various components in the application, including new functionality for handling juror stakes, improved error handling, and updates to dependencies.

Detailed summary

  • Added name to useCourtDetails hook.
  • Introduced refetchWithRetry utility for API calls.
  • Enhanced Spinner component with animation.
  • Updated StakePanel to remove unnecessary props.
  • Improved error handling in parseWagmiError.
  • Updated dependencies in package.json and yarn.lock.
  • Added TxnHash component for displaying transaction hashes.
  • Modified StakeWithdrawButton to handle popup states and errors more effectively.

The following files were skipped due to too many changes: yarn.lock

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced a new Spinner component for loading animations.
    • Added a TxnHash component to display transaction hashes with status indicators.
    • Implemented a Header component for displaying staking/withdrawal information.
    • Added a StakeWithdrawPopup component for managing withdrawal actions.
    • Introduced a stakeSteps component to manage staking process steps.
    • Added a custom hook usePnkData for fetching user PNK data.
  • Improvements

    • Enhanced the InputDisplay and StakeWithdrawButton components for better state management and user interaction.
    • Simplified the StakePanel component by reducing props and internal state.
    • Updated GraphQL queries to include additional fields for better data retrieval.
    • Enhanced the QuantityToSimulate component with additional styling flexibility.
  • Bug Fixes

    • Improved error handling and validation logic across various components.
  • Chores

    • Updated various dependency versions in package.json.
    • Modified TypeScript configuration to target ES2020.
    • Streamlined the build process in the Netlify configuration.
    • Introduced a retry mechanism with refetchWithRetry for improved data fetching reliability.

Copy link
Contributor

coderabbitai bot commented Dec 6, 2024

Walkthrough

The changes in this pull request encompass various modifications across multiple files within the web application. Key updates include the introduction of new components such as Header, StakeWithdrawPopup, and TxnHash, as well as enhancements to existing components like InputDisplay and StakeWithdrawButton. Additionally, the useCourtDetails hook now returns an expanded data set with a new name field. The TypeScript configuration has been updated to target ECMAScript 2020, and several dependencies in the package.json files have been updated or removed.

Changes

File Path Change Summary
web/src/components/ExternalLink.tsx Updated import statement for Link from react-router-dom.
web/src/hooks/queries/useCourtDetails.ts Added name field to the GraphQL query in useCourtDetails.
web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx Simplified props by removing isSending, setIsSending, and setIsPopupOpen; added debouncedAmount. Updated styling for input fields.
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx Updated IActionButton interface, removed isSending, added amount. Enhanced state management and error handling.
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/Header.tsx Introduced new Header component for displaying staking/withdrawing actions.
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx Added StakeWithdrawPopup component for modal functionality.
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/stakeSteps.tsx Introduced StakeSteps enum and getStakeSteps function for managing staking steps.
web/src/pages/Courts/CourtDetails/StakePanel/index.tsx Simplified StakePanel props and removed internal state management.
web/src/pages/Courts/CourtDetails/index.tsx Removed import for isUndefined; updated invocation of StakePanel.
web/src/utils/parseWagmiError.ts Updated error handling logic and types for parseWagmiError.
web/tsconfig.json Added "target": "ES2020" to compilerOptions.
web/package.json Updated several dependency versions.
web/src/components/Spinner.tsx Introduced new styled Spinner component with animation.
web/src/components/TxnHash.tsx Added new TxnHash component for displaying transaction hashes.
web/src/pages/Courts/CourtDetails/StakePanel/Simulator/QuantityToSimulate.tsx Added optional className prop to QuantityToSimulate.
package.json Removed kleros-app from workspaces.
web/netlify.toml Updated build command to remove @kleros/kleros-app.

Suggested labels

Type: Feature🗿, Type: Enhancement :sparkles:, Package: Web

Suggested reviewers

  • alcercu
  • kemuru

🐰 In the meadow, changes bloom,
New components chase away the gloom.
With hooks and styles, we refine,
A better flow, a design divine.
Hopping forward, we celebrate,
Code so bright, it feels like fate! 🌼✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e3da0f1 and 40fa153.

📒 Files selected for processing (1)
  • web/netlify.toml (0 hunks)
💤 Files with no reviewable changes (1)
  • web/netlify.toml

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Experiment)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

netlify bot commented Dec 6, 2024

Deploy Preview for kleros-v2-university ready!

Name Link
🔨 Latest commit 40fa153
🔍 Latest deploy log https://app.netlify.com/sites/kleros-v2-university/deploys/675871e66771b30008ad69b0
😎 Deploy Preview https://deploy-preview-1775--kleros-v2-university.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

netlify bot commented Dec 6, 2024

Deploy Preview for kleros-v2-testnet ready!

Name Link
🔨 Latest commit 40fa153
🔍 Latest deploy log https://app.netlify.com/sites/kleros-v2-testnet/deploys/675871e7f417d6000855603a
😎 Deploy Preview https://deploy-preview-1775--kleros-v2-testnet.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

netlify bot commented Dec 6, 2024

Deploy Preview for kleros-v2-testnet-devtools failed. Why did it fail? →

Name Link
🔨 Latest commit 40fa153
🔍 Latest deploy log https://app.netlify.com/sites/kleros-v2-testnet-devtools/deploys/675871e66b94640008cb71d3

Copy link

netlify bot commented Dec 6, 2024

Deploy Preview for kleros-v2-neo ready!

Name Link
🔨 Latest commit 40fa153
🔍 Latest deploy log https://app.netlify.com/sites/kleros-v2-neo/deploys/675871e69bd8540008ecf8a9
😎 Deploy Preview https://deploy-preview-1775--kleros-v2-neo.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (10)
web/src/utils/parseWagmiError.ts (1)

Line range hint 10-17: Consider adding type guard for safer type casting

The null check is a good addition. However, the type casting could be made safer with a type guard.

Consider this improvement:

 export const parseWagmiError = (error: UseSimulateContractReturnType["error"]) => {
   if (!error) return "";
-  const extError = error as ExtendedWagmiError;
+  
+  const isExtendedError = (err: any): err is ExtendedWagmiError => {
+    return 'message' in err;
+  };
+  
+  if (!isExtendedError(error)) return error?.toString() || "";
+  
+  const metaMessage = error?.metaMessages?.[0];
+  const shortMessage = error?.shortMessage;

   return metaMessage ?? shortMessage ?? error.message;
 };

This change:

  1. Adds runtime type checking
  2. Provides better TypeScript type inference
  3. Handles cases where the error might not match the expected structure
web/tsconfig.json (1)

69-71: Consider aligning lib array with target version

The lib array includes "ESNext.Array" which is more modern than your ES2020 target. This might lead to inconsistencies where TypeScript allows usage of features that won't be available in the compiled output. Consider using "ES2020.Array" to maintain consistency with your target.

    "target": "ES2020",
    "lib": [
-     "ESNext.Array"
+     "ES2020.Array"
    ],
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/stakeSteps.tsx (1)

93-275: Consider refactoring getStakeSteps to reduce code duplication

There is significant code duplication within the switch cases of the getStakeSteps function. Refactoring can improve maintainability and reduce potential errors.

web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx (1)

92-92: Simplify conditional rendering with optional chaining

You can improve readability by using optional chaining in the conditional rendering of CustomTimeline.

Apply this diff:

-{steps && steps.items && <CustomTimeline items={steps.items} />}
+{steps?.items && <CustomTimeline items={steps.items} />}
🧰 Tools
🪛 Biome (1.9.4)

[error] 92-92: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

web/src/pages/Courts/CourtDetails/StakePanel/SimulatorPopup/QuantityToSimulate.tsx (1)

53-53: LGTM! Consider using React.ComponentProps for className type

The addition of the className prop and its implementation is correct. For better type safety, consider using React.ComponentProps:

interface IQuantityToSimulate {
-  className?: string;
+  className?: React.ComponentProps<typeof Container>["className"];
}

Also applies to: 61-61, 92-92

web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/Header.tsx (1)

78-86: Consider memoizing StyledQuantityToSimulate props

The props object is recreated on every render. Consider using useMemo:

+ const quantityToSimulateProps = useMemo(() => ({
+   jurorCurrentEffectiveStake,
+   jurorCurrentSpecificStake,
+   isStaking: !isWithdraw,
+   amountToStake: Number(uncommify(amount)),
+ }), [jurorCurrentEffectiveStake, jurorCurrentSpecificStake, isWithdraw, amount]);

{isSuccess ? null : (
  <StyledQuantityToSimulate
-   {...{
-     jurorCurrentEffectiveStake,
-     jurorCurrentSpecificStake,
-     isStaking: !isWithdraw,
-     amountToStake: Number(uncommify(amount)),
-   }}
+   {...quantityToSimulateProps}
  />
)}
web/src/pages/Courts/CourtDetails/index.tsx (1)

Line range hint 141-173: Consider memoizing getCourtsPath results

The getCourtsPath function performs recursive traversal which could be expensive for deep court hierarchies.

+ const memoizedPaths = new Map<string, IItem[] | null>();

export const getCourtsPath = (
  node: CourtTreeQuery["court"],
  id: string | undefined,
  path: IItem[] = []
): IItem[] | null => {
+  const cacheKey = `${node?.id}-${id}`;
+  if (memoizedPaths.has(cacheKey)) {
+    return memoizedPaths.get(cacheKey) || null;
+  }

  if (!node || !id) return null;
  // ... rest of the function ...
+  const result = /* existing return value */;
+  memoizedPaths.set(cacheKey, result);
+  return result;
};
web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx (1)

Line range hint 99-109: Consider extracting error validation logic

The error handling logic in the useEffect hook could be made more maintainable by extracting it into a separate validation function.

Consider refactoring like this:

+ const validateAmount = (
+   parsedAmount: bigint,
+   balance: bigint,
+   jurorBalance: [unknown, unknown, bigint] | undefined,
+   isStaking: boolean
+ ): string | undefined => {
+   if (parsedAmount > 0n && balance === 0n && isStaking) {
+     return "You need a non-zero PNK balance to stake";
+   }
+   if (isStaking && balance && parsedAmount > balance) {
+     return "Insufficient balance to stake this amount";
+   }
+   if (!isStaking && jurorBalance && parsedAmount > jurorBalance[2]) {
+     return "Insufficient staked amount to withdraw this amount";
+   }
+   return undefined;
+ };

  useEffect(() => {
-   if (parsedAmount > 0n && balance === 0n && isStaking) {
-     setErrorMsg("You need a non-zero PNK balance to stake");
-   } else if (isStaking && balance && parsedAmount > balance) {
-     setErrorMsg("Insufficient balance to stake this amount");
-   } else if (!isStaking && jurorBalance && parsedAmount > jurorBalance[2]) {
-     setErrorMsg("Insufficient staked amount to withdraw this amount");
-   } else {
-     setErrorMsg(undefined);
-   }
+   setErrorMsg(validateAmount(parsedAmount, balance ?? 0n, jurorBalance, isStaking));
  }, [parsedAmount, isStaking, balance, jurorBalance]);
web/src/hooks/queries/useCourtDetails.ts (1)

26-26: LGTM! Consider documenting the field usage.

The addition of the name field to the court query is clean and well-placed. This change supports the new staking flow by making the court name available to dependent components.

Consider adding a comment above the query to document which components rely on this field, making it easier to track dependencies.

web/src/pages/Courts/CourtDetails/StakePanel/index.tsx (1)

56-56: Consider making courtName required and moving the default value.

The default value for courtName should ideally be handled at the parent component level rather than in the prop definition. This makes the data flow more explicit and maintainable.

-const StakePanel: React.FC<{ courtName: string }> = ({ courtName = "General Court" }) => {
+const StakePanel: React.FC<{ courtName: string }> = ({ courtName }) => {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0e582ae and 4bf724d.

⛔ Files ignored due to path filters (2)
  • web/src/assets/svgs/icons/close-circle.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (13)
  • web/package.json (1 hunks)
  • web/src/components/ExternalLink.tsx (1 hunks)
  • web/src/hooks/queries/useCourtDetails.ts (1 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx (3 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/SimulatorPopup/QuantityToSimulate.tsx (4 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (5 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/Header.tsx (1 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx (1 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/stakeSteps.tsx (1 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/index.tsx (3 hunks)
  • web/src/pages/Courts/CourtDetails/index.tsx (2 hunks)
  • web/src/utils/parseWagmiError.ts (1 hunks)
  • web/tsconfig.json (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • web/src/components/ExternalLink.tsx
  • web/package.json
🧰 Additional context used
🪛 Biome (1.9.4)
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx

[error] 92-92: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (9)
web/src/utils/parseWagmiError.ts (1)

1-1: Verify the impact of wagmi type changes across the codebase

The migration from SimulateContractErrorType to UseSimulateContractReturnType["error"] looks correct. However, we should verify that this type change doesn't affect other components using this utility.

Also applies to: 3-3

✅ Verification successful

Type change from SimulateContractErrorType to UseSimulateContractReturnType is safe

The verification shows that:

  1. No remaining usage of SimulateContractErrorType exists in the codebase
  2. All files using parseWagmiError are consuming it as an error parsing utility that returns a string message
  3. The type change is internal to the parseWagmiError implementation and doesn't affect the function's interface or return type
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining usage of SimulateContractErrorType and find all files using parseWagmiError

# Check for any remaining SimulateContractErrorType imports
echo "Checking for any remaining SimulateContractErrorType imports..."
rg -l "SimulateContractErrorType" "web/src"

# Find all files using parseWagmiError to verify they handle the new type correctly
echo "Finding all files using parseWagmiError..."
rg -l "parseWagmiError" "web/src"

Length of output: 582


Script:

#!/bin/bash
# Let's examine the usage context in the files that use parseWagmiError

echo "Checking parseWagmiError usage in wrapWithToast.ts..."
rg -A 5 "parseWagmiError" "web/src/utils/wrapWithToast.ts"

echo "\nChecking parseWagmiError usage in SubmitDisputeButton.tsx..."
rg -A 5 "parseWagmiError" "web/src/pages/Resolver/NavigationButtons/SubmitDisputeButton.tsx"

echo "\nChecking parseWagmiError usage in StakeWithdrawButton.tsx..."
rg -A 5 "parseWagmiError" "web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx"

echo "\nChecking parseWagmiError usage in stakeSteps.tsx..."
rg -A 5 "parseWagmiError" "web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/stakeSteps.tsx"

Length of output: 3122

web/tsconfig.json (1)

68-68: Verify browser compatibility requirements

Setting the TypeScript target to ES2020 enables modern JavaScript features like optional chaining, nullish coalescing, and dynamic imports. While these features are well-supported in modern browsers, please ensure this aligns with your browser compatibility requirements.

Run this script to check the project's browser targets:

✅ Verification successful

Let me gather more information about the browser compatibility requirements by checking the package.json and any build configuration files.


Let me check for any Vite configuration in the repository since it's a common build tool for modern web applications.


Based on the gathered information, I can now provide the final response:

ES2020 target is appropriate for this project

The codebase extensively uses ES2020 features like optional chaining and nullish coalescing operators across multiple TypeScript files. The project uses Vite as the build tool (found vite.config.js) which provides modern browser support by default. Additionally, the presence of polyfills in devDependencies (crypto-browserify, path-browserify, etc.) indicates proper handling of browser compatibility.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check browser targets configuration

# Check for browserslist config in package.json or .browserslistrc
echo "Checking browserslist configuration..."
if [ -f ".browserslistrc" ]; then
    cat .browserslistrc
else
    cat package.json | jq -r '.browserslist'
fi

# Check for any transpilation configuration
echo -e "\nChecking for babel configuration..."
for file in .babelrc .babelrc.js babel.config.js; do
    if [ -f "$file" ]; then
        cat "$file"
    fi
done

Length of output: 477


Script:

#!/bin/bash
# Check package.json for build tools and their configurations
echo "Checking package.json for build configuration..."
cat package.json | jq -r '.dependencies, .devDependencies'

# Check for any webpack or vite configuration
echo -e "\nChecking for build tool configurations..."
for file in vite.config.ts webpack.config.js; do
    if [ -f "$file" ]; then
        echo "Found $file:"
        cat "$file"
    fi
done

# Check if this is part of a monorepo by looking at parent package.json
echo -e "\nChecking parent package.json if exists..."
if [ -f "../package.json" ]; then
    cat "../package.json" | jq -r '.dependencies, .devDependencies'
fi

Length of output: 919


Script:

#!/bin/bash
# Search for vite config files recursively
echo "Searching for vite configuration files..."
fd -e ts -e js -e mjs "vite.config" 

# Check for any esbuild configuration
echo -e "\nSearching for esbuild configuration..."
fd -e ts -e js -e mjs "esbuild.config"

# Look for any build-related configuration in package.json
echo -e "\nChecking build scripts in package.json..."
cat package.json | jq -r '.scripts'

# Check for any TypeScript files using modern features
echo -e "\nChecking usage of ES2020 features..."
rg -l "(\?\.)|\?\?" --type ts

Length of output: 9175

web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (1)

212-212: ⚠️ Potential issue

Incorrect condition in handleClick function

The condition if (ActionType.allowance && isAllowance && increaseAllowanceConfig && publicClient) uses ActionType.allowance, which is always truthy as a string constant, leading to unintended behavior. You likely meant to check only isAllowance.

Apply this diff to fix the condition:

-if (ActionType.allowance && isAllowance && increaseAllowanceConfig && publicClient) {
+if (isAllowance && increaseAllowanceConfig && publicClient) {

Likely invalid or redundant comment.

web/src/pages/Courts/CourtDetails/index.tsx (1)

120-120: Verify StakePanel works correctly without id prop

The id prop has been removed from StakePanel. Let's verify this change doesn't break functionality.

✅ Verification successful

StakePanel component correctly refactored to use only courtName prop

Looking at the StakePanel implementation, it's been properly refactored to only use the courtName prop, and it doesn't require the id prop for its functionality. The component handles staking/withdrawal actions using only the court name for display purposes, while other required data is managed through its child components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if StakePanel uses useParams internally
rg -A 5 "useParams.*id.*StakePanel" 

# Check for any direct id prop usage in StakePanel
ast-grep --pattern 'const StakePanel = ({ id }) => { $$$ }'

Length of output: 99


Script:

#!/bin/bash
# Let's check StakePanel component implementation and its props
fd "StakePanel" --type f --exec rg -A 10 "StakePanel"

# Also check for any usage of useParams in StakePanel
fd "StakePanel" --type f --exec rg "useParams" {}

Length of output: 101


Script:

#!/bin/bash
# Search for StakePanel component in the web/src directory
rg -l "StakePanel" web/src/

# Once we find the file, let's examine its implementation
rg -A 20 "export.*StakePanel" web/src/

Length of output: 249


Script:

#!/bin/bash
# Let's examine the StakePanel component implementation
cat web/src/pages/Courts/CourtDetails/StakePanel/index.tsx

# Also check for any useParams usage in this file
rg "useParams" web/src/pages/Courts/CourtDetails/StakePanel/index.tsx

Length of output: 2321

web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx (3)

15-16: LGTM: Styling improvements enhance UI consistency

The added border-radius styling and landscape-specific adjustments improve the visual cohesion of the input field and button components.

Also applies to: 23-25, 68-68


144-148: LGTM: Clean button integration

The StakeWithdrawButton props have been appropriately simplified while maintaining necessary functionality and error state handling.


71-78: Verify state management after props removal

The removal of isSending, setIsSending, and setIsPopupOpen props suggests that state management has been moved up the component tree. This is a good practice, but we should verify the state handling in parent components.

✅ Verification successful

Let me gather more information about the state management by checking the implementation of StakePanel and its interaction with InputDisplay.


Props removal is correct and state is properly managed

The removed props (isSending, setIsSending, setIsPopupOpen) are now correctly managed in the StakeWithdrawButton component, which handles its own popup state. The InputDisplay component has been simplified to only manage amount-related props, following React's best practices of lifting state up and keeping components focused. The state management restructuring is properly implemented.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for state management in parent components
ast-grep --pattern 'const [setIsSending, setIsPopupOpen] = useState<boolean>'

# Look for StakePanel component that might be managing this state
rg -A 10 "const StakePanel.*React\.FC" 

Length of output: 1162


Script:

#!/bin/bash
# Check StakePanel implementation and its usage of InputDisplay
rg -l "InputDisplay" web/src/pages/Courts/CourtDetails/StakePanel/

# Get the content of StakePanel index file
cat web/src/pages/Courts/CourtDetails/StakePanel/index.tsx

# Look for any popup or sending state management in the StakePanel directory
rg "isSending|setIsSending|isPopupOpen|setIsPopupOpen" web/src/pages/Courts/CourtDetails/StakePanel/

Length of output: 3382

web/src/pages/Courts/CourtDetails/StakePanel/index.tsx (2)

57-60: LGTM! Clean state management.

The state management is well-organized with clear separation of concerns:

  • amount for input value
  • isActive for tab selection
  • action for operation type

79-79: Consider type safety for amount parsing.

The amount value is passed directly to InputDisplay and then parsed using uncommify for SimulatorPopup. Consider adding validation or error handling for the amount parsing.

Let's check how uncommify handles invalid inputs:

✅ Verification successful

Let me check how the amount is validated in InputDisplay component and useParsedAmount hook.


Let me check the implementation of the Input component being used and any validation logic in the component.


Input validation is properly implemented

The code already has comprehensive validation and error handling for the amount:

  1. The InputDisplay component implements several validation checks:

    • Validates non-zero balance requirement
    • Checks for insufficient balance when staking
    • Validates withdrawal amounts against staked balance
    • Shows appropriate error messages through setErrorMsg
  2. The StakeWithdrawButton component adds additional validations:

    • Validates against minimum stake requirements
    • Handles and displays Wagmi errors
    • Disables the button when amount is invalid

The type assertion as \${number}`onuncommifyresult is safe sinceuncommify` only removes commas from the string, and subsequent validations ensure proper numeric handling.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for uncommify implementation and tests
rg -A 5 "uncommify" --type ts

Length of output: 4203


Script:

#!/bin/bash
# Search for useParsedAmount implementation
ast-grep --pattern 'const useParsedAmount = $_'

# Search for amount validation in InputDisplay
rg -A 10 "const InputDisplay" --type ts

Length of output: 1299


Script:

#!/bin/bash
# Search for Input component implementation
rg -A 15 "const Input.*= .*{" --type ts

# Search for validation logic in InputDisplay
rg -A 20 "setErrorMsg" --type ts

Length of output: 10860

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (3)
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (3)

44-50: Consider adding amount validation in the interface

The amount prop is typed as string while parsedAmount is bigint. Consider adding validation or using a more type-safe approach to ensure amount string always parses to a valid bigint.

interface IActionButton {
  amount: string;
  parsedAmount: bigint;
+ // Add validation to ensure amount is always a valid number string
+ validate?: (amount: string) => boolean;
  action: ActionType;
  setAmount: (arg0: string) => void;
  setErrorMsg: (msg: string) => void;
}

263-268: Enhance error handling with error boundaries

The error handling in useEffect could be more robust by implementing React Error Boundaries for catching and handling render-time errors.

Consider implementing an ErrorBoundary component:

class StakeErrorBoundary extends React.Component {
  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    // Log error to monitoring service
    // Show user-friendly error message
  }
  
  render() {
    return this.props.children;
  }
}

302-313: Enhance accessibility for stake/withdraw actions

The button component could benefit from improved accessibility attributes.

<Button
  text={isStaking ? "Stake" : "Withdraw"}
  isLoading={isPopupOpen || isSimulatingAllowance || isSimulatingSetStake}
  disabled={isDisabled || isSimulatingAllowance || isSimulatingSetStake}
+ aria-busy={isPopupOpen || isSimulatingAllowance || isSimulatingSetStake}
+ aria-label={`${isStaking ? "Stake" : "Withdraw"} tokens`}
  onClick={handleClick}
/>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 4bf724d and d5c9c27.

📒 Files selected for processing (3)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (5 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/Header.tsx (1 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/Header.tsx
🔇 Additional comments (1)
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (1)

Line range hint 1-316: Verify contract interaction patterns across the codebase

Let's verify that similar contract interaction patterns are consistently implemented across the codebase.

✅ Verification successful

Contract interaction patterns are consistently implemented

The verification shows that the contract interaction patterns in StakeWithdrawButton.tsx follow the established patterns across the codebase:

  • Error handling consistently uses the parseWagmiError utility across all contract interactions
  • Transaction confirmation logic using waitForTransactionReceipt with 2 confirmations is standardized
  • The component follows the same simulate-then-write pattern seen in other components using wagmi hooks

The implementation aligns with the codebase's best practices for blockchain interactions, error handling, and transaction management.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar contract interaction patterns
# Look for potential inconsistencies in error handling and transaction flow

# Check for other components using similar wagmi hooks
rg -l "useSimulate.*Contract|useWrite.*Contract" --type typescript

# Check for consistent error handling patterns
rg "parseWagmiError" --type typescript -C 2

# Look for potential transaction confirmation patterns
rg "waitForTransactionReceipt" --type typescript -C 2

Length of output: 271


Script:

#!/bin/bash
# Search for similar contract interaction patterns without file type restriction
# Look for potential inconsistencies in error handling and transaction flow

# Check for other components using similar wagmi hooks
rg -l "useSimulate|useWrite"

# Check for consistent error handling patterns
rg "parseWagmiError" -C 2

# Look for potential transaction confirmation patterns
rg "waitForTransactionReceipt" -C 2

Length of output: 9836

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (7)
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx (2)

80-90: Avoid Using !important in Styled Components

The use of !important in CSS can make the code harder to maintain and override unintentionally. In the StyledButton component, several styles are marked with !important.

Consider removing the !important declarations and adjusting the CSS specificity or the order of the styles to achieve the desired effect.


122-129: Improve Accessibility by Announcing Delays to Screen Readers

The informational message about potential delays is only visually displayed. Users relying on screen readers might miss this important information.

Consider adding aria-live attributes to make sure that assistive technologies announce this message.

{phase !== Phases.staking ? (
  <InfoContainer>
    <Divider />
    <StyledInfoCard
+     aria-live="polite"
      msg={`The ${action === ActionType.stake ? "stake" : "withdraw"} might be delayed by ~1 hr.`}
    />
  </InfoContainer>
) : null}
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/stakeSteps.tsx (1)

73-126: Avoid Unnecessary Nested Functions

The party function inside createStakeSteps is redefined every time the function is called, which can affect performance.

Consider moving the party function outside or memoizing it if necessary.

web/src/components/TxnHash.tsx (2)

25-27: Avoid Unnecessary Use of useMemo

The transactionExplorerLink doesn't have computational complexity that warrants the use of useMemo.

Remove useMemo and compute the value directly to simplify the code.

-const transactionExplorerLink = useMemo(() => {
-  return `${getChain(DEFAULT_CHAIN)?.blockExplorers?.default.url}/tx/${hash}`;
-}, [hash]);
+const transactionExplorerLink = `${getChain(DEFAULT_CHAIN)?.blockExplorers?.default.url}/tx/${hash}`;

33-35: Improve Hash Display for Better Readability

The transaction hash is truncated arbitrarily, which might not be optimal for user recognition.

Consider using a utility function to format the hash consistently.

<span>{truncateHash(hash)}</span>

Where truncateHash is:

function truncateHash(hash: string): string {
  return `${hash.substring(0, 6)}...${hash.substring(hash.length - 4)}`;
}
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (2)

52-59: Initialize State with Proper Types

The popupStepsState is initialized without specifying its type, which could lead to type inconsistencies.

Explicitly define the state type when using useState.

-const [popupStepsState, setPopupStepsState] = useState<[_TimelineItem1, ..._TimelineItem1[]]>();
+const [popupStepsState, setPopupStepsState] = useState<[_TimelineItem1, ..._TimelineItem1[]] | undefined>();

250-274: Ensure Correct Logical Operators in Conditions

In the isDisabled calculation, the condition parsedAmount == 0n should use strict equality.

Use === instead of == for strict comparison.

-if (parsedAmount == 0n || /* other conditions */)
+if (parsedAmount === 0n || /* other conditions */)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d5c9c27 and bfcb020.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (7)
  • web/package.json (1 hunks)
  • web/src/components/Spinner.tsx (1 hunks)
  • web/src/components/TxnHash.tsx (1 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (5 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/Header.tsx (1 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx (1 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/stakeSteps.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • web/src/components/Spinner.tsx
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/Header.tsx
🔇 Additional comments (5)
web/package.json (2)

84-84: Verify UI library compatibility with new stake flow components

The upgrade to ui-components-library ^2.16.0 should be verified against the new stake flow components mentioned in the PR objectives.

✅ Verification successful

UI library compatibility verified with stake flow components

The stake-related components are using basic UI components (Button, CustomTimeline, _TimelineItem1, StateProp) from the library that are stable across versions. The recent changes in the codebase only involve simplifying the timeline state management structure, which is a refactoring that doesn't indicate any compatibility issues with the UI library upgrade.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for UI component usage and compatibility

# Find imports from ui-components-library in stake-related components
rg -l "@kleros/ui-components-library" | grep -i "stake"

# Check the changelog for relevant updates
curl -s "https://raw.githubusercontent.com/kleros/ui-components-library/main/CHANGELOG.md" | grep -A 10 "2.16.0"

Length of output: 524


Script:

#!/bin/bash
# Let's examine the actual UI component imports in stake-related files
for file in web/src/pages/Courts/StakeMaintenanceButton/ExecuteDelayedStakeButton.tsx \
           web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx \
           web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/stakeSteps.tsx \
           web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx \
           web/src/pages/Courts/StakeMaintenanceButton/PassPhaseButton.tsx; do
    echo "=== $file ==="
    rg "import.*@kleros/ui-components-library" "$file" -A 2
done

# Let's also check the git history to see what UI components were modified or added
git diff HEAD~1 -- web/src/pages/Courts/StakeMaintenanceButton/ExecuteDelayedStakeButton.tsx \
                   web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx \
                   web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/stakeSteps.tsx \
                   web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx \
                   web/src/pages/Courts/StakeMaintenanceButton/PassPhaseButton.tsx

Length of output: 10921


89-89: Verify implications of react-query downgrade

The downgrade from ^5.61.0 to ^5.56.2 could have potential impacts on query handling and might introduce compatibility issues.

✅ Verification successful

Let me gather more information about the usage of react-query in the codebase to understand potential impacts.


Let me check the specific react-query features being used in the codebase to ensure they're compatible with version 5.56.2.


Based on the gathered information, I can now provide the final response:

React Query downgrade appears safe to proceed

The downgrade from ^5.61.0 to ^5.56.2 appears to be safe because:

  • No security vulnerabilities were found for this package
  • The codebase uses basic query features (useQuery) with standard configurations
  • Peer dependency requirements are compatible (React ^18 || ^19)
  • The usage patterns found in the codebase (staleTime, queryKey, enabled flags) are stable features available in both versions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for breaking changes and security advisories

# Check for breaking changes in changelog
curl -s https://raw.githubusercontent.com/TanStack/query/main/CHANGELOG.md | grep -A 10 "5.56.2"

# Check for security advisories
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: NPM, package: "@tanstack/react-query") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

# Check for peer dependency conflicts
npm info "@tanstack/[email protected]" peerDependencies

Length of output: 531


Script:

#!/bin/bash
# Search for react-query hooks and features usage
rg -l "@tanstack/react-query" --type ts --type tsx

# Find specific query features usage that might be affected by version changes
ast-grep --pattern 'useQuery($$$)' 
ast-grep --pattern 'useMutation($$$)'
ast-grep --pattern 'useInfiniteQuery($$$)'

Length of output: 7237


Script:

#!/bin/bash
# Check package.json for other tanstack dependencies
rg "@tanstack" web/package.json

# Check imports to verify query features
rg "from '@tanstack/react-query'" --type ts

Length of output: 123

web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/stakeSteps.tsx (1)

10-13: ⚠️ Potential issue

Define variant as a Strongly Typed Enum or Union Type

The variant prop in TxnLabel styled component is typed as string, which could lead to invalid values and runtime errors.

Define variant as a union of allowed string literals to ensure type safety.

-const TxnLabel = styled.label<{ variant: string }>`
+const TxnLabel = styled.label<{ variant: "success" | "error" | "pending" }>`

Likely invalid or redundant comment.

web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (2)

135-200: ⚠️ Potential issue

Handle Async Operations with Care to Prevent Memory Leaks

The handleStake function involves async operations but does not handle component unmount scenarios.

This comment is similar to a previous one about handling component unmount during async operations.


242-248: ⚠️ Potential issue

Avoid State Updates on Unmounted Components

Component state is being updated in useEffect, but there is no cleanup function to prevent updating state after unmount.

Implement a cleanup function to set a flag when the component is unmounted.

useEffect(() => {
+ let isMounted = true;
+ return () => {
+   isMounted = false;
+ };
}, [/* dependencies */]);

// Then, before setting state:
if (isMounted) {
  setErrorMsg(parseWagmiError(setStakeError || allowanceError));
}

Likely invalid or redundant comment.

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 9, 2024
@Harman-singh-waraich Harman-singh-waraich changed the title feat(web): new-stake-flow-v1 feat(web): new-stake-flow Dec 9, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (8)
web/src/pages/Courts/CourtDetails/StakePanel/index.tsx (1)

56-57: Consider adding amount validation.

The amount state could benefit from validation to ensure valid numeric input and prevent potential issues with the uncommify function.

 const StakePanel: React.FC<{ courtName: string }> = ({ courtName = "General Court" }) => {
   const [amount, setAmount] = useState("");
+  const handleAmountChange = (value: string) => {
+    // Allow only numbers and commas
+    if (!/^[\d,]*$/.test(value)) return;
+    setAmount(value);
+  };

Then update the InputDisplay props:

-  <InputDisplay {...{ action, amount, setAmount }} />
+  <InputDisplay {...{ action, amount, setAmount: handleAmountChange }} />
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (5)

56-58: Consider consolidating popup-related state

The popup states (isPopupOpen, isSuccess, popupStepsState) could be consolidated into a single state object for better state management.

-const [isPopupOpen, setIsPopupOpen] = useState(false);
-const [isSuccess, setIsSuccess] = useState(false);
-const [popupStepsState, setPopupStepsState] = useState<[_TimelineItem1, ..._TimelineItem1[]]>();
+const [popupState, setPopupState] = useState<{
+  isOpen: boolean;
+  isSuccess: boolean;
+  steps?: [_TimelineItem1, ..._TimelineItem1[]];
+}>({
+  isOpen: false,
+  isSuccess: false,
+});

107-109: Consider extracting complex enabled conditions

The simulation enabled conditions are complex and could benefit from being extracted into a separate function for better readability and maintainability.

+const canSimulateAllowance = (params: {
+  isAllowance: boolean;
+  targetStake?: bigint;
+  allowance?: bigint;
+  balance?: bigint;
+  isPopupOpen: boolean;
+}) => {
+  const { isAllowance, targetStake, allowance, balance, isPopupOpen } = params;
+  return isAllowance && 
+    !isUndefined(targetStake) && 
+    !isUndefined(allowance) && 
+    !isUndefined(balance) && 
+    !isPopupOpen;
+};

 enabled:
-  isAllowance && !isUndefined(targetStake) && !isUndefined(allowance) && !isUndefined(balance) && !isPopupOpen,
+  canSimulateAllowance({ isAllowance, targetStake, allowance, balance, isPopupOpen }),

228-228: Improve error message clarity

The generic error message "Something went wrong. Please restart the process." could be more specific about the nature of the error.

-new Error("Something went wrong. Please restart the process.")
+new Error("Failed to simulate stake after approval. Please try the process again.")

255-261: Consider splitting error handling effect

The effect handles multiple error conditions. Consider splitting it into separate effects for better separation of concerns.

+useEffect(() => {
+  if (isPopupOpen) return;
+  if (setStakeError || allowanceError) {
+    setErrorMsg(parseWagmiError(setStakeError || allowanceError));
+  }
+}, [setStakeError, allowanceError, setErrorMsg, isPopupOpen]);
+
+useEffect(() => {
+  if (isPopupOpen) return;
+  if (targetStake !== 0n && courtDetails && targetStake < BigInt(courtDetails.court?.minStake)) {
+    setErrorMsg(`Min Stake in court is: ${formatETH(courtDetails?.court?.minStake)}`);
+  }
+}, [targetStake, courtDetails, setErrorMsg, isPopupOpen]);

305-305: Consider explicit prop passing

Instead of spreading props to StakeWithdrawPopup, consider passing them explicitly for better maintainability and type safety.

-{isPopupOpen && <StakeWithdrawPopup {...{ action, closePopup, amount, steps: popupStepsState, isSuccess }} />}
+{isPopupOpen && (
+  <StakeWithdrawPopup
+    action={action}
+    closePopup={closePopup}
+    amount={amount}
+    steps={popupStepsState}
+    isSuccess={isSuccess}
+  />
+)}
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/stakeSteps.tsx (2)

39-39: Enhance type safety by defining a specific type for transaction hashes

Currently, the hash, approvalHash, and stakeHash parameters are typed as `0x${string}` | undefined. Defining a specific type alias for transaction hashes can improve readability and maintainability.

You can create a type alias and update the function signatures:

type TxnHash = `0x${string}` | undefined;

// Update in createApprovalSteps
hash: TxnHash,

// Update in createStakeSteps
approvalHash: TxnHash,
stakeHash: TxnHash,

// Update in getStakeSteps
approvalHash?: TxnHash,
stakeHash?: TxnHash,

Also applies to: 79-79, 132-134


136-160: Handle unexpected stepType values explicitly

In the getStakeSteps function, the default case in your switch statement returns a "refused" state. To improve code robustness, consider handling unexpected stepType values more explicitly. You could log a warning or throw an error to help with debugging.

For example:

default:
-  return createStakeSteps(theme, "refused", "active", amount, approvalHash, stakeHash, error, false);
+  console.warn(`Unhandled stepType: ${stepType}`);
+  throw new Error(`Unhandled stepType: ${stepType}`);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between bfcb020 and 64da137.

📒 Files selected for processing (6)
  • web/src/pages/Courts/CourtDetails/StakePanel/Simulator/QuantityToSimulate.tsx (4 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (5 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/Header.tsx (1 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/stakeSteps.tsx (1 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/index.tsx (3 hunks)
  • web/src/pages/Courts/CourtDetails/index.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • web/src/pages/Courts/CourtDetails/index.tsx
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/Header.tsx
🧰 Additional context used
📓 Learnings (3)
web/src/pages/Courts/CourtDetails/StakePanel/index.tsx (1)
Learnt from: Harman-singh-waraich
PR: kleros/kleros-v2#1775
File: web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx:0-0
Timestamp: 2024-12-09T12:36:59.441Z
Learning: In the `StakeWithdrawButton` component, the transaction flow logic is tightly linked to component updates, so extracting it into a custom hook does not provide significant benefits.
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/stakeSteps.tsx (1)
Learnt from: Harman-singh-waraich
PR: kleros/kleros-v2#1775
File: web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx:0-0
Timestamp: 2024-12-09T12:36:59.441Z
Learning: In the `StakeWithdrawButton` component, the transaction flow logic is tightly linked to component updates, so extracting it into a custom hook does not provide significant benefits.
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (1)
Learnt from: Harman-singh-waraich
PR: kleros/kleros-v2#1775
File: web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx:0-0
Timestamp: 2024-12-09T12:36:59.441Z
Learning: In the `StakeWithdrawButton` component, the transaction flow logic is tightly linked to component updates, so extracting it into a custom hook does not provide significant benefits.
🔇 Additional comments (8)
web/src/pages/Courts/CourtDetails/StakePanel/Simulator/QuantityToSimulate.tsx (2)

53-53: LGTM! Well-implemented className prop.

The addition of the optional className prop follows React best practices:

  • Proper TypeScript interface definition
  • Correct props destructuring
  • Proper spreading to the styled Container component

This change enhances the component's styling flexibility while maintaining type safety.

Also applies to: 61-61, 92-92


17-17: Verify the centered layout alignment.

The addition of justify-content: center will center-align all flex items. Please ensure this aligns with the design requirements and doesn't affect the layout in different viewport sizes.

✅ Verification successful

Based on the search results, I can generate the final response as I have enough context about the component's usage:

Center alignment is appropriate for this component's usage contexts

The justify-content: center style is suitable as the component is used in two specific contexts:

  • As a direct child in the Simulator's layout (StakePanel/Simulator/index.tsx)
  • Within a styled wrapper in the popup header (StakeWithdrawPopup/Header.tsx) where it has a specific margin-top

In both cases, the centering aligns with typical form/popup layouts and won't cause layout issues.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the component is used in different contexts where centering might affect the layout

# Search for QuantityToSimulate usage
rg -l "QuantityToSimulate" | while read -r file; do
  echo "=== $file ==="
  rg -A 5 "QuantityToSimulate" "$file"
done

Length of output: 2412

web/src/pages/Courts/CourtDetails/StakePanel/index.tsx (3)

4-4: LGTM! Import changes are appropriate.

The added imports for uncommify and landscapeStyle are necessary for the component's functionality and responsive design.

Also applies to: 6-6


78-82: LGTM! Clean implementation with good separation of concerns.

The component maintains a clear structure with proper state management and logical UI separation.


55-55: Verify the impact of removing the id prop.

The removal of the id prop might affect court identification in other parts of the application.

✅ Verification successful

Let me try a different search strategy to verify the impact of removing the id prop.


Removal of id prop is safe

The verification shows that:

  • StakePanel is only used in CourtDetails component and receives just the courtName prop
  • The component itself only uses courtName for display purposes
  • No court ID references or dependencies exist within the StakePanel component
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usages of the court id in related components and potential breaking changes

# Search for references to court id in related components
echo "Checking for court id usage in related components..."
rg -l "courtId|id.*court" "web/src/pages/Courts"

# Check for any components passing id to StakePanel
echo "Checking for components passing id to StakePanel..."
ast-grep --pattern 'StakePanel $$$id={$_}$$$'

Length of output: 324


Script:

#!/bin/bash
# Search for StakePanel usage patterns
echo "Checking StakePanel usage..."
rg -A 2 "<StakePanel" web/src/pages/Courts

# Search for the component definition history
echo "Checking component history..."
rg -A 5 "StakePanel.*FC.*=" web/src/pages/Courts

# Check for any court id related state or props in the same file
echo "Checking court id usage in StakePanel..."
rg "id|court" web/src/pages/Courts/CourtDetails/StakePanel/index.tsx

Length of output: 1406

web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (2)

45-50: LGTM! Interface changes align with component responsibilities

The IActionButton interface has been streamlined by removing isSending and setIsSending props while adding amount and parsedAmount. This change better reflects the component's actual needs.


52-52: Verify component usage across the codebase

Let's verify that all usages of StakeWithdrawButton have been updated to provide the required props according to the interface changes.

✅ Verification successful

Component usage is properly aligned with interface

The verification shows that StakeWithdrawButton is used correctly in InputDisplay.tsx, which is its only direct usage in the codebase. All required props (amount, parsedAmount, action, setAmount, setErrorMsg) are being passed correctly through object spread. Other files only import the ActionType type and don't directly use the component.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for StakeWithdrawButton usage
ast-grep --pattern 'StakeWithdrawButton $$$'

Length of output: 46


Script:

#!/bin/bash
# Search for StakeWithdrawButton usage with ripgrep for better coverage
rg "StakeWithdrawButton" -l

Length of output: 362


Script:

#!/bin/bash
# Search for actual component usage patterns
rg "<StakeWithdrawButton" -A 3

Length of output: 387


Script:

#!/bin/bash
# Look for the file itself to understand its exports
rg -l "export.*StakeWithdrawButton"

Length of output: 106


Script:

#!/bin/bash
# Let's check the full context of the component usage in InputDisplay.tsx
rg -A 10 "<StakeWithdrawButton" "web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx"

Length of output: 379


Script:

#!/bin/bash
# Let's also check if there are any other indirect usages through imports/exports
rg "import.*StakeWithdrawButton" --type ts

Length of output: 541

web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/stakeSteps.tsx (1)

107-107: Ensure safe access to error properties

The error parameter is used without sufficient null checking, which might lead to runtime errors if error is undefined. In lines 107 and 118, accessing error?.message assumes that error exists.

This issue was previously noted in past review comments. Please ensure you check if error is defined before accessing its properties. Since you're already using optional chaining (error?.message), this may suffice, but double-check to prevent any potential exceptions.

Also applies to: 118-118

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
package.json (1)

39-40: Ensure consistent versioning strategy across dependencies

The Parcel-related packages are pinned to exact versions while TypeScript uses semver range. Consider pinning the TypeScript version for consistency and to prevent potential compatibility issues.

-    "typescript": "^5.7.2"
+    "typescript": "5.7.2"

Also applies to: 51-51

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 64da137 and bf8256b.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (4)
  • .gitignore (1 hunks)
  • kleros-app/package.json (2 hunks)
  • kleros-app/vite.config.js (0 hunks)
  • package.json (2 hunks)
💤 Files with no reviewable changes (1)
  • kleros-app/vite.config.js
🔇 Additional comments (3)
kleros-app/package.json (1)

24-24: Verify Parcel build configuration

The transition to Parcel looks good, but ensure there's a proper Parcel configuration file (.parcelrc) to replace the removed Vite config, especially for TypeScript and module settings.

Also applies to: 27-28

.gitignore (2)

205-207: LGTM! Comprehensive ignore patterns added

The additions properly handle build artifacts and generated files for Parcel, subgraph, and Netlify deployments.


Line range hint 1-207: Verify complete removal of Vite configuration

Please ensure all Vite-related configurations and references have been removed from the codebase.

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 9, 2024
coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 9, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0f0a7eb and a668e22.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (1)
  • kleros-app/package.json (2 hunks)
🔇 Additional comments (2)
kleros-app/package.json (2)

48-48: Verify TypeScript compatibility with the new version

The TypeScript update to 5.7.2 might introduce breaking changes or new features.

Also applies to: 50-50

✅ Verification successful

Let me analyze the TypeScript configuration files to check for any potential compatibility issues.


No TypeScript compatibility issues detected with Parcel 2.13.2

The codebase inspection shows that:

  • The TypeScript configuration is using standard compiler options without any deprecated features
  • The codebase usage of TypeScript features (from the grep results) shows only stable features like const enum and no usage of newer TypeScript 5.7 features
  • Parcel 2.13.2 is fully compatible with TypeScript 5.7.2 as they're both recent stable versions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for TypeScript breaking changes

# Look for TypeScript configuration files
fd -e json -e jsonc tsconfig

# Search for usage of potentially affected TypeScript features
rg -g '*.ts' -g '*.tsx' 'satisfies|using|const enum|override'

Length of output: 3544


Script:

#!/bin/bash
# Check TypeScript configurations and compiler options
cat kleros-app/tsconfig.json

# Check package.json for TypeScript version and related dependencies
cat kleros-app/package.json | grep -A 5 -B 5 "typescript"

Length of output: 1441


24-24: Verify Parcel build configuration and output

The migration from Vite to Parcel is a significant tooling change. Ensure that:

  1. All build artifacts are correctly generated
  2. The build output matches the expected format for the library

Also applies to: 27-28

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between b117bf9 and e460576.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • kleros-app/package.json (2 hunks)
  • package.json (2 hunks)
  • web/package.json (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • package.json
  • web/package.json
🔇 Additional comments (2)
kleros-app/package.json (2)

48-50: LGTM! Dependencies are up-to-date

The added Parcel version and TypeScript update are both recent stable versions.


56-62: Review peer dependency version downgrades

This issue was previously identified and remains valid. Several peer dependencies have been downgraded to less specific versions which could allow older, potentially less stable versions.

Let's verify if these versions align with the web package requirements:

#!/bin/bash
# Check web package.json for dependency version requirements
fd -g "web/package.json" --exec jq -r '.dependencies | with_entries(select(.key | test("^(@tanstack/react-query|react|react-dom|graphql-request|viem|wagmi)$")))' {} \;

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 9, 2024
Copy link
Contributor

@kemuru kemuru left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, just a couple of comments:

  1. I would delete the padding-top here, looks more balanced like this since the Close button is already occupying that space
Screen.Recording.2024-12-09.at.22.12.28.mov
  1. sometimes I get a failed error when approving (even though the approve went good)
Screen.Recording.2024-12-09.at.22.03.05.mov

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (3)
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx (1)

79-90: Consider removing !important flags

The use of multiple !important flags in the styled component suggests potential style specificity issues. Consider restructuring the CSS to avoid these overrides by:

  1. Increasing selector specificity
  2. Adjusting the component hierarchy
  3. Using styled-components' theme system
 const StyledButton = styled(LightButton)`
-  border: none !important;
-  padding: 8px !important;
-  border-radius: 7px !important;
-  height: fit-content !important;
+  && {
+    border: none;
+    padding: 8px;
+    border-radius: 7px;
+    height: fit-content;
+  }
   align-self: end;
   .button-svg {
     path {
       fill: ${({ theme }) => theme.stroke};
     }
   }
`;
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (2)

311-335: Improve retry mechanism type safety and configuration

The retry mechanism could benefit from better type safety and configuration options.

+interface RetryOptions {
+  retryCount?: number;
+  retryDelay?: number;
+  shouldRetry?: (error: unknown) => boolean;
+}

-async function refetchWithRetry<T>(fn: () => Promise<T>, retryCount = 5, retryDelay = 2000) {
+async function refetchWithRetry<T>(
+  fn: () => Promise<T>,
+  options: RetryOptions = {}
+): Promise<T | undefined> {
+  const {
+    retryCount = 5,
+    retryDelay = 2000,
+    shouldRetry = () => true
+  } = options;
   let attempts = 0;

   while (attempts < retryCount) {
     try {
       const returnData = await fn();
-      //@ts-expect-error data does exist
-      if (returnData && returnData?.data !== undefined) {
+      if (returnData && 'data' in returnData) {
         return returnData;
       }
     } catch (error) {
       console.error(`Attempt ${attempts + 1} failed with error:`, error);
+      if (!shouldRetry(error)) {
+        return;
+      }
     }

     attempts++;

263-287: Simplify complex conditional logic

The isDisabled calculation could be simplified for better readability and maintainability.

 const isDisabled = useMemo(() => {
+  const hasInvalidAmount = 
+    parsedAmount === 0n ||
+    isUndefined(targetStake) ||
+    isUndefined(courtDetails);
+
+  const isBelowMinStake =
+    targetStake !== 0n && 
+    targetStake < BigInt(courtDetails?.court?.minStake ?? 0);
+
+  const hasAllowanceError =
+    isAllowance && (
+      isUndefined(increaseAllowanceConfig) || 
+      isSimulatingAllowance || 
+      !isUndefined(allowanceError)
+    );
+
+  const hasStakeError =
+    isUndefined(setStakeConfig) || 
+    isSimulatingSetStake || 
+    !isUndefined(setStakeError);
+
+  return hasInvalidAmount || isBelowMinStake || hasAllowanceError || hasStakeError;
-  if (
-    parsedAmount == 0n ||
-    isUndefined(targetStake) ||
-    isUndefined(courtDetails) ||
-    (targetStake !== 0n && targetStake < BigInt(courtDetails.court?.minStake))
-  )
-    return true;
-  if (isAllowance) {
-    return isUndefined(increaseAllowanceConfig) || isSimulatingAllowance || !isUndefined(allowanceError);
-  }
-  return isUndefined(setStakeConfig) || isSimulatingSetStake || !isUndefined(setStakeError);
 }, [
   parsedAmount,
   targetStake,
   courtDetails,
   increaseAllowanceConfig,
   isSimulatingAllowance,
   setStakeConfig,
   isSimulatingSetStake,
   setStakeError,
   allowanceError,
   isAllowance,
 ]);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d2581e5 and 364ad1f.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • web/package.json (2 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (5 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/package.json
🧰 Additional context used
📓 Learnings (2)
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx (1)
Learnt from: Harman-singh-waraich
PR: kleros/kleros-v2#1775
File: web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx:0-0
Timestamp: 2024-12-09T12:36:59.441Z
Learning: In the `StakeWithdrawButton` component, the transaction flow logic is tightly linked to component updates, so extracting it into a custom hook does not provide significant benefits.
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (1)
Learnt from: Harman-singh-waraich
PR: kleros/kleros-v2#1775
File: web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx:0-0
Timestamp: 2024-12-09T12:36:59.441Z
Learning: In the `StakeWithdrawButton` component, the transaction flow logic is tightly linked to component updates, so extracting it into a custom hook does not provide significant benefits.
🔇 Additional comments (2)
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawPopup/index.tsx (2)

1-33: LGTM!

The imports are well-organized, and the animation keyframes are properly defined for a smooth entrance effect.


110-134: 🛠️ Refactor suggestion

Add accessibility enhancements

The modal implementation should include the following accessibility features:

  1. ARIA attributes for the modal
  2. Focus management
  3. Keyboard navigation support
 const StakeWithdrawPopup: React.FC<IStakeWithdrawPopup> = ({ amount, closePopup, steps, isSuccess, action }) => {
   useLockOverlayScroll(true);
   const { data: phase } = useSortitionModulePhase();
+  const modalRef = useRef<HTMLDivElement>(null);
+
+  useEffect(() => {
+    const handleEscape = (e: KeyboardEvent) => {
+      if (e.key === 'Escape') closePopup();
+    };
+    document.addEventListener('keydown', handleEscape);
+    return () => document.removeEventListener('keydown', handleEscape);
+  }, [closePopup]);
+
+  useEffect(() => {
+    if (modalRef.current) {
+      modalRef.current.focus();
+    }
+  }, []);

   return (
-    <Overlay onClick={closePopup}>
-      <Container onClick={(e) => e.stopPropagation()}>
+    <Overlay onClick={closePopup} role="dialog" aria-modal="true">
+      <Container
+        ref={modalRef}
+        onClick={(e) => e.stopPropagation()}
+        tabIndex={-1}
+        aria-labelledby="modal-title"
+      >

Likely invalid or redundant comment.

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 10, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Outside diff range and nitpick comments (7)
web/src/hooks/usePNKData.tsx (3)

19-23: Enhance hook documentation

The current documentation could be more comprehensive about the return values and potential errors.

 /**
  * @description hook to provide user's pnk data. (pnk balance, pnk allowance, jurorBalance for provided courtId)
  * @param param0 optional court Id to fetch juror balance for. Defaults to 0
+ * @returns {Object} An object containing:
+ *   - balance: The user's PNK token balance
+ *   - jurorBalance: The user's staked balance for the specified court
+ *   - allowance: The PNK token allowance for the Kleros core contract
+ *   - refetchAllowance: Function to manually refetch the allowance
+ * @throws Will not throw, but returns undefined values if user is not connected
  */

15-17: Consider extracting constants and improving types

The default courtId and fallback address could be more explicitly defined as constants.

+const DEFAULT_COURT_ID = "0";
+const FALLBACK_ADDRESS = "0x" as const;
+
 interface UsePnkDataParams {
   courtId?: string;
 }
 
-export const usePnkData = ({ courtId = "0" }: UsePnkDataParams) => {
+export const usePnkData = ({ courtId = DEFAULT_COURT_ID }: UsePnkDataParams) => {

Also applies to: 23-23


25-28: Consider adding loading state to return value

The hook could benefit from exposing the loading state of the queries.

   const queryConfig = {
     enabled: !isUndefined(address),
     refetchInterval: REFETCH_INTERVAL,
   };
+
+  const { data: balance, isLoading: isBalanceLoading } = useReadPnkBalanceOf({
   ...
+  return {
+    balance,
+    jurorBalance,
+    allowance,
+    refetchAllowance,
+    isLoading: isBalanceLoading || isJurorBalanceLoading || isAllowanceLoading
+  };
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (2)

1-8: Consider organizing imports for better maintainability

The imports could be better organized into groups:

  1. React and routing
  2. External libraries
  3. Internal constants and hooks
  4. Internal components
  5. Internal utilities
 import React, { useCallback, useEffect, useMemo, useState } from "react";
 import styled, { DefaultTheme, useTheme } from "styled-components";
 import { useParams } from "react-router-dom";
 import { type TransactionReceipt } from "viem";
 import { usePublicClient } from "wagmi";
 
 import { type _TimelineItem1, Button } from "@kleros/ui-components-library";
+
 import { DEFAULT_CHAIN } from "consts/chains";
 import {
   klerosCoreAddress,
   useSimulateKlerosCoreSetStake,
   useWriteKlerosCoreSetStake,
   useSimulatePnkIncreaseAllowance,
   useWritePnkIncreaseAllowance,
 } from "hooks/contracts/generated";
 import { useCourtDetails } from "hooks/queries/useCourtDetails";
 import { usePnkData } from "hooks/usePNKData";
+
 import { formatETH } from "utils/format";
 import { isUndefined } from "utils/index";
 import { parseWagmiError } from "utils/parseWagmiError";
 import { refetchWithRetry } from "utils/refecthWithRetry";
+
 import { EnsureChain } from "components/EnsureChain";
 import StakeWithdrawPopup from "./StakeWithdrawPopup";
 import { getStakeSteps, StakeSteps } from "./StakeWithdrawPopup/stakeSteps";

Also applies to: 19-23, 27-28


220-244: Optimize memoization and effect dependencies

The isDisabled computation could be simplified and split into smaller, more focused checks:

-const isDisabled = useMemo(() => {
+const isValidAmount = useMemo(() => 
+  parsedAmount > 0n && 
+  !isUndefined(targetStake) && 
+  !isUndefined(courtDetails) &&
+  (targetStake === 0n || targetStake >= BigInt(courtDetails.court?.minStake))
+, [parsedAmount, targetStake, courtDetails]);
+
+const isTransactionPending = useMemo(() => 
+  isSimulatingAllowance || isSimulatingSetStake
+, [isSimulatingAllowance, isSimulatingSetStake]);
+
+const hasErrors = useMemo(() => 
+  !isUndefined(setStakeError) || !isUndefined(allowanceError)
+, [setStakeError, allowanceError]);
+
+const isDisabled = useMemo(() => {
   if (
-    parsedAmount == 0n ||
-    isUndefined(targetStake) ||
-    isUndefined(courtDetails) ||
-    (targetStake !== 0n && targetStake < BigInt(courtDetails.court?.minStake))
+    !isValidAmount || isTransactionPending || hasErrors
   )
     return true;
web/src/utils/refecthWithRetry.ts (2)

12-14: Enhance error logging

The current error logging could be more informative for debugging purposes.

-console.error(`Attempt ${attempts + 1} failed with error:`, error);
+console.error(
+  `refetchWithRetry: Attempt ${attempts + 1}/${retryCount} failed after ${retryDelay}ms:`,
+  error instanceof Error ? error.message : error
+);

1-25: Consider adding AbortSignal support

For better resource management, the function should support cancellation through AbortSignal.

Here's a suggested implementation:

export async function refetchWithRetry<T>(
  fn: () => Promise<T>,
  retryCount = 5,
  retryDelay = 2000,
  signal?: AbortSignal
): Promise<T | undefined> {
  let attempts = 0;

  while (attempts < retryCount) {
    try {
      if (signal?.aborted) {
        throw new Error('Operation cancelled');
      }

      const returnData = await fn();
      if (returnData && 'data' in returnData && returnData.data !== undefined) {
        return returnData;
      }
    } catch (error) {
      if (signal?.aborted || attempts + 1 >= retryCount) {
        throw error;
      }
      console.error(
        `refetchWithRetry: Attempt ${attempts + 1}/${retryCount} failed:`,
        error instanceof Error ? error.message : error
      );
    }

    attempts++;
    const backoffDelay = retryDelay * Math.pow(2, attempts) + Math.random() * 1000;
    const finalDelay = Math.min(backoffDelay, 30000);
    await new Promise((resolve) => setTimeout(resolve, finalDelay));
  }
  return undefined;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 364ad1f and e3da0f1.

📒 Files selected for processing (4)
  • web/src/hooks/usePNKData.tsx (1 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx (3 hunks)
  • web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (3 hunks)
  • web/src/utils/refecthWithRetry.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/src/pages/Courts/CourtDetails/StakePanel/InputDisplay.tsx
🧰 Additional context used
📓 Learnings (1)
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (1)
Learnt from: Harman-singh-waraich
PR: kleros/kleros-v2#1775
File: web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx:0-0
Timestamp: 2024-12-09T12:36:59.441Z
Learning: In the `StakeWithdrawButton` component, the transaction flow logic is tightly linked to component updates, so extracting it into a custom hook does not provide significant benefits.
🔇 Additional comments (4)
web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx (3)

50-59: Consider splitting this component for better maintainability

As noted in a previous review, this file has grown quite large. Consider splitting it into:

  1. A container component handling state and data fetching
  2. A presentation component for the UI
  3. A separate module for transaction handling logic

This would improve maintainability and make the code easier to test.


246-264: LGTM! Clean and well-structured UI implementation

The UI rendering logic is clean, well-organized, and follows React best practices:

  • Clear separation of concerns
  • Good component composition
  • Proper prop passing

110-156: 🛠️ Refactor suggestion

Enhance transaction handling robustness

The handleStake function could benefit from several improvements:

  1. Add timeout for transaction confirmation
  2. Implement retry mechanism for failed transactions
  3. Handle component unmount during async operations
 const handleStake = useCallback(
   (config?: typeof setStakeConfig, approvalHash?: `0x${string}`) => {
+    const mounted = useRef(true);
+    useEffect(() => {
+      return () => {
+        mounted.current = false;
+      };
+    }, []);
+
     const isWithdraw = action === ActionType.withdraw;
     const requestData = config?.request ?? setStakeConfig?.request;
     const commonArgs: [string, DefaultTheme, `0x${string}` | undefined] = [amount, theme, approvalHash];

     if (requestData && publicClient) {
-      setPopupStepsState(/*...*/);
+      if (mounted.current) {
+        setPopupStepsState(/*...*/);
+      }

       setStake(requestData)
         .then(async (hash) => {
-          await publicClient.waitForTransactionReceipt({ hash, confirmations: 2 })
+          await publicClient.waitForTransactionReceipt({ 
+            hash, 
+            confirmations: 2,
+            timeout: 60_000 // 1 minute timeout
+          })

Likely invalid or redundant comment.

web/src/utils/refecthWithRetry.ts (1)

1-1: Verify usage patterns across the codebase

Let's check how this utility is being used to ensure consistent error handling.

✅ Verification successful

Function is used appropriately with proper error handling

The verification shows that refetchWithRetry is used correctly in StakeWithdrawButton.tsx for handling stake-related data refetching after transactions. The function is imported from the correct location and used in a context where retrying failed operations makes sense (blockchain transactions). No inconsistent usage patterns or error handling issues were found.

  • Used in web/src/pages/Courts/CourtDetails/StakePanel/StakeWithdrawButton.tsx for retrying stake data fetching
  • Implementation in web/src/utils/refecthWithRetry.ts provides reasonable defaults (5 retries with 2000ms delay)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of refetchWithRetry
rg "refetchWithRetry" --type ts --type tsx -C 3

# Look for similar retry patterns that could be consolidated
ast-grep --pattern 'while ($cond) { try { $$$; } catch ($err) { $$$; } }'

Length of output: 151


Script:

#!/bin/bash
# Search for usages of refetchWithRetry with correct file type flags
rg "refetchWithRetry" -t ts -C 3

# Look for similar retry patterns that could be consolidated
ast-grep --pattern 'try { $$$; } catch ($err) { await $delay; $retry; }'

Length of output: 2014

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 10, 2024
alcercu
alcercu previously approved these changes Dec 10, 2024
Copy link
Contributor

@alcercu alcercu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@alcercu alcercu enabled auto-merge December 10, 2024 16:30
Copy link

codeclimate bot commented Dec 10, 2024

Code Climate has analyzed commit 40fa153 and detected 82 issues on this pull request.

Here's the issue category breakdown:

Category Count
Complexity 1
Style 81

View more on Code Climate.

Copy link
Contributor

@alcercu alcercu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@kemuru kemuru self-requested a review December 10, 2024 17:08
@alcercu alcercu added this pull request to the merge queue Dec 10, 2024
Merged via the queue into dev with commit 8cde978 Dec 10, 2024
23 of 28 checks passed
@kemuru kemuru mentioned this pull request Dec 13, 2024
17 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants