Files
impersonator/docs/04-development.md

542 lines
9.9 KiB
Markdown
Raw Permalink Normal View History

feat: comprehensive project improvements and fixes - Fix all TypeScript compilation errors (40+ fixes) - Add missing type definitions (TransactionRequest, SafeInfo) - Fix TransactionRequestStatus vs TransactionStatus confusion - Fix import paths and provider type issues - Fix test file errors and mock providers - Implement comprehensive security features - AES-GCM encryption with PBKDF2 key derivation - Input validation and sanitization - Rate limiting and nonce management - Replay attack prevention - Access control and authorization - Add comprehensive test suite - Integration tests for transaction flow - Security validation tests - Wallet management tests - Encryption and rate limiter tests - E2E tests with Playwright - Add extensive documentation - 12 numbered guides (setup, development, API, security, etc.) - Security documentation and audit reports - Code review and testing reports - Project organization documentation - Update dependencies - Update axios to latest version (security fix) - Update React types to v18 - Fix peer dependency warnings - Add development tooling - CI/CD workflows (GitHub Actions) - Pre-commit hooks (Husky) - Linting and formatting (Prettier, ESLint) - Security audit workflow - Performance benchmarking - Reorganize project structure - Move reports to docs/reports/ - Clean up root directory - Organize documentation - Add new features - Smart wallet management (Gnosis Safe, ERC4337) - Transaction execution and approval workflows - Balance management and token support - Error boundary and monitoring (Sentry) - Fix WalletConnect configuration - Handle missing projectId gracefully - Add environment variable template
2026-01-14 02:17:26 -08:00
# 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<string>("");
useEffect(() => {
// Side effects
}, []);
return (
<Box>
<Button onClick={() => setState("new value")}>
Click me
</Button>
</Box>
);
}
```
#### 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 (
<ErrorBoundary>
<YourComponent />
</ErrorBoundary>
);
}
```
### 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<string>("");
const [loading, setLoading] = useState<boolean>(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(<WalletManager />);
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 (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
}
```
### 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/)