# Development Guide This guide covers the development workflow, best practices, and common patterns used in the Impersonator project. ## Development Workflow ### 1. Starting Development ```bash # Start development server pnpm dev # Server runs on http://localhost:3000 ``` ### 2. Making Changes 1. Create a feature branch 2. Make your changes 3. Write/update tests 4. Run linter and tests 5. Commit changes 6. Push and create PR ### 3. Testing Changes ```bash # Run all tests pnpm test # Run tests in watch mode pnpm test:watch # Run with coverage pnpm test:coverage # Run specific test suite pnpm test:security pnpm test:integration ``` ### 4. Code Quality Checks ```bash # Run linter pnpm lint # Fix linting issues pnpm lint --fix ``` ## Development Patterns ### Context Usage #### Using SmartWalletContext ```typescript import { useSmartWallet } from "@/contexts/SmartWalletContext"; function MyComponent() { const { activeWallet, smartWallets, connectToWallet, createWallet, addOwner, removeOwner, updateThreshold, } = useSmartWallet(); // Use context values and methods } ``` #### Using TransactionContext ```typescript import { useTransaction } from "@/contexts/TransactionContext"; function MyComponent() { const { transactions, pendingTransactions, createTransaction, approveTransaction, executeTransaction, estimateGas, } = useTransaction(); // Use context values and methods } ``` #### Using SafeInjectContext ```typescript import { useSafeInject } from "@/contexts/SafeInjectContext"; function MyComponent() { const { address, appUrl, setAddress, setAppUrl, iframeRef, latestTransaction, } = useSafeInject(); // Use context values and methods } ``` ### Component Patterns #### Functional Components with Hooks ```typescript "use client"; import { useState, useEffect } from "react"; import { Box, Button } from "@chakra-ui/react"; export default function MyComponent() { const [state, setState] = useState(""); useEffect(() => { // Side effects }, []); return ( ); } ``` #### Form Handling ```typescript import { useState } from "react"; import { useToast } from "@chakra-ui/react"; import { validateAddress } from "@/utils/security"; function AddressForm() { const [address, setAddress] = useState(""); const toast = useToast(); const handleSubmit = async () => { // Validate input const validation = validateAddress(address); if (!validation.valid) { toast({ title: "Invalid Address", description: validation.error, status: "error", }); return; } // Process valid address const checksummed = validation.checksummed!; // ... rest of logic }; return ( // Form JSX ); } ``` ### Error Handling #### Try-Catch Pattern ```typescript try { const result = await someAsyncOperation(); // Handle success } catch (error: any) { console.error("Operation failed:", error); toast({ title: "Error", description: error.message || "Operation failed", status: "error", }); } ``` #### Error Boundary ```typescript import ErrorBoundary from "@/components/ErrorBoundary"; function App() { return ( ); } ``` ### Validation Patterns #### Address Validation ```typescript import { validateAddress } from "@/utils/security"; const validation = validateAddress(address); if (!validation.valid) { throw new Error(validation.error); } const checksummed = validation.checksummed!; ``` #### Transaction Validation ```typescript import { validateTransactionRequest } from "@/utils/security"; const validation = validateTransactionRequest({ from: "0x...", to: "0x...", value: "1000000000000000000", data: "0x", }); if (!validation.valid) { console.error("Validation errors:", validation.errors); } ``` ### Async Operations #### Using Async/Await ```typescript async function fetchData() { try { const data = await someAsyncCall(); return data; } catch (error) { console.error("Failed to fetch:", error); throw error; } } ``` #### Promise Handling ```typescript someAsyncCall() .then((result) => { // Handle success }) .catch((error) => { // Handle error }); ``` ### State Management #### Local State ```typescript const [value, setValue] = useState(""); const [loading, setLoading] = useState(false); ``` #### Context State ```typescript // Access context state const { activeWallet } = useSmartWallet(); ``` #### Derived State ```typescript const pendingCount = transactions.filter( (tx) => tx.status === TransactionStatus.PENDING ).length; ``` ## Security Best Practices ### Input Validation Always validate user input: ```typescript import { validateAddress, validateTransactionValue } from "@/utils/security"; // Validate address const addressValidation = validateAddress(userInput); if (!addressValidation.valid) { // Handle invalid input } // Validate transaction value const valueValidation = validateTransactionValue(value); if (!valueValidation.valid) { // Handle invalid value } ``` ### Secure Storage Use SecureStorage for sensitive data: ```typescript import { SecureStorage } from "@/utils/encryption"; const storage = new SecureStorage(); await storage.setItem("key", JSON.stringify(sensitiveData)); const data = await storage.getItem("key"); ``` ### Rate Limiting Respect rate limits: ```typescript import { RateLimiter } from "@/utils/security"; const limiter = new RateLimiter(); if (!limiter.checkLimit(userAddress)) { throw new Error("Rate limit exceeded"); } ``` ## Code Style Guidelines ### TypeScript - Use strict mode - Define types for all functions - Use interfaces for object shapes - Avoid `any` type - Use type guards when needed ### Naming Conventions - **Components**: PascalCase (`WalletManager`) - **Functions**: camelCase (`validateAddress`) - **Constants**: UPPER_SNAKE_CASE (`MAX_GAS_LIMIT`) - **Types/Interfaces**: PascalCase (`SmartWalletConfig`) - **Files**: Match export name ### Code Formatting - Use Prettier for formatting - 2 spaces for indentation - Semicolons required - Single quotes for strings - Trailing commas in objects/arrays ### Comments - Use JSDoc for public APIs - Explain "why" not "what" - Keep comments up to date - Remove commented-out code ## Testing Patterns ### Unit Tests ```typescript import { validateAddress } from "@/utils/security"; describe("validateAddress", () => { it("should validate correct addresses", () => { const result = validateAddress("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"); expect(result.valid).toBe(true); }); it("should reject invalid addresses", () => { const result = validateAddress("invalid"); expect(result.valid).toBe(false); }); }); ``` ### Component Tests ```typescript import { render, screen } from "@testing-library/react"; import WalletManager from "@/components/SmartWallet/WalletManager"; describe("WalletManager", () => { it("should render wallet list", () => { render(); expect(screen.getByText("Wallets")).toBeInTheDocument(); }); }); ``` ## Debugging ### Console Logging ```typescript // Use monitoring service for production import { monitoring } from "@/utils/monitoring"; monitoring.debug("Debug message", { context }); monitoring.info("Info message", { context }); monitoring.warn("Warning message", { context }); monitoring.error("Error message", error, { context }); ``` ### React DevTools - Install React DevTools browser extension - Inspect component tree - View props and state - Profile performance ### Browser DevTools - Use Network tab for API calls - Use Console for errors - Use Application tab for storage - Use Sources for debugging ## Performance Optimization ### Memoization ```typescript import { useMemo, useCallback } from "react"; // Memoize expensive calculations const expensiveValue = useMemo(() => { return computeExpensiveValue(data); }, [data]); // Memoize callbacks const handleClick = useCallback(() => { doSomething(); }, [dependencies]); ``` ### Lazy Loading ```typescript import { lazy, Suspense } from "react"; const HeavyComponent = lazy(() => import("./HeavyComponent")); function App() { return ( Loading...}> ); } ``` ### Code Splitting Next.js automatically code-splits by route. For manual splitting: ```typescript import dynamic from "next/dynamic"; const DynamicComponent = dynamic(() => import("./Component"), { ssr: false, }); ``` ## Git Workflow ### Branch Naming - `feature/description` - New features - `fix/description` - Bug fixes - `refactor/description` - Refactoring - `docs/description` - Documentation - `test/description` - Test additions ### Commit Messages Follow conventional commits: ``` feat: add wallet connection fix: resolve address validation bug docs: update API documentation test: add integration tests refactor: extract constants ``` ### Pull Request Process 1. Create feature branch 2. Make changes and commit 3. Write/update tests 4. Run tests and linter 5. Create PR with description 6. Address review comments 7. Merge after approval ## Common Tasks ### Adding a New Wallet Type 1. Create helper in `helpers/smartWallet/` 2. Add type to `types.ts` 3. Update `SmartWalletContext` 4. Add UI component 5. Write tests ### Adding a New Transaction Type 1. Update `TransactionRequest` type 2. Add validation in `utils/security.ts` 3. Update execution logic 4. Add UI component 5. Write tests ### Adding a New Network 1. Add to `NETWORKS` in `utils/constants.ts` 2. Update network validation 3. Add to network list component 4. Test connection ## Resources - [Next.js Docs](https://nextjs.org/docs) - [React Docs](https://react.dev) - [TypeScript Docs](https://www.typescriptlang.org/docs/) - [Chakra UI Docs](https://chakra-ui.com/) - [ethers.js Docs](https://docs.ethers.org/)