Skip to content

Fix centrel input errors#84

Open
Muskan121622 wants to merge 2 commits intoStabilityNexus:mainfrom
Muskan121622:fix-centrel-input-errors
Open

Fix centrel input errors#84
Muskan121622 wants to merge 2 commits intoStabilityNexus:mainfrom
Muskan121622:fix-centrel-input-errors

Conversation

@Muskan121622
Copy link

@Muskan121622 Muskan121622 commented Dec 14, 2025

Fix Routing & Strengthen Input Validation Across Vault Workflows

#81

Summary

This PR standardizes vault routing and introduces robust, reusable input validation to improve reliability, security, and UX across all vault-related flows.

Key Changes

  • Routing Standardization

    • Unifies vault navigation under app/[vaultId]
    • Uses canonical URLs: /${address}?chainId=<id>
  • Centralized Validation

    • Adds utils/validation.ts with helpers for:
      • Address validation
      • Chain ID validation
      • Safe path/query param parsing
  • Validation Integration

    • Find Vault: Inline validation errors and guarded navigation
    • Explorer Cards: Validated “Enter Vault” actions
    • Create Vault: ERC20 address and chain ID validation before submit
    • Vault Detail Page: Early validation of path/query params with graceful error handling
  • UI Improvements

    • Displays last sync timestamp on the vault detail page
  • Security

    • Adds SECURITY_TEST_REPORT.md documenting Burp Suite testing methodology, findings, and recommendations

Code References

  • app/[vaultId]/InteractionClient.tsx:66
  • components/FindVault/FindVaultForm.tsx:60
  • components/Explorer/CardExplorer.tsx:49
  • components/CreateVault/CreateForm.tsx:101


<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

* **Documentation**
  * Added comprehensive contributing guide outlining project conventions, workflow, and coding standards.
  * Expanded README with detailed features overview, tech stack, architecture, setup instructions, and deployment guidance.
  * Added security assessment documentation.

* **New Features**
  * Support for vault identification via URL parameters and path-like identifiers.
  * Display of last synced timestamp in vault status area.
  * Real-time validation with error messages for vault address and chain selection inputs.
  * Normalized vault address handling in navigation.

* **Improvements**
  * Enhanced security attributes on external links.

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

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

@coderabbitai
Copy link

coderabbitai bot commented Dec 14, 2025

Walkthrough

Adds address and chain ID validation utilities and applies them across multiple components to improve vault navigation and parameter handling. Updates InteractionClient with sync tracking and path-parameter resolution. Expands documentation with comprehensive guides for contributing, security testing, and project setup.

Changes

Cohort / File(s) Summary
Documentation
CONTRIBUTING.md, README.md, SECURITY_TEST_REPORT.md
Introduces contributing guidelines, rewrites README with full architecture/setup documentation, and adds security assessment report.
Validation Utilities
utils/validation.ts
New module exporting address normalization, hex validation, chain ID validation, and vault path parsing functions.
Type Improvements
types/shims.d.ts
Adds TypeScript ambient module declarations for dependencies and augments React hooks and event types.
Vault Interaction
app/[vaultId]/InteractionClient.tsx
Adds vault address/chain ID resolution from URL parameters with fallback path parsing; introduces lastSyncedAt state tracking and UI display.
Vault Discovery & Creation
components/CreateVault/CreateForm.tsx, components/FindVault/FindVaultForm.tsx
Adds input validation for vault addresses and chain IDs with inline error display; updates navigation to use normalized addresses and validated chains.
Vault Navigation
components/Explorer/CardExplorer.tsx
Updates vault link construction to use normalized addresses with explicit chain ID validation; adds TypeScript event parameter typings.
Build Configuration
package.json
Adds typecheck script running tsc --noEmit.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Validation logic correctness: verify isHexAddress, normalizeAddress, and parseVaultPathParam handle edge cases and invalid inputs appropriately
  • InteractionClient state management: confirm vault/chain resolution fallback logic and sync tracking updates are sound
  • URL routing consistency: ensure all components construct URLs with the new format consistently and validated parameters propagate correctly
  • Type shims scope: verify ambient module declarations don't mask real type issues and React hook augmentations align with actual usage patterns

Possibly related PRs

Suggested reviewers

  • Zahnentferner

🐰 A rabbit hops through code with glee,
Addresses validated, chains running free!
Paths now parse, syncs now track,
No more broken vaults—we're back on track!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
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 ❓ Inconclusive The title 'Fix centrel input errors' is vague and appears to contain a typo ('centrel' instead of 'central'), making it unclear what specific changes are being made. Use a more descriptive title that clearly conveys the main change, such as 'Standardize vault routing and add centralized input validation' to reflect the actual scope of standardizing routing and introducing reusable validation utilities.
✅ 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: 3

Caution

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

⚠️ Outside diff range comments (2)
components/CreateVault/CreateForm.tsx (1)

102-119: Don’t validate with normalizeAddress() and then submit the raw (possibly invalid) address strings.
Right now coin can pass validation (after .trim()), but writeContract/simulateContract still receive the untrimmed coin string; also vaultCreator isn’t validated at all.

   const validateInputs = () => {
     const Errors: any = {}

     if (!coinName) Errors.coinName = 'Name for hodlCoin is required'
     if (!symbol) Errors.symbol = 'Symbol for hodlCoin is required'
-    if (!coin || !normalizeAddress(coin)) Errors.coin = 'Valid ERC20 address is required'
-    if (!vaultCreator) Errors.vaultCreator = 'Vault creator address is required'
+    const nCoin = normalizeAddress(coin)
+    if (!nCoin) Errors.coin = 'Valid ERC20 address is required'
+    const nCreator = normalizeAddress(vaultCreator)
+    if (!nCreator) Errors.vaultCreator = 'Valid vault creator address is required'
     if (vaultFee === '') Errors.vaultFee = 'Vault fee is required'
     if (vaultCreatorFee === '')
       Errors.vaultCreatorFee = 'Vault creator fee is required'
     if (Number(vaultFee) < 0) Errors.vaultFee = 'Vault fee cannot be negative'
     if (Number(vaultCreatorFee) < 0)
       Errors.vaultCreatorFee = 'Vault creator fee cannot be negative'
-    if (!isValidChainId(config.state.chainId)) Errors.coin = 'Unsupported chain'
+    if (!isValidChainId(config.state.chainId)) Errors.chainId = 'Unsupported chain'

     setErrors(Errors)
     return Object.keys(Errors).length === 0
   }
   async function createVault() {
     if (!validateInputs()) {
       toast({
         title: 'Error',
         description: 'Please fix the errors before submitting.',
         variant: 'destructive',
       });
       return;
     }

     try {
       setLoadingCreation(true)
       const chainId = config.state.chainId
+      const nCoin = normalizeAddress(coin)!
+      const nCreator = normalizeAddress(vaultCreator)!

       const tx = await writeContract(config as any, {
         address: HodlCoinVaultFactories[chainId],
         abi: HodlCoinFactoryAbi,
         functionName: 'createHodlCoin',
         args: [
           coinName,
           symbol,
-          coin as `0x${string}`,
-          vaultCreator as `0x${string}`,
+          nCoin,
+          nCreator,
           vaultFeeNumerator,
           vaultCreatorFeeNumerator,
           BigInt(stableOrderFee),
         ],
       })

(Repeat the same nCoin/nCreator usage in the simulateContract call.)

Also applies to: 134-164, 168-181

components/FindVault/FindVaultForm.tsx (1)

67-75: Chain ID UX: resetting to 0 on invalid/partial input makes the field hard to edit.
Typing an unsupported/partial value immediately collapses to empty (0''), which can feel “broken”. Consider storing chainIdInput: string and separately tracking parsedChainId: number | null.

Also applies to: 79-79

🧹 Nitpick comments (10)
SECURITY_TEST_REPORT.md (1)

22-44: Use rel="noopener noreferrer" (not just noreferrer) and add test metadata.
Also consider recording the test date, Burp Suite version, and the commit/branch tested so the findings are traceable.

- - External Links: Transaction explorer links use `target="_blank"`. Recommend `rel="noreferrer"`.
+ - External Links: Transaction explorer links use `target="_blank"`. Recommend `rel="noopener noreferrer"`.
...
- - Add `rel="noreferrer"` to external links.
+ - Add `rel="noopener noreferrer"` to external links.
CONTRIBUTING.md (1)

41-50: Add npm run typecheck to the PR checklist (and consider avoiding hardcoded line numbers).

 ## Pull Request Checklist
 ...
 - Ensure `npm run lint` passes.
+- Ensure `npm run typecheck` passes.
 - Verify local build if applicable: `npm run build`.
components/CreateVault/CreateForm.tsx (1)

440-458: For target="_blank", prefer rel="noopener noreferrer".

-  rel="noreferrer"
+  rel="noopener noreferrer"
README.md (1)

19-33: Docs: vault detail route + scripts list look out of sync with the new routing + typecheck script.

-- Detailed vault view: balances, fees, price, and manual sync (`/v/[vaultId]`)
+- Detailed vault view: balances, fees, price, and manual sync (`/[vaultId]?chainId=<id>`)
...
 ## Scripts
 ...
 - `npm run lint`: Run Next.js ESLint checks
+- `npm run typecheck`: Run TypeScript type checking (no emit)
-```
+```text
 app/
   [vaultId]/           # Vault detail route

Also applies to: 51-99, 127-133

utils/validation.ts (1)

11-32: Minor robustness/perf: cache supported chain IDs and limit split to 2 parts.

-import { getSupportedChainIds } from './chains'
+import { getSupportedChainIds } from './chains'
+
+const SUPPORTED_CHAIN_IDS = getSupportedChainIds()

 export const isValidChainId = (id: number): boolean => {
   if (!Number.isFinite(id)) return false
-  return getSupportedChainIds().includes(id)
+  return SUPPORTED_CHAIN_IDS.includes(id)
 }
 ...
   if (pv.includes(':')) {
-    const [a, c] = pv.split(':')
+    const [a, c] = pv.split(':', 2)
     addr = a
     cid = Number(c)
   } else if (pv.includes('@')) {
-    const [a, c] = pv.split('@')
+    const [a, c] = pv.split('@', 2)
     addr = a
     cid = Number(c)
   }
components/Explorer/CardExplorer.tsx (1)

141-142: Avoid any + direct style mutation in hover handlers; use proper event typing and CSS/state.
(e: any) => e.currentTarget.style... sidesteps TS and can be brittle across SVG/component changes; prefer React.MouseEvent<SVGSVGElement> (or HTMLElement) and drive hover via className/state.

Also applies to: 164-166, 171-172

components/FindVault/FindVaultForm.tsx (2)

31-39: Good validation + routing, but parseChainIdInput(String(chainId)) is a smell.
You’re validating a derived string from a numeric state that’s already been coerced; this gets cleaner if you keep the raw input string and parse/validate from that.


88-98: Consider suppressing “Invalid address” while the field is empty.
After a user clears the field, showing an error can be noisy; often better to show errors only when non-empty (or after blur/submit).

app/[vaultId]/InteractionClient.tsx (2)

292-298: Prefer an explicit Balances type over typeof balances in state updaters.
Using setBalances((prev: typeof balances) => ...) works, but it couples typing to an outer value; a named type/interface is clearer and avoids accidental refactors changing inferred types.

Also applies to: 324-328


517-520: Last synced UI: consider including date (not just time) to reduce ambiguity.
If a user leaves the tab open overnight, “Last synced 1:02:03 PM” is unclear without a date.

📜 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 (5)
components/Explorer/CardExplorer.tsx (1)
utils/validation.ts (2)
  • normalizeAddress (5-9)
  • isValidChainId (11-14)
components/FindVault/FindVaultForm.tsx (1)
utils/validation.ts (2)
  • normalizeAddress (5-9)
  • parseChainIdInput (34-38)
utils/validation.ts (1)
utils/chains.ts (1)
  • getSupportedChainIds (252-254)
components/CreateVault/CreateForm.tsx (2)
utils/validation.ts (2)
  • normalizeAddress (5-9)
  • isValidChainId (11-14)
utils/config.ts (1)
  • config (14-27)
app/[vaultId]/InteractionClient.tsx (1)
utils/validation.ts (3)
  • normalizeAddress (5-9)
  • isValidChainId (11-14)
  • parseVaultPathParam (16-32)
🪛 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 (1)
package.json (1)

5-11: Good addition—consider wiring npm run typecheck into CI / PR checklist.
Having a dedicated tsc --noEmit step is useful, but it only helps if it runs consistently (e.g., CI + local checklist).

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

Critical: invalid/missing params can leave the page stuck on the loading screen.
setError(...) in the param-parse effect doesn’t guarantee isLoading becomes false, and the render checks isLoading before error, so users can see an infinite loader instead of the error UI.

   useEffect(() => {
     const vault = searchParams.get('vault')
     const chain = searchParams.get('chainId')

     if (vault && 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')
+        setIsLoading(false)
       }
       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')
+        setIsLoading(false)
       }
+    } else {
+      setError('Missing vault address or chain ID')
+      setIsLoading(false)
     }
   }, [searchParams, params, activeChainId])
-  if (isLoading) {
+  if (error) {
+    return (/* existing error UI */)
+  }
+  if (isLoading) {
     return (/* existing loading UI */)
   }
-
-  if (error) {
-    return (/* existing error UI */)
-  }

Also applies to: 401-445

🤖 Prompt for AI Agents
In app/[vaultId]/InteractionClient.tsx around lines 69-95 (and similarly for the
other param parsing block at 401-445), the effect sets setError(...) when params
are invalid but never clears isLoading, so the UI can stay stuck on the loader;
update the effect to call setIsLoading(false) immediately whenever you call
setError (or otherwise ensure isLoading is set to false before returning) so the
error UI can render, and apply the same change to every other code path in these
ranges that sets an error.

Comment on lines 49 to 55
const handleContinue = () => {
if (vault.vaultAddress) {
router.push(`/v?chainId=${chainId}&vault=${vault.vaultAddress}`)
const addr = normalizeAddress(vault.vaultAddress)
const valid = isValidChainId(chainId)
if (addr && valid) {
router.push(`/${addr}?chainId=${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

Add user-visible feedback when navigation is blocked by validation (currently no-op).
Right now, invalid vault.vaultAddress / chainId just does nothing; consider a toast so users aren’t stuck clicking “Enter Vault” with no result.

🤖 Prompt for AI Agents
In components/Explorer/CardExplorer.tsx around lines 49-55, the handleContinue
function silently returns when normalizeAddress or isValidChainId fails; change
it to show user-visible feedback (e.g., a toast or inline error) for each
validation failure before returning. Specifically, import/use your app’s toast
utility (or set an error state) and call toast.error("Invalid vault address")
when addr is falsy and toast.error("Unsupported chain") when valid is false;
keep the existing router.push only when both validations pass.

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.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's check if package.json exists and what dependencies are listed
find . -name "package.json" -type f | head -5

Repository: StabilityNexus/hodlCoin-Solidity-WebUI

Length of output: 96


🏁 Script executed:

cat ./package.json | head -80

Repository: StabilityNexus/hodlCoin-Solidity-WebUI

Length of output: 1750


🏁 Script executed:

cat ./tsconfig.json

Repository: StabilityNexus/hodlCoin-Solidity-WebUI

Length of output: 768


🏁 Script executed:

# Check if these packages actually have type definitions
# Let's look for .d.ts files or types field in package.json for key packages
cd node_modules
for pkg in lucide-react wagmi @wagmi/core; do
  if [ -f "$pkg/package.json" ]; then
    echo "=== $pkg ==="
    cat "$pkg/package.json" | grep -A 2 '"types"\|"typings"' | head -5
  fi
done

Repository: StabilityNexus/hodlCoin-Solidity-WebUI

Length of output: 144


🏁 Script executed:

# Check the actual shims file content more carefully
cat -n ./types/shims.d.ts

Repository: StabilityNexus/hodlCoin-Solidity-WebUI

Length of output: 822


🏁 Script executed:

# Search for any comments or issues in the codebase explaining why these shims were needed
rg -i "shim|type.*issue|@wagmi|lucide" --type ts --type tsx -B 2 -A 2 | head -100

Repository: StabilityNexus/hodlCoin-Solidity-WebUI

Length of output: 109


🏁 Script executed:

# Search for any references to shims or type issues
rg -i "shim|types/shims" --type ts | head -20

Repository: StabilityNexus/hodlCoin-Solidity-WebUI

Length of output: 64


🌐 Web query:

lucide-react TypeScript definitions type support

💡 Result:

Short answer

  • lucide-react ships bundled TypeScript definitions: each icon is a typed React component and the package exports types like LucideProps and LucideIcon. [1][2]

What that means

  • Icons are typed as React forward-ref components: ForwardRefExoticComponent<Omit<LucideProps, "ref"> & RefAttributes>. LucideProps includes common SVG props plus size and absoluteStrokeWidth. [2]
  • Docs explicitly state “full TypeScript support” for lucide-react. [1]

Common problems & fixes

  • If you get JSX/element-type errors (e.g. “X cannot be used as a JSX component”), it’s usually a TypeScript / @types/react mismatch (React 18+ vs TS / JSX settings) — resolve by aligning TS, @types/react/@types/react-dom (or using the built-in react types with TS 4.5+/React 18), or relax type checking (e.g. skipLibCheck) as a temporary workaround. See community reports and discussion. [3]

If you want, tell me:

  • your TS version, @types/react (or react) version, and tsconfig.jsx setting and I’ll give precise fixes and config snippets.

Sources

  1. lucide.dev — Lucide React package docs. [1]
  2. Bundled declaration file (lucide-react.d.ts). [2]
  3. GitHub issue showing typical JSX/TS errors and discussion. [3]

🌐 Web query:

wagmi @wagmi/core TypeScript definitions type support

💡 Result:

Short answer — @wagmi/core has first-class TypeScript support. Key points:

  • Requirements: TypeScript (docs state >= 5.7.3) and strict mode enabled in tsconfig. [1]
  • Type inference: wagmi infers types from ABIs and EIP‑712 Typed Data (powered by Viem / ABIType). To get inference you must define ABIs/typed data inline or use const assertions (e.g., const abi = [...] as const). [1][2]
  • Package dependency: install/use [email protected] alongside @wagmi/core for the TypeScript integration. [3]
  • Stability notes: type changes may be released as patch updates; lock @wagmi/core and typescript to specific patch versions for reproducible behavior. [1]

If you want, I can show a minimal TypeScript example (readContract / signTypedData) demonstrating const assertions and correct tsconfig.


🌐 Web query:

Next.js next/navigation next/link TypeScript types built-in

💡 Result:

Short answer: Yes — Next.js ships built-in TypeScript types for next/link and next/navigation, and recent Next.js versions provide optional statically-typed routes so Link.href and the App Router navigation methods (push/replace/prefetch) are type-checked.

What to know and how to enable it

  • Next.js includes TypeScript support and its type definitions by default. [1]
  • To get statically-typed links you opt into the typed-routes feature (named experimental.typedRoutes or typedRoutes depending on Next.js version) in next.config and use TypeScript; Next.js then generates route types under .next/types which you should include in tsconfig.json. This types Link.href and App Router navigation (useRouter/useNavigation) for literal routes; non-literal hrefs may need a cast (as Route). [2][3]

Example (next.config):

  • next.config.ts / next.config.js: enable typedRoutes/experimental.typedRoutes, then run next dev/build so .next/types is generated and picked up by TypeScript. Include ".next/types/**/*.ts" in tsconfig.json include if needed. [2][3]

References

  • Next.js TypeScript docs (statically typed links, generated .next/types). [2]
  • Next.js TypeScript config / general TypeScript support. [1][3]

🌐 Web query:

React 18 useState useEffect useCallback TypeScript @types/react correct types

💡 Result:

Short summary and correct typings (React 18 + TypeScript / @types/react)

  • useState

    • Signature: function useState(initialState: S | (() => S)): [S, Dispatch<SetStateAction>]
    • Usage: prefer explicit generic when initial value is null/unknown: const [user, setUser] = useState<User | null>(null). [1][2]
  • useEffect / useLayoutEffect

    • Signature: function useEffect(effect: () => (void | (() => void | undefined)), deps?: DependencyList)
    • Notes: effect may return a cleanup function or void; deps is DependencyList (readonly any[]). [1][2]
  • useCallback

    • React 18 signature: function useCallback(callback: T, deps: DependencyList): T
    • Implication: callback parameter types are not forced by useCallback’s type; you must type the callback parameters explicitly (or provide a generic) to avoid implicit any. Example:
      • const handle = useCallback((e: React.MouseEvent) => { ... }, []);
      • or const handle = useCallback<() => void>(() => { ... }, []);
    • Older React @types used T extends (...args: any[]) => any; React 18 widened to T extends Function which can surface implicit-any on params. [1][2][3]

Recommendations

  • Install matching @types/react for your React version.
  • Explicitly annotate state generics when initial value is null/unknown.
  • Always type callback parameters for useCallback to satisfy strict TS settings.
  • Hover/signature in VS Code or inspect @types/react in node_modules for exact local types.

Sources: React docs (react.dev) and React + TypeScript cheatsheet / @types/react notes. [1][2][3]

References
[1] React docs — Using TypeScript (react.dev).
[2] React + TypeScript Cheatsheet (react-typescript-cheatsheet).
[3] typescript-cheatsheets / react GitHub notes on useCallback and hook signatures.


🏁 Script executed:

# Let's check if there are any files importing from 'react' that might rely on these hook signatures
rg "useState|useEffect|useCallback" --type ts -l | head -10

Repository: StabilityNexus/hodlCoin-Solidity-WebUI

Length of output: 380


🏁 Script executed:

# Check one of the files that uses hooks to see the actual usage pattern
head -40 ./components/hooks/useTokenSearch.ts

Repository: StabilityNexus/hodlCoin-Solidity-WebUI

Length of output: 1352


🏁 Script executed:

# Check the rest of the file to see actual useState/useEffect usage
tail -50 ./components/hooks/useTokenSearch.ts

Repository: StabilityNexus/hodlCoin-Solidity-WebUI

Length of output: 1451


🏁 Script executed:

# Get full file to see useState usage
wc -l ./components/hooks/useTokenSearch.ts
cat ./components/hooks/useTokenSearch.ts | grep -A 3 "useState"

Repository: StabilityNexus/hodlCoin-Solidity-WebUI

Length of output: 538


Remove these type shims—they mask real types and some signatures are incorrect.

The packages declared in lines 1–5 (lucide-react, wagmi, @wagmi/core, next/navigation, next/link) all ship with first-class TypeScript definitions, making those ambient module declarations unnecessary and harmful. Declaring them as untyped silences real type errors.

Additionally:

  • Line 8 (useEffect signature): The (...args: any[]) => any is wrong; React 18's useEffect expects () => void | (() => void). This incorrect override could mask legitimate type issues in effect handlers.
  • Lines 12–15 (JSX.IntrinsicElements): Widening to [elemName: string]: any defeats JSX prop validation.
  • Line 19 (React.MouseEvent): Setting to any removes event type safety.

These shims undermine the value of npm run typecheck by hiding real issues.

Recommended action: Remove types/shims.d.ts entirely and verify npm run typecheck passes. If it does, the shims were not needed. If it fails, fix the underlying issues rather than adding blanket any declarations.

🤖 Prompt for AI Agents
types/shims.d.ts lines 1–20: delete this shim file entirely (it masks real type
definitions for lucide-react, wagmi, @wagmi/core, next/navigation, next/link and
overrides React types incorrectly); after removal run npm run typecheck and fix
any resulting type errors in code (prefer correcting code or adding
narrowly-scoped declaration files with accurate types rather than reintroducing
blanket any shims), ensure React hooks and event types use their proper
signatures (useEffect returns void | (() => void), restore proper
JSX.IntrinsicElements typings and remove the React.MouseEvent:any override).

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