Skip to content

Fix file stucture and buds#86

Open
Muskan121622 wants to merge 2 commits intoStabilityNexus:mainfrom
Muskan121622:fix-new
Open

Fix file stucture and buds#86
Muskan121622 wants to merge 2 commits intoStabilityNexus:mainfrom
Muskan121622:fix-new

Conversation

@Muskan121622
Copy link

@Muskan121622 Muskan121622 commented Dec 14, 2025

  • Problem

  • Vault detail: incorrect coin balance scaling and render perf on large state updates #85

    • getBalances divided coin amounts by 10**18 regardless of token decimals.
    • Balance formatting recomputed every render, increasing cost on state changes.
  • Changes

    • Scale coinReserve and coinBalance using vault.decimals || 18 (file_path:line_number app/[vaultId]/InteractionClient.tsx:291–296).
    • Add useMemo for formatted display values to avoid repeated computation (file_path:line_number app/[vaultId]/InteractionClient.tsx:400–409, 501–513).
    • Maintain HodlCoin conversions at 18 decimals.
  • Rationale

    • Correctness for all ERC-20 tokens and smoother UI.
  • Testing

    • Visually confirm balances match expected on-chain scaled values for a token with non-18 decimals.
    • Ensure memoization reflects updated balances after sync, deposit, and withdraw actions.
  • Notes

    • Dependencies should be installed ( npm install / pnpm install ) to run the app; temporary type shims exist only for IDE unblocking.
      Next Steps
  • Install Node 18+ and dependencies to run npm run dev , npm run typecheck , and npm run lint .

  • After installs, remove types/shims.d.ts and rely on real types from node_modules .

Summary by CodeRabbit

  • Documentation

    • Added comprehensive Contributing Guide with setup instructions and coding standards
    • Reorganized README with architecture overview, quick start, and deployment guidelines
    • Added security test report documenting assessment findings
  • New Features

    • Vault navigation now supports path parameters for direct access
    • Last synced timestamp displayed in vault interface
    • Enhanced address and chain ID validation to prevent invalid inputs
  • Bug Fixes

    • Improved security with external link protection attributes

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 14, 2025

Walkthrough

Adds input validation infrastructure for vault addresses and chain IDs via new utils/validation.ts module. Introduces path parameter parsing in InteractionClient.tsx for vault context from URL. Adds last synced timestamp tracking to vault state. Updates multiple components (CreateForm, FindVaultForm, CardExplorer) to use validation utilities. Adds comprehensive documentation (CONTRIBUTING.md, SECURITY_TEST_REPORT.md) and rebuilds README with structured sections.

Changes

Cohort / File(s) Change Summary
Documentation
CONTRIBUTING.md, SECURITY_TEST_REPORT.md, README.md
New contributing guide with setup, branching, coding standards, and PR checklist; new security test report detailing methodology and findings; README rebranded from Next.js starter to HodlCoin platform overview with TOC, features, architecture, and deployment sections
Validation utilities
utils/validation.ts
New module exporting address and chain validators: isHexAddress, normalizeAddress, isValidChainId, parseVaultPathParam, parseChainIdInput
Vault data & sync state
app/[vaultId]/InteractionClient.tsx
Added lastSyncedAt state tracking; URL path parameter parsing and validation for vault address/chain ID; enhanced data loading with caching; functional state updates with explicit typing; UI display of last synced timestamp
Form validation & links
components/CreateVault/CreateForm.tsx, components/FindVault/FindVaultForm.tsx
Added address/chain validation using new utilities; updated vault navigation URLs to include normalized address and chainId; added rel="noreferrer" to external links; inline validation error feedback
Explorer navigation
components/Explorer/CardExplorer.tsx
Added address/chain validation and normalization in handleContinue; updated navigation path to include chainId parameter; cast event handlers for inline style updates
Type definitions
types/shims.d.ts
Added ambient module declarations for lucide-react, wagmi, @wagmi/core, next/navigation, next/link; augmented React hooks (useState, useEffect, useCallback) and JSX typings
Package configuration
package.json
Added typecheck npm script running tsc --noEmit

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Validation logic correctness: Ensure normalizeAddress and parseVaultPathParam handle edge cases (malformed input, null checks, fallback behavior) correctly across all usage sites
  • URL parameter parsing & state propagation: Verify parseVaultPathParam correctly extracts and validates vault ID; confirm lastSyncedAt state transitions in all sync paths (initial load, manual sync, blockchain refresh)
  • Form submission logic: Check that navigation URLs are properly constructed with normalized addresses and chainId query parameters in CreateForm, FindVaultForm, and CardExplorer
  • Type safety in shims.d.ts: Ensure ambient declarations don't cause conflicts; verify React hooks augmentation is consistent with actual usage patterns

Possibly related issues

Possibly related PRs

  • Redirect link fixed #42: Both PRs modify CreateVault/CreateForm.tsx navigation logic for the "Go to Vault" link, changing URL construction from static path to normalized address with chainId parameter
  • Frontend changes and Reward bug fixed. #40: Both PRs modify app/[vaultId]/InteractionClient.tsx vault data fetching and state management; this PR adds path parameter parsing and lastSyncedAt while related PR augments cached vault data structures
  • Token Selection Added to the Create Vault Form #55: Both PRs modify components/CreateVault/CreateForm.tsx; this PR adds address/chain validation and link security, complementing token selection and chain-aware state changes in related PR

Suggested reviewers

  • Zahnentferner

🐰 A hoppy PR hops in with validation so bright,
Paths parsed and synced from the code's morning light,
Addresses normalized, chains checked with care,
Documentation blooms—security, guides everywhere! ✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ⚠️ Warning The title "Fix file stucture and buds" contains a typo ("stucture" instead of "structure") and "buds" appears to be another typo or unclear abbreviation. However, the actual PR objectives describe fixing balance calculation bugs and adding memoization to the InteractionClient component, which are not about file structure at all. The title is misleading about the actual changeset. Update the title to accurately reflect the main changes, such as 'Fix token decimal scaling and add memoization for balance formatting' or similar, to clearly indicate the balance calculation and performance optimization focus.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/[vaultId]/InteractionClient.tsx (1)

292-297: Use dynamic decimals instead of hardcoded 10 ** 18 for balance conversions.
readContract returns bigint; converting via Number() risks precision loss for large values, and hardcoding 10 ** 18 breaks support for non-18 decimal tokens. The code reads the coin's decimals but doesn't use it.

Fix coinReserve and coinBalance using the coin's decimals:

+      const decimals = vault.decimals ?? 18
       setBalances((prev: typeof balances) => ({
         ...prev,
-        coinReserve: Number(coinReserveOnChain) / 10 ** 18,
-        coinBalance: Number(coinBalanceOnChain) / 10 ** 18,
+        coinReserve: Number(coinReserveOnChain) / 10 ** decimals,
+        coinBalance: Number(coinBalanceOnChain) / 10 ** decimals,
         hodlCoinBalance: Number(hodlCoinBalanceOnChain) / 10 ** 18,
       }))

Alternatively (preferred): import formatUnits from viem and store raw bigint values in state, formatting only for display. This avoids Number() conversion losses entirely.

🧹 Nitpick comments (7)
README.md (1)

52-98: Add language specifier to the fenced code block.

The file structure code block should specify text or leave blank for proper rendering and linting compliance.

Apply this diff:

 ## File Structure
-```
+```text
 app/
app/[vaultId]/InteractionClient.tsx (3)

10-16: Avoid (params as any); type useParams so vaultId is safe and predictable.
This reduces runtime edge-cases (e.g., string[]) and removes the any escape hatch.

-import { useSearchParams, useRouter, useParams } from 'next/navigation'
+import { useSearchParams, useRouter, useParams } from 'next/navigation'
 ...
-  const params = useParams()
+  const params = useParams<{ vaultId?: string }>()
 ...
-    const pv = (params as any)?.vaultId
+    const pv = params?.vaultId

Also applies to: 26-30, 84-88


67-67: lastSyncedAt UX is good; consider setting it when serving cached data too.
Right now it updates on fresh fetch and manual sync, but a cache hit leaves it blank, which can look like “never synced”.

Also applies to: 216-216, 371-371, 517-520


324-328: Precision risk with Number(bigint) conversions for supply and price; consider using formatUnits + string-based state.

The current code converts bigint values to Number before dividing by decimals. Per viem documentation, Number() loses precision above 2^53-1 (~9 billion). For hodlCoinSupply with 18 decimals, any totalSupply exceeding ~9M tokens will silently lose precision. The recommended pattern is formatUnits(value, decimals) which returns a properly formatted string.

This would require storing balances as strings instead of numbers, which is a broader architecture change. If you keep numeric state, consider at minimum validating that values remain within safe bounds or document the limitation.

utils/validation.ts (3)

16-32: parseVaultPathParam: trim segments and guard against extra separators.
Small hardening: split(':') / split('@') can yield more than 2 parts; trimming prevents subtle failures with whitespace.

   if (pv.includes(':')) {
-    const [a, c] = pv.split(':')
-    addr = a
-    cid = Number(c)
+    const [a, c] = pv.split(':', 2)
+    addr = a.trim()
+    cid = Number(c?.trim())
   } else if (pv.includes('@')) {
-    const [a, c] = pv.split('@')
-    addr = a
-    cid = Number(c)
+    const [a, c] = pv.split('@', 2)
+    addr = a.trim()
+    cid = Number(c?.trim())
   }

34-38: parseChainIdInput: trim and treat empty input as null.
Avoids Number('') === 0 pitfalls and makes UI validation cleaner.

 export const parseChainIdInput = (val: string): number | null => {
-  const num = Number(val)
+  const v = val?.trim()
+  if (!v) return null
+  const num = Number(v)
   if (!Number.isFinite(num)) return null
   return isValidChainId(num) ? num : null
 }

1-14: Use viem's address validation for EIP-55 checksum support.
isAddress(addr, { strict: true }) validates EIP-55 checksummed addresses by default, and getAddress(addr) normalizes to the correct checksum. Replace the regex-only approach to catch invalid checksums and improve safety in form validation (FindVaultForm, CreateForm) and contract interactions.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 787e368 and bb2d43e.

📒 Files selected for processing (10)
  • CONTRIBUTING.md (1 hunks)
  • README.md (1 hunks)
  • SECURITY_TEST_REPORT.md (1 hunks)
  • app/[vaultId]/InteractionClient.tsx (8 hunks)
  • components/CreateVault/CreateForm.tsx (4 hunks)
  • components/Explorer/CardExplorer.tsx (4 hunks)
  • components/FindVault/FindVaultForm.tsx (4 hunks)
  • package.json (1 hunks)
  • types/shims.d.ts (1 hunks)
  • utils/validation.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
app/[vaultId]/InteractionClient.tsx (1)
utils/validation.ts (3)
  • normalizeAddress (5-9)
  • isValidChainId (11-14)
  • parseVaultPathParam (16-32)
utils/validation.ts (1)
utils/chains.ts (1)
  • getSupportedChainIds (252-254)
components/CreateVault/CreateForm.tsx (1)
utils/validation.ts (2)
  • normalizeAddress (5-9)
  • isValidChainId (11-14)
components/Explorer/CardExplorer.tsx (1)
utils/validation.ts (2)
  • normalizeAddress (5-9)
  • isValidChainId (11-14)
🪛 LanguageTool
CONTRIBUTING.md

[style] ~31-~31: Consider using a different verb for a more formal wording.
Context: ...fig.json:25). - Run npm run lint` and fix issues before committing. - Follow Pret...

(FIX_RESOLVE)

🪛 markdownlint-cli2 (0.18.1)
README.md

52-52: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (9)
package.json (1)

10-10: LGTM! Useful addition for build-time type safety.

The typecheck script enables standalone TypeScript validation without emitting files, which is valuable for CI/CD pipelines and pre-commit checks.

SECURITY_TEST_REPORT.md (1)

1-44: Well-structured security documentation.

The report provides clear findings and actionable recommendations. The validation utilities referenced (e.g., utils/validation.ts) align with security best practices for client-side input handling.

CONTRIBUTING.md (1)

1-53: Comprehensive contributing guide with helpful references.

The guide provides clear workflows and specific file references, making it easy for contributors to understand the project structure and conventions.

README.md (1)

1-190: Excellent documentation transformation.

The README has been restructured from a basic starter template to comprehensive platform documentation with clear sections, specific file references, and helpful setup instructions.

components/Explorer/CardExplorer.tsx (1)

49-55: Good validation before navigation.

The address normalization and chain ID validation prevent navigation with invalid parameters, improving robustness.

components/FindVault/FindVaultForm.tsx (2)

28-39: Excellent input validation with user feedback.

The real-time validation for both address and chain ID, combined with inline error messages, provides clear feedback and prevents invalid navigation attempts.


71-75: Good UX with immediate validation feedback.

Validating inputs on change and displaying errors inline helps users correct issues before submission.

Also applies to: 91-94

components/CreateVault/CreateForm.tsx (2)

107-107: Proper input validation before vault creation.

Validating both the ERC20 address format and chain ID support prevents contract interaction errors and improves user feedback.

Also applies to: 115-115


443-443: Security best practice applied.

Adding rel="noreferrer" to external links prevents the Referer header from being sent, which aligns with the security recommendations in the Security Test Report.

Comment on lines 69 to +95
useEffect(() => {
const vault = searchParams.get('vault')
const chain = searchParams.get('chainId')

if (vault && chain) {
setVaultAddress(vault as `0x${string}`)
setChainId(Number(chain))
const naddr = normalizeAddress(vault)
const cid = Number(chain)
if (naddr && isValidChainId(cid)) {
setVaultAddress(naddr)
setChainId(cid)
} else {
setError('Invalid vault address or chain ID')
}
return
}
const pv = (params as any)?.vaultId
if (typeof pv === 'string' && pv.length > 0) {
const { address, chainId: parsedCid } = parseVaultPathParam(pv)
const cid = parsedCid ?? activeChainId ?? 0
if (address && isValidChainId(cid)) {
setVaultAddress(address)
setChainId(cid)
} else {
setError('Invalid vault address or chain ID')
}
}
}, [searchParams])
}, [searchParams, params, activeChainId])
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix “stuck loading” when URL params are invalid (error is masked by isLoading).
Right now you can set error without ever clearing isLoading, but the render checks isLoading before error, so the user may never see the error state.

-  if (isLoading) {
+  if (error) {
+    return (
+      <div className="relative min-h-screen flex items-center justify-center bg-background overflow-hidden">
+        {/* Matrix background effect */}
+        <div className="absolute inset-0 opacity-10">
+          <div ref={matrixRef} className="absolute inset-0 w-full h-full" />
+        </div>
+        
+        <Card className="bg-background/50 backdrop-blur-xl border-red-500/20 p-8 shadow-2xl shadow-red-500/5 max-w-md mx-4">
+          <div className="flex flex-col items-center space-y-4 text-center">
+            <AlertCircle className="h-8 w-8 text-red-500" />
+            <h2 className="text-xl font-semibold text-gradient">Error Loading Vault</h2>
+            <p className="text-muted-foreground">{error}</p>
+            <Link href="/">
+              <Button variant="outline" className="border-primary/50 hover:bg-primary/10">
+                <ArrowLeft className="h-4 w-4 mr-2" />
+                Go Back Home
+              </Button>
+            </Link>
+          </div>
+        </Card>
+      </div>
+    )
+  }
+
+  if (isLoading) {
     return (
       <div className="relative min-h-screen mt-16 flex items-center justify-center bg-background overflow-hidden">
         {/* Matrix background effect */}
         <div className="absolute inset-0 opacity-10">
           <div ref={matrixRef} className="absolute inset-0 w-full h-full" />
           <div className="absolute top-1/4 left-1/4 w-32 h-32 bg-gray-300/15 dark:bg-purple-500/10 rounded-full blur-3xl animate-pulse" />
           <div className="absolute bottom-1/3 right-1/4 w-24 h-24 bg-gray-400/10 dark:bg-violet-500/15 rounded-full blur-2xl animate-pulse animation-delay-2000" />
         </div>
         
         <Card className="bg-background/50 backdrop-blur-xl border-primary/20 p-8 shadow-2xl shadow-primary/5">
           <div className="flex flex-col items-center space-y-4">
             <Loader2 className="h-8 w-8 animate-spin text-primary" />
             <p className="text-muted-foreground">Loading vault data...</p>
           </div>
         </Card>
       </div>
     )
   }
-
-  if (error) {
-    return ( ... )
-  }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In app/[vaultId]/InteractionClient.tsx around lines 69 to 95, the effect can set
error without clearing isLoading so the UI remains stuck showing loading; update
the effect so any branch that sets setError(...) also calls setIsLoading(false),
and ensure successful branches that setVaultAddress/setChainId also call
setIsLoading(false) (or clear isLoading at the end of the effect once validation
is complete); make sure every execution path either clears isLoading or leaves
it intentionally true only while async work is underway.

</Button>
</Link>
<Link href={`/v?chainId=${config.state.chainId}&vault=${vaultAddress}`}>
<Link href={`/${normalizeAddress(vaultAddress) ?? vaultAddress}?chainId=${config.state.chainId}`}>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential issue with normalization fallback.

The fallback ?? vaultAddress could still route to an invalid address if normalization fails. Since vault creation already validated the address (lines 107, 115), this scenario shouldn't occur, but it's worth ensuring the fallback never happens.

Consider asserting that normalization succeeds or logging when fallback is used:

-<Link href={`/${normalizeAddress(vaultAddress) ?? vaultAddress}?chainId=${config.state.chainId}`}>
+<Link href={`/${normalizeAddress(vaultAddress) || vaultAddress}?chainId=${config.state.chainId}`}>

Or more defensively:

const normalizedAddr = normalizeAddress(vaultAddress);
if (!normalizedAddr) {
  console.error('Vault address normalization failed after creation:', vaultAddress);
}
// Use normalizedAddr with proper null handling
🤖 Prompt for AI Agents
In components/CreateVault/CreateForm.tsx around line 453, the code uses
normalizeAddress(vaultAddress) with a fallback to vaultAddress which could route
to an invalid address; change this to explicitly normalize once into a variable,
assert or log if normalization returns falsy, and only use the normalized value
in the Link (or redirect to an error/validation path) so the fallback never
silently proceeds — i.e., compute normalizedAddr =
normalizeAddress(vaultAddress), if normalizedAddr is falsy log an error (or
throw/handle) and avoid using vaultAddress as a fallback, then use
normalizedAddr in the Link href.

Comment on lines +141 to +142
onMouseEnter={(e: any) => e.currentTarget.style.color = 'hsl(50 100% 45%)'}
onMouseLeave={(e: any) => e.currentTarget.style.color = ''} />
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Event handler type casts are a symptom of the shims.d.ts issue.

The (e: any) casts for onMouseEnter and onMouseLeave handlers are unnecessary with proper React types. These casts are likely needed because types/shims.d.ts overrides React's type definitions with permissive any types.

Once types/shims.d.ts is removed (as recommended), these handlers should be typed properly:

onMouseEnter={(e: React.MouseEvent<HTMLSpanElement>) => e.currentTarget.style.color = 'hsl(50 100% 45%)'}

Also applies to: 164-165, 171-172

🤖 Prompt for AI Agents
In components/Explorer/CardExplorer.tsx around lines 141-142 (and also update
164-165 and 171-172), replace the permissive (e: any) event parameter with the
proper React event typing and remove the casts: use e:
React.MouseEvent<HTMLSpanElement> for onMouseEnter and onMouseLeave so you can
safely access e.currentTarget.style; ensure React is imported for types (import
React from 'react' or enable isolated type import) and, separately, remove or
fix types/shims.d.ts that is overriding React types so these handlers no longer
require any casts.

Comment on lines +1 to +20
declare module 'lucide-react';
declare module 'wagmi';
declare module '@wagmi/core';
declare module 'next/navigation';
declare module 'next/link';
declare module 'react' {
export function useState<T>(initialState: T | (() => T)): [T, (value: T | ((prev: T) => T)) => void];
export function useEffect(effect: (...args: any[]) => any, deps?: any[]): void;
export function useCallback<T extends (...args: any[]) => any>(callback: T, deps: any[]): T;
}

declare namespace JSX {
interface IntrinsicElements {
[elemName: string]: any;
}
}

declare namespace React {
type MouseEvent = any;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Remove these temporary type shims and install proper type definitions.

This ambient declaration file uses any extensively, which defeats TypeScript's type safety. The proper types should be available from:

  • lucide-react exports its own types
  • @types/react@^18 is already in devDependencies (line 50 in package.json)
  • wagmi, @wagmi/core, next/navigation, next/link export their own types

As noted in the PR objectives, these temporary shims should be removed after installing real types from node_modules. The types already exist in your dependencies—this file likely masks actual type errors that should be fixed in the consuming code instead.

🤖 Prompt for AI Agents
In types/shims.d.ts around lines 1 to 20, remove this temporary ambient
declaration file that broadly declares many modules and uses any types; instead
install or enable the real type definitions from node_modules (ensure
lucide-react, wagmi, @wagmi/core, next and React types are present), delete the
file, run npm/yarn install to fetch types, and then fix any TypeScript errors
surfaced in the consuming code by updating incorrect typings or imports so the
proper exported types from those packages are used rather than any.

@Muskan121622 Muskan121622 changed the title Fix ile stucture and buds Fix file stucture and buds Dec 14, 2025
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