Skip to content

Latest commit

 

History

History
1903 lines (1662 loc) · 62.1 KB

File metadata and controls

1903 lines (1662 loc) · 62.1 KB

🚀 MEGA PLAN: PakoMarket Market Details Page - Complete Implementation Strategy

📋 Executive Summary

Transform the current prototype market details page into a production-ready, contract-integrated component that serves as the cornerstone of the PakoMarket prediction market platform. This plan combines architectural excellence, Web3 integration, and user experience optimization into a systematic 4-week implementation roadmap.

🎯 Strategic Objectives

Primary Goals:

  1. Contract-Ready Trading: Full integration with smart contracts and USDC
  2. Production Architecture: Scalable, maintainable, and testable codebase
  3. Exceptional UX: Intuitive, accessible, and performant user experience
  4. Security-First: Robust validation, error handling, and safety measures

Success Metrics:

  • Zero precision errors in financial calculations
  • Sub-2s page load times with proper caching
  • 100% accessibility compliance (WCAG 2.1 AA)
  • Full trading flow from approval to settlement

🛡️ Risk Mitigation Strategy

Core Risk Mitigation Principles:

  1. Start with Mock Data: Get UI working before contract integration
  2. Incremental Testing: Test each component as you build it
  3. Fallback Strategies: Graceful degradation when Web3 features fail

Implementation Approach:

  • Phase 1: Mock data + UI components (Week 1)
  • Phase 2: Contract integration with fallbacks (Week 2)
  • Phase 3: Real-time features + optimization (Week 3)
  • Phase 4: Testing + production polish (Week 4)

Fallback Strategies:

  • Web3 Unavailable: Show "Connect Wallet" prompts with mock data
  • Contract Errors: Display user-friendly error messages with retry options
  • Network Issues: Graceful degradation to read-only mode
  • Transaction Failures: Clear error messages with suggested actions

🏗️ PHASE 1: FOUNDATION & ARCHITECTURE (Week 1)

🔧 Day 1-2: Component Architecture Overhaul

1.1 File Structure Implementation

apps/web/src/app/market/[id]/
├── page.tsx                    # Server component with data fetching
├── loading.tsx                 # Loading UI (Next.js convention)
├── error.tsx                   # Error boundary (Next.js convention)
├── not-found.tsx              # 404 page (Next.js convention)
├── components/
   ├── MarketHeader.tsx        # Title, volume, close time, status
   ├── MarketBreadcrumb.tsx    # Navigation breadcrumb
   ├── ProbabilityChart.tsx    # Historical price chart
   ├── OutcomeSelector.tsx     # Yes/No outcome selection
   ├── TradePanel.tsx          # Trading interface
   ├── RelatedMarkets.tsx      # Suggested markets
   ├── MarketDetails.tsx       # Market description, rules
   └── skeletons/
       ├── MarketHeaderSkeleton.tsx
       ├── ChartSkeleton.tsx
       └── TradePanelSkeleton.tsx
├── hooks/
   ├── useMarketData.ts        # Market data fetching & caching
   ├── useTrading.ts           # Trading state management
   ├── useUSDCAllowance.ts     # USDC approval flow
   ├── usePriceQuotes.ts       # Real-time price quotes
   └── useMarketValidation.ts  # Market ID & state validation
├── utils/
   ├── formatting.ts           # Number, currency, date formatters
   ├── validation.ts           # Zod schemas for all inputs
   ├── calculations.ts         # Financial math with bigint
   └── constants.ts            # Trading constants & limits
└── types/
    ├── market.ts              # Market data interfaces
    ├── trading.ts             # Trading-related types
    └── api.ts                 # API response types

1.2 TypeScript Interface Design

// types/market.ts
export interface Market {
  id: string;
  title: string;
  description: string;
  endDate: Date;
  volume: bigint;           // USDC volume in wei (6 decimals)
  liquidity: bigint;        // Total liquidity
  status: MarketStatus;
  outcomes: Outcome[];
  metadata: {
    creator: Address;
    createdAt: Date;
    category: string;
    tags: string[];
    ipfsHash?: string;
  };
}

export interface Outcome {
  id: string;
  name: string;
  probability: number;      // 0-1 float for display only
  price: bigint;           // Actual price in wei
  volume: bigint;          // Volume in USDC wei
  shares: bigint;          // Total shares outstanding
}

export type MarketStatus = 'Open' | 'Closed' | 'Paused' | 'Resolved' | 'Invalid';

1.3 Server Component Architecture

// app/market/[id]/page.tsx
import { Suspense } from 'react';
import { notFound } from 'next/navigation';
import { MarketHeader } from './components/MarketHeader';
import { MarketContent } from './components/MarketContent';
import { validateMarketId } from './utils/validation';

export default async function MarketPage({
  params
}: {
  params: { id: string }
}) {
  // Server-side validation
  const { success, data: marketId } = validateMarketId(params.id);
  if (!success) notFound();

  // Server-side data fetching (eventually from API)
  const market = await getMarketData(marketId);
  if (!market) notFound();

  return (
    <div className="min-h-screen bg-gray-50 dark:bg-[#0b1220]">
      <MarketHeader market={market} />
      <Suspense fallback={<MarketContentSkeleton />}>
        <MarketContent marketId={marketId} initialData={market} />
      </Suspense>
    </div>
  );
}

🎨 Day 3-4: UX Foundation & Navigation

2.1 Navigation System

// components/MarketBreadcrumb.tsx
export function MarketBreadcrumb({ market }: { market: Market }) {
  return (
    <nav className="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400 mb-4">
      <Link
        href="/"
        className="hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
      >
        Markets
      </Link>
      <ChevronRight className="w-4 h-4" />
      <Link
        href={`/?category=${market.metadata.category}`}
        className="hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
      >
        {market.metadata.category}
      </Link>
      <ChevronRight className="w-4 h-4" />
      <span className="text-gray-900 dark:text-gray-100 font-medium truncate">
        {market.title}
      </span>
    </nav>
  );
}

2.2 Market Status System

// components/MarketStatusBanner.tsx
export function MarketStatusBanner({ market }: { market: Market }) {
  const statusConfig = {
    Open: {
      bg: 'bg-green-50 dark:bg-green-900/20',
      text: 'text-green-700 dark:text-green-400',
      icon: <TrendingUp className="w-4 h-4" />
    },
    Closed: {
      bg: 'bg-gray-50 dark:bg-gray-800',
      text: 'text-gray-700 dark:text-gray-300',
      icon: <Clock className="w-4 h-4" />
    },
    Resolved: {
      bg: 'bg-blue-50 dark:bg-blue-900/20',
      text: 'text-blue-700 dark:text-blue-400',
      icon: <CheckCircle className="w-4 h-4" />
    },
    // ... other statuses
  };

  const config = statusConfig[market.status];
  const timeLeft = getTimeLeft(market.endDate);

  return (
    <div className={`${config.bg} border border-opacity-20 rounded-lg p-4 mb-6`}>
      <div className="flex items-center justify-between">
        <div className={`flex items-center gap-2 ${config.text}`}>
          {config.icon}
          <span className="font-medium">{market.status}</span>
          {market.status === 'Open' && timeLeft && (
            <span className="text-sm"> Closes {timeLeft}</span>
          )}
        </div>
        {market.status === 'Resolved' && (
          <div className="text-sm">
            Resolved: <strong>{getResolutionOutcome(market)}</strong>
          </div>
        )}
      </div>
    </div>
  );
}

2.3 Loading States & Skeletons

// components/skeletons/MarketHeaderSkeleton.tsx
export function MarketHeaderSkeleton() {
  return (
    <div className="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-700">
      <div className="max-w-7xl mx-auto px-4 py-6">
        <div className="animate-pulse">
          <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-1/3 mb-4"></div>
          <div className="h-8 bg-gray-200 dark:bg-gray-700 rounded w-2/3 mb-4"></div>
          <div className="flex gap-6 mb-4">
            <div className="h-6 bg-gray-200 dark:bg-gray-700 rounded w-24"></div>
            <div className="h-6 bg-gray-200 dark:bg-gray-700 rounded w-32"></div>
            <div className="h-6 bg-gray-200 dark:bg-gray-700 rounded w-28"></div>
          </div>
        </div>
      </div>
    </div>
  );
}

🧮 Day 5-7: Decimal Precision & Math Foundation

3.3 Phase 1 Checklist

## **PHASE 1 COMPLETION CHECKLIST**

### **File Structure & Architecture**
- [ ] Created `/apps/web/src/app/market/[id]/` directory structure
- [ ] Implemented `page.tsx` as server component
- [ ] Created `loading.tsx`, `error.tsx`, `not-found.tsx` pages
- [ ] Set up component directory with proper organization
- [ ] Created hooks directory for custom hooks
- [ ] Set up utils directory for helper functions
- [ ] Created types directory for TypeScript interfaces

### **Component Extraction**
- [ ] Extracted `MarketHeader.tsx` from monolithic file
- [ ] Extracted `ProbabilityChart.tsx` (with placeholder)
- [ ] Extracted `OutcomeSelector.tsx` for Yes/No selection
- [ ] Extracted `TradePanel.tsx` for trading interface
- [ ] Extracted `RelatedMarkets.tsx` for suggestions
- [ ] Created skeleton components for loading states
- [ ] All components have proper TypeScript interfaces

### **Decimal Precision & Math**
- [ ] Created `FinancialMath` utility class
- [ ] Implemented `toUSDCWei()` and `fromUSDCWei()` functions
- [ ] Added `calculateSharesOut()` with slippage protection
- [ ] Added `calculateUSDCIn()` for reverse calculations
- [ ] Implemented `formatUSDC()` and `formatShares()` helpers
- [ ] All money calculations use `bigint` instead of `number`
- [ ] Added input validation with Zod schemas

### **Mock Data Integration**
- [ ] Created comprehensive mock market data
- [ ] Implemented proper TypeScript interfaces for all data
- [ ] Added mock historical data for charts
- [ ] Created mock related markets data
- [ ] All mock data uses proper `bigint` values
- [ ] Mock data structure matches real API structure

### **Basic UI/UX**
- [ ] Implemented responsive design (mobile-first)
- [ ] Added dark/light mode support throughout
- [ ] Created proper loading states and skeletons
- [ ] Added basic error handling and display
- [ ] Implemented proper navigation breadcrumbs
- [ ] Added market status banners (Open/Closed/Resolved)
- [ ] All components are accessible (basic a11y)

### **Testing Foundation**
- [ ] Set up testing environment (Vitest + React Testing Library)
- [ ] Created unit tests for `FinancialMath` utility
- [ ] Added component tests for basic rendering
- [ ] Implemented mock data testing
- [ ] Added input validation testing
- [ ] All critical paths have test coverage

### **Code Quality**
- [ ] All components under 200 lines
- [ ] Proper TypeScript types throughout
- [ ] No `any` types used
- [ ] Consistent naming conventions
- [ ] Proper error boundaries
- [ ] Clean, readable code structure

### **Performance Basics**
- [ ] Components are properly memoized where needed
- [ ] No unnecessary re-renders
- [ ] Proper key props for lists
- [ ] Images are optimized
- [ ] Bundle size is reasonable (< 200KB for this phase)

### **Documentation**
- [ ] All components have JSDoc comments
- [ ] README updated with new structure
- [ ] TypeScript interfaces are well documented
- [ ] Utility functions have usage examples
- [ ] Component props are documented

### **Phase 1 Success Criteria**
- [ ] Market details page loads with mock data
- [ ] All components render without errors
- [ ] Responsive design works on mobile and desktop
- [ ] Dark/light mode switching works
- [ ] Basic trading interface is functional (UI only)
- [ ] All tests pass
- [ ] No TypeScript errors
- [ ] Performance is acceptable (< 2s load time)

3.1 Financial Calculations Utility

// utils/calculations.ts
import { parseUnits, formatUnits } from 'viem';

export const USDC_DECIMALS = 6;
export const SHARE_DECIMALS = 18;
export const PRECISION_MULTIPLIER = 10n ** 18n;

export class FinancialMath {
  // Convert display amount to blockchain amount
  static toUSDCWei(amount: string | number): bigint {
    if (typeof amount === 'number') {
      if (!Number.isFinite(amount) || amount < 0) {
        throw new Error('Invalid amount');
      }
      amount = amount.toString();
    }
    return parseUnits(amount, USDC_DECIMALS);
  }

  // Convert blockchain amount to display amount
  static fromUSDCWei(wei: bigint): string {
    return formatUnits(wei, USDC_DECIMALS);
  }

  // Calculate shares received for USDC amount
  static calculateSharesOut(
    usdcIn: bigint,
    currentPrice: bigint,
    slippageTolerance: number = 0.01 // 1%
  ): { sharesOut: bigint; minSharesOut: bigint } {
    const sharesOut = (usdcIn * PRECISION_MULTIPLIER) / currentPrice;
    const slippageAmount = (sharesOut * BigInt(Math.floor(slippageTolerance * 10000))) / 10000n;
    const minSharesOut = sharesOut - slippageAmount;

    return { sharesOut, minSharesOut };
  }

  // Calculate USDC needed for desired shares
  static calculateUSDCIn(
    sharesDesired: bigint,
    currentPrice: bigint
  ): bigint {
    return (sharesDesired * currentPrice) / PRECISION_MULTIPLIER;
  }

  // Price impact calculation
  static calculatePriceImpact(
    usdcAmount: bigint,
    liquidity: bigint
  ): number {
    if (liquidity === 0n) return 0;
    const impact = Number(usdcAmount * 10000n / liquidity) / 100; // Convert to percentage
    return Math.min(impact, 100); // Cap at 100%
  }

  // Format for display with proper decimal places
  static formatUSDC(wei: bigint, decimals: number = 2): string {
    const amount = Number(formatUnits(wei, USDC_DECIMALS));
    return new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency: 'USD',
      minimumFractionDigits: decimals,
      maximumFractionDigits: decimals,
    }).format(amount);
  }

  static formatShares(shares: bigint, decimals: number = 4): string {
    const amount = Number(formatUnits(shares, SHARE_DECIMALS));
    return new Intl.NumberFormat('en-US', {
      minimumFractionDigits: decimals,
      maximumFractionDigits: decimals,
    }).format(amount);
  }

  static formatPercentage(value: number, decimals: number = 1): string {
    return new Intl.NumberFormat('en-US', {
      style: 'percent',
      minimumFractionDigits: decimals,
      maximumFractionDigits: decimals,
    }).format(value / 100);
  }
}

3.2 Input Validation System

// utils/validation.ts
import { z } from 'zod';
import { isAddress } from 'viem';

export const MarketIdSchema = z.string().uuid().or(z.string().min(1));

export const TradeAmountSchema = z.object({
  amount: z.string()
    .refine((val) => !isNaN(Number(val)) && Number(val) > 0, "Amount must be positive")
    .refine((val) => Number(val) >= 0.01, "Minimum amount is $0.01")
    .refine((val) => Number(val) <= 10000, "Maximum amount is $10,000")
    .transform((val) => FinancialMath.toUSDCWei(val)),
  slippage: z.number()
    .min(0.001, "Minimum slippage is 0.1%")
    .max(0.5, "Maximum slippage is 50%")
    .default(0.01),
  deadline: z.number()
    .min(60, "Minimum deadline is 1 minute")
    .max(3600, "Maximum deadline is 1 hour")
    .default(1200), // 20 minutes
});

export const AddressSchema = z.string().refine(isAddress, "Invalid Ethereum address");

export function validateMarketId(id: string) {
  return MarketIdSchema.safeParse(id);
}

export function validateTradeParams(params: unknown) {
  return TradeAmountSchema.safeParse(params);
}

PHASE 2: WEB3 INTEGRATION (Week 2)

🔗 Day 8-10: Smart Contract Integration

4.1 Trading Hooks Architecture

// hooks/useUSDCAllowance.ts
import { useAccount, useReadContract, useWriteContract } from 'wagmi';
import { erc20Abi } from 'viem';
import { config } from '@/lib/config';

export function useUSDCAllowance(spender: Address) {
  const { address } = useAccount();

  // Read current allowance
  const { data: allowance, isLoading, refetch } = useReadContract({
    address: config.contracts.USDC as Address,
    abi: erc20Abi,
    functionName: 'allowance',
    args: address && spender ? [address, spender] : undefined,
    query: { enabled: Boolean(address && spender) }
  });

  // Write contract for approval
  const { writeContract: approve, isPending: isApproving } = useWriteContract();

  const approveUSDC = useCallback(async (amount: bigint) => {
    if (!address || !spender) throw new Error('No address or spender');

    return approve({
      address: config.contracts.USDC as Address,
      abi: erc20Abi,
      functionName: 'approve',
      args: [spender, amount],
    });
  }, [approve, address, spender]);

  const needsApproval = useCallback((amount: bigint) => {
    return !allowance || allowance < amount;
  }, [allowance]);

  return {
    allowance: allowance || 0n,
    approveUSDC,
    isApproving,
    needsApproval,
    refetch,
    isLoading,
  };
}

4.2 Trading State Management

// hooks/useTrading.ts
import { useState, useCallback } from 'react';
import { useAccount, useWriteContract, useWaitForTransactionReceipt } from 'wagmi';
import { toast } from 'sonner';

export type TradeState = 'idle' | 'approving' | 'trading' | 'confirming' | 'success' | 'error';

export function useTrading(marketAddress: Address) {
  const { address, chainId } = useAccount();
  const [tradeState, setTradeState] = useState<TradeState>('idle');
  const [txHash, setTxHash] = useState<Hash>();
  const [error, setError] = useState<string>();

  const { allowance, approveUSDC, needsApproval } = useUSDCAllowance(marketAddress);
  const { writeContract: trade } = useWriteContract();

  const { isLoading: isConfirming } = useWaitForTransactionReceipt({
    hash: txHash,
    onSuccess: () => {
      setTradeState('success');
      toast.success('Trade completed successfully!');
    },
    onError: (error) => {
      setTradeState('error');
      setError(error.message);
      toast.error('Trade failed');
    }
  });

  const executeTrade = useCallback(async (params: {
    outcome: 'yes' | 'no';
    amount: bigint;
    minSharesOut: bigint;
    deadline: number;
  }) => {
    try {
      setError(undefined);

      // Validate chain
      if (chainId !== config.local.chainId) {
        throw new Error('Please switch to the correct network');
      }

      // Check approval first
      if (needsApproval(params.amount)) {
        setTradeState('approving');
        toast.info('Approving USDC...');
        await approveUSDC(params.amount);
        // Wait for approval to be mined before continuing
        await new Promise(resolve => setTimeout(resolve, 2000));
      }

      // Execute trade
      setTradeState('trading');
      toast.info('Executing trade...');

      const hash = await trade({
        address: marketAddress,
        abi: marketAbi, // Import your market ABI
        functionName: 'buyShares',
        args: [
          params.outcome === 'yes' ? 0 : 1, // outcome index
          params.amount,
          params.minSharesOut,
          BigInt(Math.floor(Date.now() / 1000) + params.deadline)
        ],
      });

      setTxHash(hash);
      setTradeState('confirming');
      toast.info('Confirming transaction...');

    } catch (err) {
      setTradeState('error');
      const errorMessage = err instanceof Error ? err.message : 'Trade failed';
      setError(errorMessage);
      toast.error(errorMessage);
    }
  }, [chainId, marketAddress, needsApproval, approveUSDC, trade]);

  const reset = useCallback(() => {
    setTradeState('idle');
    setError(undefined);
    setTxHash(undefined);
  }, []);

  return {
    tradeState,
    error,
    txHash,
    isConfirming,
    executeTrade,
    reset,
    canTrade: address && chainId === config.local.chainId,
  };
}

4.3 Real-time Price Quotes

// hooks/usePriceQuotes.ts
import { useEffect, useState } from 'react';
import { useBlockNumber } from 'wagmi';

export function usePriceQuotes(marketAddress: Address, refreshInterval: number = 30000) {
  const [quotes, setQuotes] = useState<{
    yes: { price: bigint; priceImpact: number };
    no: { price: bigint; priceImpact: number };
  }>();

  const { data: blockNumber } = useBlockNumber({ watch: true });

  const fetchQuotes = useCallback(async (amount: bigint) => {
    if (!marketAddress || amount === 0n) return;

    try {
      // This would call your contract's getQuote function
      const [yesQuote, noQuote] = await Promise.all([
        getQuote(marketAddress, 'yes', amount),
        getQuote(marketAddress, 'no', amount),
      ]);

      setQuotes({
        yes: yesQuote,
        no: noQuote,
      });
    } catch (error) {
      console.error('Failed to fetch quotes:', error);
    }
  }, [marketAddress]);

  // Refresh quotes on new blocks
  useEffect(() => {
    if (blockNumber) {
      fetchQuotes(parseUnits('100', 6)); // Default quote for $100
    }
  }, [blockNumber, fetchQuotes]);

  return { quotes, fetchQuotes };
}

🌐 Day 11-12: Network & Chain Management

5.1 Chain Validation System

// hooks/useChainValidation.ts
export function useChainValidation() {
  const { chainId, switchChain } = useSwitchChain();
  const targetChainId = config.local.chainId;

  const isCorrectChain = chainId === targetChainId;
  const isUnsupported = chainId && !isCorrectChain;

  const switchToCorrectChain = useCallback(async () => {
    try {
      await switchChain({ chainId: targetChainId });
      toast.success('Switched to correct network');
    } catch (error) {
      toast.error('Failed to switch network');
      throw error;
    }
  }, [switchChain, targetChainId]);

  return {
    isCorrectChain,
    isUnsupported,
    switchToCorrectChain,
    currentChainId: chainId,
    targetChainId,
  };
}

5.2 Network Status Component

// components/NetworkStatus.tsx
export function NetworkStatus() {
  const { isCorrectChain, isUnsupported, switchToCorrectChain } = useChainValidation();
  const { isConnected } = useAccount();

  if (!isConnected) return null;

  if (isUnsupported) {
    return (
      <div className="bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-700 rounded-lg p-4 mb-6">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-2 text-yellow-700 dark:text-yellow-400">
            <AlertTriangle className="w-5 h-5" />
            <span className="font-medium">Wrong Network</span>
            <span className="text-sm">Please switch to Localhost 8545</span>
          </div>
          <button
            onClick={switchToCorrectChain}
            className="px-4 py-2 bg-yellow-600 hover:bg-yellow-700 text-white rounded-lg text-sm font-medium transition-colors"
          >
            Switch Network
          </button>
        </div>
      </div>
    );
  }

  if (isCorrectChain) {
    return (
      <div className="bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-700 rounded-lg p-3 mb-6">
        <div className="flex items-center gap-2 text-green-700 dark:text-green-400">
          <CheckCircle className="w-4 h-4" />
          <span className="text-sm">Connected to Localhost 8545</span>
        </div>
      </div>
    );
  }

  return null;
}

📊 Day 13-14: Data Integration & Caching

6.2 Phase 2 Checklist

## **PHASE 2 COMPLETION CHECKLIST**

### **Web3 Integration**
- [ ] Implemented `useUSDCAllowance` hook
- [ ] Created `useTrading` hook with full trading flow
- [ ] Added `usePriceQuotes` hook for real-time quotes
- [ ] Implemented `useChainValidation` hook
- [ ] Added proper error handling for all Web3 operations
- [ ] Created fallback strategies for Web3 failures
- [ ] All hooks have proper TypeScript types

### **Trading Flow Implementation**
- [ ] USDC approval flow works correctly
- [ ] Buy/Sell transactions execute properly
- [ ] Slippage protection is implemented
- [ ] Transaction monitoring and status updates
- [ ] Error handling for failed transactions
- [ ] Success/failure notifications to users
- [ ] Proper loading states during transactions

### **Chain Management**
- [ ] Network validation works correctly
- [ ] Network switching functionality
- [ ] Wrong network warnings and prompts
- [ ] Chain ID validation for all operations
- [ ] Graceful handling of unsupported networks
- [ ] User-friendly network status indicators

### **Real-time Data**
- [ ] Price quotes update in real-time
- [ ] Market data refreshes automatically
- [ ] Proper caching with React Query
- [ ] Optimistic updates for better UX
- [ ] Error handling for data fetch failures
- [ ] Fallback to cached data when needed

### **Contract Integration**
- [ ] All contract calls use proper ABI
- [ ] Gas estimation for transactions
- [ ] Transaction confirmation handling
- [ ] Event listening for real-time updates
- [ ] Proper error parsing from contract calls
- [ ] Fallback strategies for contract failures

### **Security & Validation**
- [ ] All user inputs validated with Zod
- [ ] Decimal precision handled with bigint
- [ ] No client-side private key exposure
- [ ] Proper error handling without data leakage
- [ ] XSS protection on all dynamic content
- [ ] Input sanitization for all user data

### **Testing & Quality**
- [ ] Unit tests for all Web3 hooks
- [ ] Integration tests for trading flow
- [ ] Error handling tests for all failure scenarios
- [ ] Mock Web3 provider for testing
- [ ] Contract interaction tests
- [ ] Performance tests for real-time updates

### **Fallback Strategies**
- [ ] Web3 unavailable: Show connect wallet prompts
- [ ] Contract errors: Display user-friendly messages
- [ ] Network issues: Graceful degradation to read-only
- [ ] Transaction failures: Clear error messages with retry
- [ ] Data fetch failures: Show cached data with refresh option
- [ ] All fallbacks tested and working

### **Phase 2 Success Criteria**
- [ ] Full trading flow works end-to-end
- [ ] USDC approval and trading execute correctly
- [ ] Real-time price updates work
- [ ] Network switching functions properly
- [ ] Error handling is comprehensive
- [ ] All fallback strategies work
- [ ] Performance is maintained (< 2s load time)
- [ ] All tests pass
- [ ] No TypeScript errors

6.1 Market Data Fetching

// hooks/useMarketData.ts
import { useQuery, useQueryClient } from '@tanstack/react-query';

export function useMarketData(marketId: string) {
  return useQuery({
    queryKey: ['market', marketId],
    queryFn: async () => {
      // For now, use mock data but structure for API integration
      const market = mockMarkets.find(m => m.id === marketId);
      if (!market) throw new Error('Market not found');

      // Transform mock data to proper format
      return {
        ...market,
        volume: FinancialMath.toUSDCWei(market.poolUsd.toString()),
        outcomes: market.outcomes?.map(outcome => ({
          ...outcome,
          price: FinancialMath.toUSDCWei((outcome.price || 0.5).toString()),
          volume: FinancialMath.toUSDCWei((outcome.volume || 0).toString()),
          shares: parseUnits('1000000', SHARE_DECIMALS), // Mock shares
        })) || [],
      };
    },
    staleTime: 1000 * 60 * 5, // 5 minutes
    refetchInterval: 1000 * 30, // 30 seconds
    retry: 3,
  });
}

export function useMarketList() {
  return useQuery({
    queryKey: ['markets'],
    queryFn: async () => {
      // Transform all mock markets
      return mockMarkets.map(market => ({
        ...market,
        volume: FinancialMath.toUSDCWei(market.poolUsd.toString()),
      }));
    },
    staleTime: 1000 * 60 * 2, // 2 minutes
  });
}

🎨 PHASE 3: UX EXCELLENCE (Week 3)

💫 Day 15-17: Advanced UI Components

7.1 Trading Panel Component

// components/TradePanel.tsx
export function TradePanel({ market }: { market: Market }) {
  const [selectedOutcome, setSelectedOutcome] = useState<'yes' | 'no'>('yes');
  const [amount, setAmount] = useState<string>('');
  const [slippage, setSlippage] = useState<number>(0.01); // 1%
  const [showAdvanced, setShowAdvanced] = useState<boolean>(false);

  const { isConnected, address } = useAccount();
  const { isCorrectChain, switchToCorrectChain } = useChainValidation();
  const { executeTrade, tradeState, error, canTrade } = useTrading(market.address);
  const { quotes, fetchQuotes } = usePriceQuotes(market.address);

  // Real-time quote updates
  const debouncedAmount = useDebounce(amount, 500);
  useEffect(() => {
    if (debouncedAmount && parseFloat(debouncedAmount) > 0) {
      fetchQuotes(FinancialMath.toUSDCWei(debouncedAmount));
    }
  }, [debouncedAmount, fetchQuotes]);

  const handleTrade = useCallback(async () => {
    if (!amount || !quotes) return;

    try {
      const parsedAmount = FinancialMath.toUSDCWei(amount);
      const quote = quotes[selectedOutcome];
      const { minSharesOut } = FinancialMath.calculateSharesOut(
        parsedAmount,
        quote.price,
        slippage
      );

      await executeTrade({
        outcome: selectedOutcome,
        amount: parsedAmount,
        minSharesOut,
        deadline: 1200, // 20 minutes
      });
    } catch (err) {
      console.error('Trade failed:', err);
    }
  }, [amount, quotes, selectedOutcome, slippage, executeTrade]);

  const isValidAmount = amount && parseFloat(amount) >= 0.01 && parseFloat(amount) <= 10000;
  const quote = quotes?.[selectedOutcome];

  return (
    <div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6">
      <div className="flex justify-between items-center mb-6">
        <h3 className="text-lg font-semibold">Trade</h3>
        <button
          onClick={() => setShowAdvanced(!showAdvanced)}
          className="text-sm text-gray-500 hover:text-gray-700 dark:hover:text-gray-300"
        >
          {showAdvanced ? 'Simple' : 'Advanced'}
        </button>
      </div>

      {/* Network Status */}
      {isConnected && !isCorrectChain && (
        <div className="bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-700 rounded-lg p-3 mb-4">
          <div className="flex items-center justify-between">
            <span className="text-yellow-700 dark:text-yellow-400 text-sm">Wrong network</span>
            <button
              onClick={switchToCorrectChain}
              className="text-yellow-700 dark:text-yellow-400 text-sm underline hover:no-underline"
            >
              Switch
            </button>
          </div>
        </div>
      )}

      {/* Outcome Selection */}
      <div className="grid grid-cols-2 gap-2 mb-6">
        {['yes', 'no'].map((outcome) => (
          <button
            key={outcome}
            onClick={() => setSelectedOutcome(outcome as 'yes' | 'no')}
            className={`p-3 rounded-lg border-2 transition-all ${
              selectedOutcome === outcome
                ? 'border-blue-500 bg-blue-50 dark:bg-blue-900/20'
                : 'border-gray-200 dark:border-gray-600 hover:border-gray-300 dark:hover:border-gray-500'
            }`}
          >
            <div className="text-sm font-medium capitalize">{outcome}</div>
            <div className="text-xs text-gray-500 dark:text-gray-400">
              {FinancialMath.formatUSDC(
                market.outcomes.find(o => o.name.toLowerCase() === outcome)?.price || 0n
              )}
            </div>
          </button>
        ))}
      </div>

      {/* Amount Input */}
      <div className="mb-4">
        <label className="block text-sm font-medium mb-2">Amount (USDC)</label>
        <div className="relative">
          <span className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500">$</span>
          <input
            type="number"
            value={amount}
            onChange={(e) => setAmount(e.target.value)}
            placeholder="0.00"
            min="0.01"
            max="10000"
            step="0.01"
            className="w-full pl-8 pr-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-700"
          />
        </div>
        <div className="flex justify-between text-xs text-gray-500 dark:text-gray-400 mt-1">
          <span>Min: $0.01</span>
          <span>Max: $10,000</span>
        </div>
      </div>

      {/* Quick Amount Buttons */}
      <div className="grid grid-cols-4 gap-2 mb-6">
        {['10', '50', '100', '500'].map((quickAmount) => (
          <button
            key={quickAmount}
            onClick={() => setAmount(quickAmount)}
            className="py-2 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
          >
            ${quickAmount}
          </button>
        ))}
      </div>

      {/* Advanced Settings */}
      {showAdvanced && (
        <div className="mb-6 p-4 bg-gray-50 dark:bg-gray-700 rounded-lg">
          <div className="mb-4">
            <label className="block text-sm font-medium mb-2">
              Slippage Tolerance: {FinancialMath.formatPercentage(slippage * 100)}
            </label>
            <input
              type="range"
              min="0.001"
              max="0.1"
              step="0.001"
              value={slippage}
              onChange={(e) => setSlippage(parseFloat(e.target.value))}
              className="w-full"
            />
            <div className="flex justify-between text-xs text-gray-500 dark:text-gray-400 mt-1">
              <span>0.1%</span>
              <span>10%</span>
            </div>
          </div>
        </div>
      )}

      {/* Trade Preview */}
      {isValidAmount && quote && (
        <div className="bg-gray-50 dark:bg-gray-700 rounded-lg p-4 mb-6">
          <div className="space-y-2 text-sm">
            <div className="flex justify-between">
              <span>You pay</span>
              <span className="font-medium">${amount} USDC</span>
            </div>
            <div className="flex justify-between">
              <span>You receive</span>
              <span className="font-medium">
                {FinancialMath.formatShares(
                  FinancialMath.calculateSharesOut(
                    FinancialMath.toUSDCWei(amount),
                    quote.price
                  ).sharesOut
                )} shares
              </span>
            </div>
            <div className="flex justify-between">
              <span>Price impact</span>
              <span className={quote.priceImpact > 5 ? 'text-red-500' : 'text-gray-600 dark:text-gray-400'}>
                {FinancialMath.formatPercentage(quote.priceImpact)}
              </span>
            </div>
          </div>
        </div>
      )}

      {/* Trade Button */}
      <button
        onClick={handleTrade}
        disabled={!canTrade || !isValidAmount || tradeState !== 'idle'}
        className="w-full py-3 px-4 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed text-white rounded-lg font-medium transition-colors"
      >
        {!isConnected && 'Connect Wallet'}
        {isConnected && !isCorrectChain && 'Switch Network'}
        {canTrade && tradeState === 'idle' && 'Place Trade'}
        {tradeState === 'approving' && 'Approving USDC...'}
        {tradeState === 'trading' && 'Trading...'}
        {tradeState === 'confirming' && 'Confirming...'}
        {tradeState === 'success' && 'Trade Complete!'}
        {tradeState === 'error' && 'Try Again'}
      </button>

      {/* Error Display */}
      {error && (
        <div className="mt-4 p-3 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-700 rounded-lg">
          <p className="text-red-700 dark:text-red-400 text-sm">{error}</p>
        </div>
      )}

      {/* Connect Wallet CTA */}
      {!isConnected && (
        <div className="mt-4 text-center">
          <WalletConnect />
        </div>
      )}
    </div>
  );
}

7.2 Chart Integration

// components/ProbabilityChart.tsx
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';

export function ProbabilityChart({ market }: { market: Market }) {
  const [timeRange, setTimeRange] = useState<'1H' | '6H' | '1D' | '7D' | '1M' | 'ALL'>('1D');

  // Mock historical data - replace with real API call
  const historicalData = generateMockHistoricalData(market, timeRange);

  return (
    <div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6">
      <div className="flex justify-between items-center mb-6">
        <h3 className="text-lg font-semibold">Probability Over Time</h3>
        <div className="flex gap-1 bg-gray-100 dark:bg-gray-700 rounded-lg p-1">
          {(['1H', '6H', '1D', '7D', '1M', 'ALL'] as const).map((range) => (
            <button
              key={range}
              onClick={() => setTimeRange(range)}
              className={`px-3 py-1 text-xs rounded-md transition-colors ${
                timeRange === range
                  ? 'bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm'
                  : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white'
              }`}
            >
              {range}
            </button>
          ))}
        </div>
      </div>

      <div className="h-64">
        <ResponsiveContainer width="100%" height="100%">
          <LineChart data={historicalData}>
            <CartesianGrid strokeDasharray="3 3" className="opacity-30" />
            <XAxis
              dataKey="time"
              tickFormatter={(time) => new Date(time).toLocaleDateString()}
              className="text-xs"
            />
            <YAxis
              domain={[0, 100]}
              tickFormatter={(value) => `${value}%`}
              className="text-xs"
            />
            <Tooltip
              labelFormatter={(time) => new Date(time).toLocaleString()}
              formatter={(value: number, name: string) => [
                `${value.toFixed(1)}%`,
                name === 'yes' ? 'Yes' : 'No'
              ]}
              contentStyle={{
                backgroundColor: 'rgb(31 41 55)',
                border: 'none',
                borderRadius: '8px',
                color: 'white'
              }}
            />
            <Line
              type="monotone"
              dataKey="yes"
              stroke="#3b82f6"
              strokeWidth={2}
              dot={false}
              name="yes"
            />
            <Line
              type="monotone"
              dataKey="no"
              stroke="#ef4444"
              strokeWidth={2}
              dot={false}
              name="no"
            />
          </LineChart>
        </ResponsiveContainer>
      </div>
    </div>
  );
}

📱 Day 18-19: Mobile Optimization & Accessibility

8.1 Mobile-First Trading Interface

// components/MobileTradePanel.tsx
export function MobileTradePanel({ market }: { market: Market }) {
  const [isOpen, setIsOpen] = useState(false);
  const [selectedOutcome, setSelectedOutcome] = useState<'yes' | 'no'>('yes');

  return (
    <>
      {/* Mobile Trade Button */}
      <div className="md:hidden fixed bottom-20 left-4 right-4 z-40">
        <button
          onClick={() => setIsOpen(true)}
          className="w-full py-4 bg-blue-600 hover:bg-blue-700 text-white rounded-xl font-semibold shadow-lg transition-colors"
        >
          Trade on {selectedOutcome === 'yes' ? 'Yes' : 'No'}
        </button>
      </div>

      {/* Mobile Trade Modal */}
      <Dialog.Root open={isOpen} onOpenChange={setIsOpen}>
        <Dialog.Portal>
          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
          <Dialog.Content className="fixed bottom-0 left-0 right-0 bg-white dark:bg-gray-800 rounded-t-xl p-6 z-50 max-h-[90vh] overflow-y-auto">
            <div className="flex justify-between items-center mb-6">
              <Dialog.Title className="text-lg font-semibold">
                Trade: {market.title}
              </Dialog.Title>
              <Dialog.Close className="p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-full">
                <X className="w-5 h-5" />
              </Dialog.Close>
            </div>

            {/* Mobile-optimized trade interface */}
            <TradePanel market={market} isMobile />
          </Dialog.Content>
        </Dialog.Portal>
      </Dialog.Root>
    </>
  );
}

8.2 Accessibility Enhancements

// utils/accessibility.ts
export const a11yProps = {
  // Button accessibility
  button: (label: string, pressed?: boolean) => ({
    'aria-label': label,
    'aria-pressed': pressed,
    role: 'button',
    tabIndex: 0,
  }),

  // Input accessibility
  input: (label: string, error?: string, describedBy?: string) => ({
    'aria-label': label,
    'aria-invalid': !!error,
    'aria-describedby': error ? `${describedBy}-error` : describedBy,
  }),

  // Status announcements
  status: (message: string, priority: 'polite' | 'assertive' = 'polite') => ({
    'aria-live': priority,
    'aria-atomic': true,
    role: 'status',
  }),
};

// Screen reader announcements
export function announceToScreenReader(message: string, priority: 'polite' | 'assertive' = 'polite') {
  const announcement = document.createElement('div');
  announcement.setAttribute('aria-live', priority);
  announcement.setAttribute('aria-atomic', 'true');
  announcement.className = 'sr-only';
  announcement.textContent = message;

  document.body.appendChild(announcement);
  setTimeout(() => document.body.removeChild(announcement), 1000);
}

⚡ Day 20-21: Performance & Optimization

9.3 Phase 3 Checklist

## **PHASE 3 COMPLETION CHECKLIST**

### **Advanced UI Components**
- [ ] Complete `TradePanel` component with all features
- [ ] Implemented `ProbabilityChart` with Recharts
- [ ] Added time range selector (1H, 6H, 1D, 1W, 1M, ALL)
- [ ] Created mobile-optimized trading interface
- [ ] Implemented advanced settings (slippage, deadline)
- [ ] Added trade preview with calculations
- [ ] All components are fully responsive

### **Chart Integration**
- [ ] Recharts library installed and configured
- [ ] Historical data visualization working
- [ ] Interactive tooltips and legends
- [ ] Time range switching functionality
- [ ] Proper data formatting for charts
- [ ] Chart performance optimized
- [ ] Mobile-friendly chart interactions

### **Mobile Optimization**
- [ ] Mobile-first responsive design
- [ ] Touch-friendly interface elements
- [ ] Mobile trade modal implementation
- [ ] Swipe gestures for navigation
- [ ] Optimized font sizes and spacing
- [ ] Mobile-specific loading states
- [ ] Performance optimized for mobile

### **Accessibility (WCAG 2.1 AA)**
- [ ] Screen reader compatibility
- [ ] Keyboard navigation support
- [ ] Focus management and indicators
- [ ] Color contrast compliance
- [ ] ARIA labels and descriptions
- [ ] Status announcements for dynamic content
- [ ] Alternative text for all images
- [ ] Form labels and error messages

### **Performance Optimization**
- [ ] Component memoization implemented
- [ ] Image optimization with Next.js Image
- [ ] Bundle size optimization
- [ ] Lazy loading for non-critical components
- [ ] Virtual scrolling for long lists
- [ ] Debounced input handling
- [ ] Optimized re-renders

### **Advanced Features**
- [ ] Real-time price updates
- [ ] Advanced trading settings
- [ ] Price impact calculations
- [ ] Slippage protection
- [ ] Transaction history
- [ ] User position tracking
- [ ] Market statistics display

### **Error Handling & UX**
- [ ] Comprehensive error states
- [ ] Empty state components
- [ ] Loading animations and skeletons
- [ ] User-friendly error messages
- [ ] Retry mechanisms for failed operations
- [ ] Graceful degradation strategies
- [ ] Toast notifications for user feedback

### **Testing & Quality**
- [ ] Component tests for all new features
- [ ] Accessibility testing with automated tools
- [ ] Performance testing and optimization
- [ ] Mobile device testing
- [ ] Cross-browser compatibility testing
- [ ] User acceptance testing

### **Phase 3 Success Criteria**
- [ ] All UI components are polished and functional
- [ ] Charts display data correctly and interactively
- [ ] Mobile experience is excellent
- [ ] Accessibility compliance achieved
- [ ] Performance targets met (< 2s load time)
- [ ] All advanced features working
- [ ] Error handling is comprehensive
- [ ] All tests pass
- [ ] No TypeScript errors

9.1 Component Memoization

// components/OptimizedMarketCard.tsx
const MarketCard = memo(({ market, onTrade }: MarketCardProps) => {
  const memoizedOutcomes = useMemo(() =>
    market.outcomes.map(outcome => ({
      ...outcome,
      formattedPrice: FinancialMath.formatUSDC(outcome.price),
      formattedVolume: FinancialMath.formatUSDC(outcome.volume),
    }))
  , [market.outcomes]);

  return (
    <article className="...">
      {/* Optimized rendering */}
    </article>
  );
});

MarketCard.displayName = 'MarketCard';

9.2 Image Optimization

// components/OptimizedImage.tsx
import Image from 'next.js';

export function OptimizedMarketImage({ market }: { market: Market }) {
  return (
    <div className="relative w-full h-48 rounded-lg overflow-hidden">
      <Image
        src={market.imageUrl || '/images/default-market.jpg'}
        alt={market.title}
        fill
        className="object-cover"
        sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
        priority={false}
        placeholder="blur"
        blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAIAAoDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAv/xAAhEAACAQMDBQAAAAAAAAAAAAABAgMABAUGIWGRkqGx0f/EABUBAQEAAAAAAAAAAAAAAAAAAAMF/8QAGhEAAgIDAAAAAAAAAAAAAAAAAAECEgMRkf/aAAwDAQACEQMRAD8AltJagyeH0AthI5xdrLcNM91BF5pX2HaH9bcfaSXWGaRmknyJckliyjqTzSlT54b6bk+h0R//2Q=="
      />
    </div>
  );
}

🧪 PHASE 4: TESTING & POLISH (Week 4)

🔬 Day 22-24: Testing Implementation

10.1 Unit Tests for Utilities

// __tests__/utils/calculations.test.ts
import { describe, it, expect } from 'vitest';
import { FinancialMath } from '@/utils/calculations';

describe('FinancialMath', () => {
  describe('toUSDCWei', () => {
    it('should convert string amounts correctly', () => {
      expect(FinancialMath.toUSDCWei('100')).toBe(100_000_000n);
      expect(FinancialMath.toUSDCWei('0.01')).toBe(10_000n);
    });

    it('should throw on invalid amounts', () => {
      expect(() => FinancialMath.toUSDCWei('-1')).toThrow();
      expect(() => FinancialMath.toUSDCWei('abc')).toThrow();
    });
  });

  describe('calculateSharesOut', () => {
    it('should calculate shares correctly', () => {
      const usdcIn = 1_000_000n; // $1
      const price = 500_000_000_000_000_000n; // $0.50
      const result = FinancialMath.calculateSharesOut(usdcIn, price);

      expect(result.sharesOut).toBe(2_000_000_000_000_000_000n); // 2 shares
    });
  });
});

10.2 Component Tests

// __tests__/components/TradePanel.test.tsx
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { TradePanel } from '@/components/TradePanel';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const mockMarket = {
  id: '1',
  title: 'Test Market',
  // ... other properties
};

const TestWrapper = ({ children }: { children: React.ReactNode }) => {
  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false } }
  });

  return (
    <QueryClientProvider client={queryClient}>
      {children}
    </QueryClientProvider>
  );
};

describe('TradePanel', () => {
  it('should render trade options', () => {
    render(<TradePanel market={mockMarket} />, { wrapper: TestWrapper });

    expect(screen.getByText('Yes')).toBeInTheDocument();
    expect(screen.getByText('No')).toBeInTheDocument();
  });

  it('should validate trade amounts', async () => {
    render(<TradePanel market={mockMarket} />, { wrapper: TestWrapper });

    const amountInput = screen.getByPlaceholderText('0.00');
    fireEvent.change(amountInput, { target: { value: '0.001' } });

    await waitFor(() => {
      expect(screen.getByText(/minimum amount/i)).toBeInTheDocument();
    });
  });
});

🎨 Day 25-26: Final UI Polish

11.1 Error States & Empty States

// components/ErrorStates.tsx
export function MarketNotFound({ marketId }: { marketId: string }) {
  return (
    <div className="min-h-screen flex items-center justify-center">
      <div className="text-center">
        <div className="mb-4">
          <SearchX className="w-16 h-16 mx-auto text-gray-400" />
        </div>
        <h1 className="text-2xl font-bold mb-2">Market Not Found</h1>
        <p className="text-gray-600 dark:text-gray-400 mb-6">
          The market with ID "{marketId}" could not be found.
        </p>
        <Link
          href="/"
          className="inline-flex items-center gap-2 px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
        >
          <ArrowLeft className="w-4 h-4" />
          Back to Markets
        </Link>
      </div>
    </div>
  );
}

export function NetworkError({ onRetry }: { onRetry: () => void }) {
  return (
    <div className="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-700 rounded-lg p-6 text-center">
      <WifiOff className="w-12 h-12 mx-auto text-red-500 mb-4" />
      <h3 className="text-lg font-semibold mb-2">Connection Error</h3>
      <p className="text-red-700 dark:text-red-400 mb-4">
        Unable to load market data. Please check your connection.
      </p>
      <button
        onClick={onRetry}
        className="px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors"
      >
        Try Again
      </button>
    </div>
  );
}

11.2 Loading Animations

// components/animations/LoadingSpinner.tsx
export function LoadingSpinner({ size = 'medium' }: { size?: 'small' | 'medium' | 'large' }) {
  const sizeClasses = {
    small: 'w-4 h-4',
    medium: 'w-8 h-8',
    large: 'w-12 h-12',
  };

  return (
    <div className="flex justify-center">
      <div
        className={`${sizeClasses[size]} animate-spin rounded-full border-2 border-gray-300 border-t-blue-600`}
        role="status"
        aria-label="Loading"
      >
        <span className="sr-only">Loading...</span>
      </div>
    </div>
  );
}

🚀 Day 27-28: Production Readiness

12.3 Phase 4 Checklist

## **PHASE 4 COMPLETION CHECKLIST**

### **Testing Implementation**
- [ ] Unit tests for all utility functions (90%+ coverage)
- [ ] Component tests for all major components
- [ ] Integration tests for trading flow
- [ ] End-to-end tests for critical user journeys
- [ ] Accessibility tests with automated tools
- [ ] Performance tests and optimization
- [ ] Cross-browser compatibility tests
- [ ] Mobile device testing

### **Error Handling & Recovery**
- [ ] Comprehensive error boundaries implemented
- [ ] User-friendly error messages for all scenarios
- [ ] Retry mechanisms for failed operations
- [ ] Graceful degradation strategies
- [ ] Network error handling
- [ ] Transaction failure recovery
- [ ] Data loading error states
- [ ] 404 and not found pages

### **Performance & Optimization**
- [ ] Bundle size under 500KB gzipped
- [ ] Page load time under 2 seconds
- [ ] First Contentful Paint under 1.5 seconds
- [ ] Largest Contentful Paint under 2.5 seconds
- [ ] Cumulative Layout Shift under 0.1
- [ ] Lighthouse score 90+ for all categories
- [ ] Image optimization implemented
- [ ] Code splitting and lazy loading

### **SEO & Meta Tags**
- [ ] Dynamic meta tags for each market
- [ ] Open Graph tags for social sharing
- [ ] Twitter Card tags
- [ ] Structured data markup
- [ ] Sitemap generation
- [ ] Robots.txt configuration
- [ ] Canonical URLs
- [ ] Meta descriptions for all pages

### **Analytics & Monitoring**
- [ ] Google Analytics integration
- [ ] Custom event tracking
- [ ] Performance monitoring
- [ ] Error tracking with Sentry
- [ ] User behavior analytics
- [ ] Conversion tracking
- [ ] A/B testing setup
- [ ] Real-time monitoring dashboard

### **Security & Compliance**
- [ ] XSS protection implemented
- [ ] CSRF protection enabled
- [ ] Input sanitization throughout
- [ ] Content Security Policy headers
- [ ] HTTPS enforcement
- [ ] Privacy policy compliance
- [ ] GDPR compliance measures
- [ ] Security audit completed

### **Production Deployment**
- [ ] Environment configuration
- [ ] Build optimization
- [ ] CDN configuration
- [ ] Caching strategy
- [ ] Database optimization
- [ ] API rate limiting
- [ ] Monitoring and alerting
- [ ] Backup and recovery procedures

### **Documentation & Maintenance**
- [ ] API documentation updated
- [ ] Component documentation complete
- [ ] Deployment guide written
- [ ] Troubleshooting guide created
- [ ] Maintenance procedures documented
- [ ] Code comments and JSDoc
- [ ] README updated
- [ ] Changelog maintained

### **Final Quality Assurance**
- [ ] All features working as expected
- [ ] No critical bugs or issues
- [ ] Performance targets met
- [ ] Accessibility compliance achieved
- [ ] Security measures in place
- [ ] All tests passing
- [ ] Code review completed
- [ ] User acceptance testing passed

### **Phase 4 Success Criteria**
- [ ] Production-ready application
- [ ] All performance targets met
- [ ] Comprehensive test coverage
- [ ] Security audit passed
- [ ] SEO optimization complete
- [ ] Analytics and monitoring active
- [ ] Documentation complete
- [ ] Ready for public launch

12.1 SEO & Meta Tags

// app/market/[id]/page.tsx
import { Metadata } from 'next';

export async function generateMetadata({
  params
}: {
  params: { id: string }
}): Promise<Metadata> {
  const market = await getMarketData(params.id);

  if (!market) {
    return {
      title: 'Market Not Found - PakoMarket',
    };
  }

  return {
    title: `${market.title} - PakoMarket`,
    description: `Trade on "${market.title}" - Volume: ${FinancialMath.formatUSDC(market.volume)}`,
    openGraph: {
      title: market.title,
      description: market.description,
      images: [market.imageUrl || '/images/default-og.jpg'],
      type: 'website',
    },
    twitter: {
      card: 'summary_large_image',
      title: market.title,
      description: market.description,
      images: [market.imageUrl || '/images/default-og.jpg'],
    },
  };
}

12.2 Performance Monitoring

// utils/analytics.ts
export function trackMarketView(marketId: string, marketTitle: string) {
  // Analytics tracking
  if (typeof window !== 'undefined' && window.gtag) {
    window.gtag('event', 'market_view', {
      market_id: marketId,
      market_title: marketTitle,
    });
  }
}

export function trackTrade(marketId: string, outcome: string, amount: string) {
  if (typeof window !== 'undefined' && window.gtag) {
    window.gtag('event', 'trade_initiated', {
      market_id: marketId,
      outcome,
      amount: parseFloat(amount),
    });
  }
}

🎯 FINAL DELIVERABLES & SUCCESS CRITERIA

📊 Technical Deliverables

  1. Complete Market Details Page

    • ✅ Server-side rendered with proper SEO
    • ✅ Mobile-responsive design
    • ✅ Dark/light mode support
    • ✅ Accessibility compliant (WCAG 2.1 AA)
  2. Full Trading Integration

    • ✅ USDC approval workflow
    • ✅ Real-time price quotes
    • ✅ Slippage protection
    • ✅ Chain validation
    • ✅ Transaction monitoring
  3. Robust Architecture

    • ✅ Component-based architecture
    • ✅ Custom hooks for Web3 integration
    • ✅ Proper error handling
    • ✅ Type-safe throughout
    • ✅ Performance optimized
  4. Production Features

    • ✅ Loading states and skeletons
    • ✅ Error boundaries
    • ✅ 404 handling
    • ✅ Analytics integration
    • ✅ SEO optimization

🎛️ Performance Benchmarks

Metric Target Measurement
Page Load Time < 2s Lighthouse
First Contentful Paint < 1.5s Lighthouse
Largest Contentful Paint < 2.5s Lighthouse
Cumulative Layout Shift < 0.1 Lighthouse
Bundle Size < 500KB gzipped webpack-bundle-analyzer
Accessibility Score 100/100 Lighthouse

🧪 Testing Coverage

  • Unit Tests: 90%+ coverage for utilities and hooks
  • Component Tests: Key components tested with React Testing Library
  • Integration Tests: End-to-end trading flow
  • Accessibility Tests: Automated a11y testing
  • Performance Tests: Bundle size and runtime performance

🔒 Security Checklist

  • All user inputs validated with Zod
  • Decimal precision handled with bigint
  • No client-side private key exposure
  • Proper error handling without data leakage
  • XSS protection on all dynamic content
  • CSRF protection on state-changing operations

📱 Browser Support

  • ✅ Chrome 90+
  • ✅ Firefox 88+
  • ✅ Safari 14+
  • ✅ Edge 90+
  • ✅ Mobile browsers (iOS Safari, Chrome Mobile)

🚀 POST-LAUNCH ROADMAP

Phase 5: Advanced Features (Month 2)

  • Real-time Updates: WebSocket integration for live price updates
  • Advanced Charts: Candlestick charts, volume indicators
  • Social Features: Comments, sharing, market creator profiles
  • Portfolio View: User's position tracking and P&L

Phase 6: Optimization (Month 3)

  • Caching Strategy: Redis integration for API responses
  • CDN Integration: Image and static asset optimization
  • Database Optimization: Query optimization and indexing
  • Advanced Analytics: User behavior tracking and insights

Phase 7: Scale & Extend (Month 4+)

  • Multi-chain Support: Extend beyond local development
  • Advanced Order Types: Limit orders, stop-loss
  • Liquidity Incentives: LP rewards and staking
  • Mobile App: React Native or PWA implementation

📈 SUCCESS METRICS & KPIs

User Experience Metrics

  • Page Load Speed: < 2 seconds average
  • Bounce Rate: < 30% on market detail pages
  • Trade Completion Rate: > 85% of initiated trades complete
  • Error Rate: < 1% of user interactions result in errors

Technical Metrics

  • Uptime: 99.9% availability
  • API Response Time: < 200ms average
  • Bundle Size: < 500KB compressed
  • Test Coverage: > 90% for critical paths

Business Metrics

  • Trading Volume: Track USDC volume per market
  • User Retention: Weekly active users on market pages
  • Conversion Rate: Visitors to traders conversion
  • Market Engagement: Time spent on market detail pages

🎯 MASTER IMPLEMENTATION CHECKLIST

📋 Pre-Development Setup

  • Development environment configured
  • All dependencies installed and working
  • Git repository set up with proper branching
  • CI/CD pipeline configured
  • Testing environment ready
  • Design system and components library
  • Project documentation structure

🏗️ Phase 1: Foundation (Week 1)

  • File Structure: Complete directory setup
  • Component Extraction: All components extracted and working
  • Decimal Precision: Financial math utilities implemented
  • Mock Data: Comprehensive mock data system
  • Basic UI/UX: Responsive design and theming
  • Testing Foundation: Basic testing setup
  • Code Quality: TypeScript and linting
  • Performance Basics: Initial optimization

⚡ Phase 2: Web3 Integration (Week 2)

  • Web3 Hooks: All trading hooks implemented
  • Trading Flow: Complete buy/sell functionality
  • Chain Management: Network validation and switching
  • Real-time Data: Live price updates and caching
  • Contract Integration: All contract calls working
  • Security & Validation: Input validation and security
  • Testing & Quality: Web3 testing implementation
  • Fallback Strategies: All fallbacks working

🎨 Phase 3: UX Excellence (Week 3)

  • Advanced UI: Complete trading interface
  • Chart Integration: Recharts implementation
  • Mobile Optimization: Mobile-first design
  • Accessibility: WCAG 2.1 AA compliance
  • Performance: Advanced optimization
  • Advanced Features: Real-time updates, etc.
  • Error Handling: Comprehensive error states
  • Testing & Quality: Advanced testing

🧪 Phase 4: Testing & Polish (Week 4)

  • Testing Implementation: Complete test suite
  • Error Handling: All error scenarios covered
  • Performance: All targets met
  • SEO & Meta: Complete SEO optimization
  • Analytics: Monitoring and tracking
  • Security: Security audit and compliance
  • Production: Deployment readiness
  • Documentation: Complete documentation

🚀 Production Readiness

  • Performance: All benchmarks met
  • Security: Security audit passed
  • Testing: 90%+ test coverage
  • Accessibility: WCAG 2.1 AA compliant
  • SEO: Complete SEO optimization
  • Monitoring: Analytics and error tracking
  • Documentation: Complete and up-to-date
  • Launch: Ready for public release

📊 Success Metrics Tracking

  • Performance: Page load < 2s, Lighthouse 90+
  • Accessibility: 100% WCAG compliance
  • Testing: 90%+ coverage, all tests passing
  • Security: No critical vulnerabilities
  • UX: User acceptance testing passed
  • Code Quality: No TypeScript errors, clean code
  • Documentation: Complete and maintained
  • Launch: Production deployment successful

This mega plan transforms the current prototype into a production-ready, contract-integrated market details page that serves as the foundation for the entire PakoMarket platform. The systematic approach ensures security, scalability, and exceptional user experience while building toward full Web3 integration.

Remember: Use this plan as a guide, not a rigid checklist. Adapt and iterate based on your team's progress and changing requirements. The key is to maintain momentum while ensuring quality at each step.