This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Coinchan is a web3 application built with React, Vite, and TypeScript. It provides a platform for creating, trading, and managing crypto tokens/coins with features like trading, swapping, limit orders, prediction markets, liquidity management, farming, staking, and token creation. The application integrates with blockchain via Wagmi/Viem and supports Farcaster frames.
# Install dependencies (must use pnpm)
pnpm install
# Start the development server
pnpm dev
# Build the project (includes TypeScript check)
pnpm build
# Preview the production build
pnpm preview
# Lint the code with Biome
pnpm lint
# Format the code with Biome (auto-fix)
pnpm format
# Verify code quality (format + build)
pnpm check- Frontend Framework: React 18 with TypeScript 5.4 (strict mode)
- Build Tool: Vite 6.3 with TailwindCSS v4 plugin
- Routing: TanStack Router 1.121 with file-based routing and automatic code splitting
- State Management: React Query 5.85 with persistent localStorage caching (24-hour retention)
- Styling: Tailwind CSS 4.1 + class-variance-authority (CVA) for component variants
- UI Components: Radix UI primitives (dialog, dropdown, tabs, slider, etc.)
- Web3 Integration: Wagmi 2.16 + Viem 2.29 + RainbowKit 2.2
- Blockchain RPC: Multi-endpoint fallback (DRPC with batching, Alchemy, Cloudflare)
- Internationalization: react-i18next 15.5 with auto language detection (English, Chinese)
- Data Visualization: Recharts 2.15 + lightweight-charts 5.0
- Code Quality: Biome 1.8 (linter & formatter)
- Utilities: Zod (validation), GraphQL Request, Framer Motion, Sonner (toasts)
The application wraps components in this specific order:
ThemeProvider (dark/light mode)
└─ WalletProviders
├─ WagmiProvider (blockchain config)
├─ PersistQueryClientProvider (React Query + localStorage)
├─ RainbowKitProvider (wallet UI)
├─ ConnectionErrorHandler (Web3 error boundary)
└─ RouterProvider (TanStack Router)
- Type: File-based routing via TanStack Router with automatic route tree generation
- Route Files:
/src/routes/**/*.tsx(generates/src/routeTree.gen.ts) - Root Layout:
/src/routes/__root.tsxcontains global navigation, header, and mobile menu - Key Routes:
/- Landing page with instant trade action/swap- Token swapping interface/limit- Limit orders/predict- Prediction markets/send- Token transfers/explore/*- Token/pool exploration/positions- Liquidity positions/farm,/stake- Yield farming & staking/create- Token creation/raise- Token launches/c/:coinId- Individual coin details
- Navigation: Use
useNavigate()hook from TanStack Router, NOT react-router
- Global State: Theme (React Context) + Wagmi connection state
- Server State: React Query with:
- Stale time: 60 seconds (reduces network calls)
- Cache time: 7 days in localStorage
- Offline-first mode (uses cached data when offline)
- Conditional refetches disabled by default
- Persistence: LocalStorage via
@tanstack/query-sync-storage-persister
Wagmi Setup (/src/wagmi.ts):
- Network: Ethereum mainnet only (chain sync disabled)
- RPC Endpoints: Multi-endpoint fallback with batching
- DRPC (primary) - Batches up to 100 requests within 10ms, 1MB max batch size
- Alchemy (fallback)
- Cloudflare (final fallback)
- Wallet Connectors: Via RainbowKit (Farcaster Frame, injected, Coinbase, MetaMask)
- Features: Auto-reconnect on mount
Contract ABIs (/src/constants/):
- ZAMM (zAMM protocol)
- zCurve (bonding curve)
- ZRouter (routing)
- Prediction Markets
- Farming contracts (zChef)
- ICO contracts
- Wrapping contracts (ERC6909)
- Uniswap Universal Router
- Chainlink Aggregators
/src/components/- React components/ui/- Radix UI-based primitives/ui/8bit/- Retro/8-bit styled components/explorer/- Token/pool exploration/pools/- Liquidity pool components/swap/- Swap interface/trade/- Trading components/farm/- Farming interface/predict/- Prediction market/raise/- Token launch forms/create/- Token creation
/src/routes/- TanStack Router file-based routes/src/hooks/- Custom React hooks (20+ hooks for data fetching, transactions, etc.)/src/lib/- Utility functions and helpersutils.ts- cn(), formatNumber(), formatting utilitiestheme.tsx- Theme context providerzCurveClientCalc.ts- zCurve protocol calculationszrouter.ts- ZRouter protocol utilitiespools.ts- Pool managementswap.ts- Swap logicaddress.ts- Address utilitiesConnectionErrorHandler.tsx- Web3 error handling
/src/constants/- Contract ABIs & addresses (28+ files)/src/types/- TypeScript type definitions/src/contexts/- React context providers/src/i18n/- Internationalization setup/locales/en.json- English translations (~1000+ keys)/locales/zh.json- Chinese translations
/src/styles/- Global styles/src/index.css- Tailwind imports + CSS custom properties/src/wagmi.ts- Wagmi configuration/src/main.tsx- React entry point
Use Radix UI primitives with Tailwind classes and CVA for variants:
import { cva } from "class-variance-authority";
import { cn } from "@/lib/utils";
const buttonVariants = cva(
"inline-flex items-center justify-center",
{
variants: {
variant: { default: "...", ghost: "..." },
size: { default: "h-9", sm: "h-8" }
},
defaultVariants: { variant: "default", size: "default" }
}
);
export const Button = forwardRef(({ variant, size, className, ...props }, ref) => (
<button
className={cn(buttonVariants({ variant, size }), className)}
ref={ref}
{...props}
/>
));Create custom hooks in /src/hooks/ following this pattern:
import { useQuery } from "@tanstack/react-query";
export const useCoinPrice = ({ token }: { token?: Token }) => {
return useQuery({
queryKey: ["coin-price", token?.id?.toString()],
queryFn: async () => {
// fetch logic
},
enabled: !!token, // Conditional query
staleTime: 60_000, // 60 seconds
});
};Important: React Query is configured with:
- 60-second stale time by default
- Offline-first mode
- Persistent caching in localStorage
Create route files in /src/routes/ following this pattern:
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute('/swap')({
component: SwapPage,
errorComponent: ErrorBoundary,
});
function SwapPage() {
const navigate = Route.useNavigate();
const params = Route.useParams();
return <div>...</div>;
}Critical: Always use TanStack Router hooks (useNavigate, useParams, etc.), NOT react-router hooks.
Use Wagmi hooks for blockchain interactions:
import { useAccount, useWriteContract, useWaitForTransactionReceipt } from "wagmi";
import { CONTRACT_ABI } from "@/constants/MyContract";
const { address } = useAccount();
const { writeContract, data: hash } = useWriteContract();
const { isLoading, isSuccess } = useWaitForTransactionReceipt({ hash });
const handleSwap = async () => {
writeContract({
address: CONTRACT_ADDRESS,
abi: CONTRACT_ABI,
functionName: 'swap',
args: [...]
});
};Pattern: All contract ABIs are in /src/constants/, reference them there.
- Use Tailwind classes for styling
- Dark mode is class-based (
.darkon<html>) - CSS custom properties for theming:
- Colors:
--background,--foreground,--accent,--destructive, etc. - Typography:
--font-sans,--font-mono,--font-display
- Colors:
- Use
cn()utility from@/lib/utilsto merge classes - Access theme via
useTheme()hook from@/lib/theme
Always use translation keys, never hardcoded text:
import { useTranslation } from 'react-i18next';
const { t } = useTranslation();
const text = t('common.swap'); // Dot notation for nested keysTranslation Files: /src/i18n/locales/en.json and /src/i18n/locales/zh.json
Supported Languages: English (en), Chinese (zh)
Features: Auto-detection via query string, cookie, localStorage, or navigator
- Code Splitting: TanStack Router automatically code-splits routes
- RPC Batching: Wagmi batches blockchain calls (max 100 requests per 10ms)
- Query Caching: React Query caches for 7 days in localStorage
- Conditional Queries: Always use
enabledflag to prevent unnecessary fetches
- vite.config.ts: TanStack Router plugin MUST come before React plugin
- tsconfig.json: Strict mode enabled, path alias
@→./src - tailwind.config.js: Dark mode class-based, custom Diamond colors
- biome.json: 120-char line width, enabled linter & formatter
- package.json: Must use pnpm (has overrides for security patches)