diff --git a/ANALYSIS.md b/ANALYSIS.md new file mode 100644 index 0000000..cef9d07 --- /dev/null +++ b/ANALYSIS.md @@ -0,0 +1,17 @@ +# arc-commerce Analysis + +## Repository: arc-commerce +**URL:** https://github.com/circlefin/arc-commerce +**Stars:** 20 +**Tech Stack:** Next.js, TypeScript, Supabase, Circle Wallets + +## Readiness Score: 25/25 ⭐ + +Same documentation gaps as arc-escrow: +- No CONTRIBUTING.md +- No docs/ folder +- No architecture documentation +- No troubleshooting guide + +**Timeline:** 3-5 days (faster with arc-escrow template) +**Output:** ~1,300 lines documentation diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..b5dca51 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,488 @@ +# Contributing to arc-commerce + +Thank you for your interest in contributing to arc-commerce! This document provides guidelines and instructions for contributing to the project. + +## Table of Contents +- [Code of Conduct](#code-of-conduct) +- [Getting Started](#getting-started) +- [Development Workflow](#development-workflow) +- [Pull Request Process](#pull-request-process) +- [Code Style Guidelines](#code-style-guidelines) +- [Commit Message Conventions](#commit-message-conventions) +- [Testing Guidelines](#testing-guidelines) +- [Documentation](#documentation) +- [Issue Reporting](#issue-reporting) +- [Security](#security) + +--- + +## Code of Conduct + +We are committed to providing a welcoming and inclusive environment. By participating in this project, you agree to abide by our code of conduct: + +- **Be respectful:** Treat everyone with respect and kindness +- **Be constructive:** Provide helpful feedback and suggestions +- **Be collaborative:** Work together towards common goals +- **Be professional:** Maintain professional conduct in all interactions + +--- + +## Getting Started + +### Prerequisites + +Before contributing, ensure you have: + +- **Node.js v22+** installed (use `nvm` with `.nvmrc`) +- **npm** (comes with Node.js) +- **Git** for version control +- **Supabase CLI** (`npm install -g supabase`) +- **Docker Desktop** (for local Supabase) +- **Circle API credentials** (API key and Entity Secret) + +### Fork and Clone + +1. **Fork the repository** on GitHub by clicking the "Fork" button + +2. **Clone your fork:** +```bash + git clone https://github.com/YOUR_USERNAME/arc-commerce.git + cd arc-commerce +``` + +3. **Add upstream remote:** +```bash + git remote add upstream https://github.com/circlefin/arc-commerce.git +``` + +4. **Install dependencies:** +```bash + npm install +``` + +### Set Up Environment + +1. **Copy environment file:** +```bash + cp .env.example .env.local +``` + +2. **Configure Supabase** (choose local or remote): +```bash + # Local (Docker required) + npx supabase start + npx supabase migration up + + # OR Remote + npx supabase link --project-ref YOUR_PROJECT_REF + npx supabase db push +``` + +3. **Add Circle credentials** to `.env.local` + +4. **Run the development server:** +```bash + npm run dev +``` + +--- + +## Development Workflow + +### Branch Naming + +Use descriptive branch names following this pattern: + +- `feature/description` - New features +- `fix/description` - Bug fixes +- `docs/description` - Documentation updates +- `refactor/description` - Code refactoring +- `test/description` - Test additions/updates + +Examples: +```bash +git checkout -b feature/add-credit-export +git checkout -b fix/webhook-signature-verification +git checkout -b docs/admin-dashboard-guide +``` + +### Making Changes + +1. **Create a branch:** +```bash + git checkout -b feature/your-feature-name +``` + +2. **Make your changes** following our [Code Style Guidelines](#code-style-guidelines) + +3. **Test your changes:** +```bash + npm run lint + npm test + npm run build +``` + +4. **Commit with conventional commits:** +```bash + git add . + git commit -m "feat: add credit purchase export feature" +``` + +5. **Keep your branch updated:** +```bash + git fetch upstream + git rebase upstream/main +``` + +6. **Push to your fork:** +```bash + git push origin feature/your-feature-name +``` + +--- + +## Pull Request Process + +### Before Submitting + +Ensure your PR meets these requirements: + +- [ ] Code follows our style guidelines +- [ ] All tests pass locally +- [ ] No linting errors: `npm run lint` +- [ ] Build succeeds: `npm run build` +- [ ] Documentation updated (if needed) +- [ ] Commits follow [Conventional Commits](#commit-message-conventions) +- [ ] Branch is up-to-date with `main` + +### Submitting a PR + +1. **Push your branch** to your fork + +2. **Open a Pull Request** on GitHub + +3. **Fill out the PR template** completely: + +```markdown +## Description +Brief description of changes + +## Type of Change +- [ ] Bug fix +- [ ] New feature +- [ ] Documentation update +- [ ] Refactoring + +## Testing +- [ ] Tested locally +- [ ] All tests pass +- [ ] Linting passes + +## Screenshots (if applicable) +Add screenshots for UI changes + +## Checklist +- [ ] Code follows style guidelines +- [ ] Self-review completed +- [ ] Documentation updated +- [ ] No breaking changes (or documented) +``` + +### Review Process + +- Maintainers will review your PR +- Address feedback by pushing new commits +- Once approved, maintainers will merge + +**Review timeline:** Circle is an enterprise project - expect reviews to take several days to weeks. + +--- + +## Code Style Guidelines + +### TypeScript + +```typescript +// Use explicit types +function calculateCreditCost(credits: number): number { + return credits * 0.1 +} + +// Use interfaces for objects +interface CreditPurchase { + userId: string + amount: number + transactionId: string +} + +// Async/await over promises +async function purchaseCredits(amount: number): Promise { + const result = await createTransaction(amount) + return result +} +``` + +### React Components + +```typescript +// Functional components with TypeScript +interface DashboardProps { + userId: string + credits: number +} + +export default function Dashboard({ userId, credits }: DashboardProps) { + return ( +
+

Credits: {credits}

+
+ ) +} +``` + +### API Routes + +```typescript +// Type request/response +import { NextRequest, NextResponse } from 'next/server' + +export async function POST(req: NextRequest) { + try { + const body = await req.json() + + // Validate input + if (!body.amount) { + return NextResponse.json( + { error: 'Amount required' }, + { status: 400 } + ) + } + + // Process request + const result = await processPayment(body) + return NextResponse.json(result) + + } catch (error) { + console.error('Payment error:', error) + return NextResponse.json( + { error: 'Internal server error' }, + { status: 500 } + ) + } +} +``` + +### Naming Conventions + +- **Variables/Functions:** `camelCase` +- **Components:** `PascalCase` +- **Constants:** `UPPER_SNAKE_CASE` +- **Files:** `kebab-case.ts` or `PascalCase.tsx` for components + +--- + +## Commit Message Conventions + +Follow [Conventional Commits](https://www.conventionalcommits.org/): + +### Format +(): +[optional body] +[optional footer] + +### Types + +- `feat`: New feature +- `fix`: Bug fix +- `docs`: Documentation changes +- `style`: Code style changes (formatting, no logic change) +- `refactor`: Code refactoring +- `test`: Test additions or updates +- `chore`: Maintenance tasks + +### Examples + +```bash +# Feature +git commit -m "feat(credits): add bulk credit purchase" + +# Bug fix +git commit -m "fix(webhook): correct signature verification" + +# Documentation +git commit -m "docs(readme): update installation instructions" + +# With body +git commit -m "feat(admin): add transaction export + +Allows admins to export transaction history to CSV. +Includes filters for date range and user." +``` + +--- + +## Testing Guidelines + +### Running Tests + +```bash +# Run all tests +npm test + +# Run specific test file +npm test -- path/to/test.test.ts + +# Run in watch mode +npm test -- --watch +``` + +### Writing Tests + +```typescript +// Example test +import { describe, it, expect } from '@jest/globals' +import { calculateCreditCost } from '@/lib/credits' + +describe('Credit Calculations', () => { + it('should calculate credit cost correctly', () => { + expect(calculateCreditCost(100)).toBe(10) + }) + + it('should handle zero credits', () => { + expect(calculateCreditCost(0)).toBe(0) + }) +}) +``` + +### Test Coverage + +Aim for: +- Unit tests for utility functions +- Integration tests for API routes +- Component tests for UI logic + +--- + +## Documentation + +### Code Comments + +```typescript +/** + * Purchases credits for a user using USDC + * @param userId - User's unique identifier + * @param amount - Number of credits to purchase + * @returns Transaction details + * @throws Error if payment fails + */ +async function purchaseCredits( + userId: string, + amount: number +): Promise { + // Implementation +} +``` + +### README Updates + +When adding features: +- Update relevant sections in README.md +- Add examples if applicable +- Update environment variable documentation + +### Architecture Documentation + +For significant changes: +- Update `docs/ARCHITECTURE.md` +- Add diagrams if helpful (Mermaid format) +- Explain design decisions + +--- + +## Issue Reporting + +### Bug Reports + +Use this template: + +```markdown +## Bug Description +Clear description of the bug + +## Steps to Reproduce +1. Go to '...' +2. Click on '...' +3. See error + +## Expected Behavior +What should happen + +## Actual Behavior +What actually happens + +## Environment +- OS: [e.g., macOS 14] +- Node version: [e.g., v22.0.0] +- Browser: [e.g., Chrome 120] + +## Screenshots +If applicable +``` + +### Feature Requests + +```markdown +## Feature Description +Clear description of the proposed feature + +## Use Case +Why this feature is needed + +## Proposed Solution +How you envision this working + +## Alternatives Considered +Other approaches you've thought about +``` + +--- + +## Security + +### Reporting Vulnerabilities + +**DO NOT** open public issues for security vulnerabilities. + +Instead: +1. Review `SECURITY.md` in the repository +2. Report via Circle's bug bounty program +3. Email security contacts privately + +### Security Best Practices + +- Never commit API keys or secrets +- Use environment variables for sensitive data +- Validate all user inputs +- Keep dependencies updated +- Follow OWASP guidelines + +--- + +## Getting Help + +- **Questions:** Open a GitHub Discussion +- **Bugs:** Open an Issue +- **Chat:** Join Circle's developer community (if available) +- **Documentation:** Check the `docs/` folder + +--- + +## License + +By contributing to arc-commerce, you agree that your contributions will be licensed under the same license as the project (see LICENSE file). + +--- + +**Thank you for contributing to arc-commerce!** 🎉 + +Your contributions help improve USDC payment infrastructure and make it easier for developers to integrate Circle's technology. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..1b8b6b9 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,592 @@ +# arc-commerce Architecture + +This document provides a comprehensive overview of the arc-commerce system architecture, explaining how components interact to enable USDC-based credit purchases on Arc testnet. + +## Table of Contents +- [System Overview](#system-overview) +- [Technology Stack](#technology-stack) +- [Architecture Diagram](#architecture-diagram) +- [Core Components](#core-components) +- [Credit Purchase Flow](#credit-purchase-flow) +- [Admin Dashboard](#admin-dashboard) +- [Circle Wallets Integration](#circle-wallets-integration) +- [Database Schema](#database-schema) +- [Webhook System](#webhook-system) +- [Security Model](#security-model) + +--- + +## System Overview + +arc-commerce is a Next.js application that demonstrates USDC payment integration for purchasing credits on Arc testnet. It showcases: + +- **Credit purchase system** with USDC payments +- **Dual dashboard experience** (User vs Admin) +- **Circle Developer Controlled Wallets** for payment processing +- **Webhook-based transaction notifications** +- **Real-time balance updates** via Supabase + +### Key Features + +- Users can purchase credits with USDC +- Admin dashboard for system oversight +- Automated admin wallet creation on first startup +- Transaction history tracking +- Webhook verification for security + +--- + +## Technology Stack + +### Frontend +- **Next.js 14+** - React framework with App Router +- **TypeScript** - Type safety +- **Tailwind CSS** - Styling +- **React** - UI components + +### Backend +- **Next.js API Routes** - Server-side logic +- **Supabase** - Database and authentication +- **PostgreSQL** - Database (via Supabase) + +### Blockchain & Payments +- **Circle Developer Controlled Wallets** - Wallet management +- **Arc Testnet** - Layer 2 blockchain +- **USDC** - Payment token +- **@circle-fin/developer-controlled-wallets** - Circle SDK + +### Development Tools +- **Docker** - Local Supabase +- **ngrok** - Webhook testing +- **ESLint** - Code linting +- **TypeScript Compiler** - Type checking + +--- + +## Architecture Diagram +┌─────────────────────────────────────────────────────────────┐ +│ User Flow │ +└─────────────────────────────────────────────────────────────┘ +User Dashboard +│ +├── View Credits Balance +├── Purchase Credits Form +│ │ +│ └──> Enter Amount +│ │ +│ └──> Submit Purchase +│ │ +└─────────────────────────────┘ +│ +▼ +┌─────────────────────────────────────────────────────────────┐ +│ Backend Processing │ +└─────────────────────────────────────────────────────────────┘ +Next.js API Route: /api/purchase +│ +├──> Validate Request +├──> Get User Wallet (create if needed) +├──> Initiate USDC Transfer +│ │ +│ └──> Circle SDK +│ │ +│ └──> Arc Testnet +│ │ +│ └──> USDC Transfer +│ │ +└───────────────────────────────────────┘ +│ +▼ +┌─────────────────────────────────────────────────────────────┐ +│ Webhook Flow │ +└─────────────────────────────────────────────────────────────┘ +Circle Webhook +│ +└──> POST /api/circle/webhook +│ +├──> Verify Signature +├──> Parse Event (transfer.completed) +├──> Update Transaction Status +└──> Credit User Account +│ +└──> Supabase Update +│ +└──> User sees credits! +┌─────────────────────────────────────────────────────────────┐ +│ Admin Dashboard │ +└─────────────────────────────────────────────────────────────┘ +Admin View +│ +├── All Users +├── All Wallets +├── All Transactions +└── System Statistics + +--- + +## Core Components + +### 1. User Dashboard (`/dashboard`) + +**Purpose:** Allow users to view and purchase credits + +**Features:** +- Display current credit balance +- Credit purchase form +- Transaction history +- Real-time updates + +**Location:** `app/dashboard/page.tsx` + +### 2. Admin Dashboard (`/admin`) + +**Purpose:** System oversight and management + +**Features:** +- View all users +- View all wallets +- View all transactions +- System statistics + +**Access:** Restricted to `admin@admin.com` (configured via `ADMIN_EMAIL`) + +**Location:** `app/admin/page.tsx` + +### 3. Purchase API Route (`/api/purchase`) + +**Purpose:** Process credit purchases + +**Flow:** +1. Authenticate user +2. Validate purchase amount +3. Get or create user wallet +4. Initiate USDC transfer from user to admin wallet +5. Create transaction record (pending) +6. Return transaction ID + +**Location:** `app/api/purchase/route.ts` + +### 4. Webhook Handler (`/api/circle/webhook`) + +**Purpose:** Receive and process Circle transaction events + +**Flow:** +1. Verify webhook signature +2. Parse event payload +3. Update transaction status +4. Credit user account (if completed) +5. Handle failures + +**Location:** `app/api/circle/webhook/route.ts` + +--- + +## Credit Purchase Flow + +### Step-by-Step Process + +User Initiates Purchase +└─> User enters credit amount +└─> Clicks "Purchase Credits" +Frontend Validation +└─> Validates amount > 0 +└─> Calculates USDC cost +└─> Confirms with user +API Request +POST /api/purchase +Body: { amount: 100, usdcCost: 10 } +Backend Processing +├─> Authenticate user (Supabase) +├─> Validate request +├─> Get user wallet ID (or create) +├─> Call Circle SDK to initiate transfer: +│ transferUSDC({ +│ from: userWalletId, +│ to: adminWalletId, +│ amount: usdcCost +│ }) +└─> Create transaction record: +{ +user_id, +amount: 100 credits, +usdc_cost: 10, +status: 'pending', +circle_transfer_id +} +USDC Transfer (On-Chain) +└─> Circle executes transfer on Arc testnet +└─> User wallet → Admin wallet +Webhook Notification +└─> Circle sends webhook: transfer.completed +└─> Signature verified +└─> Transaction updated: status = 'completed' +└─> User credits incremented by 100 +User Dashboard Update +└─> Real-time update via Supabase subscription +└─> New balance displayed + + +### Transaction States + +```typescript +type TransactionStatus = + | 'pending' // Transfer initiated + | 'completed' // Transfer confirmed, credits added + | 'failed' // Transfer failed +``` + +--- + +## Admin Dashboard + +### Purpose + +Provides system administrators with oversight of: +- User accounts +- Wallet addresses +- Transaction history +- System health + +### Access Control + +```typescript +// Middleware checks if user email matches ADMIN_EMAIL +const isAdmin = user.email === process.env.ADMIN_EMAIL + +if (!isAdmin) { + redirect('/dashboard') +} +``` + +### Admin Features + +**1. User Management** +- View all registered users +- See user credit balances +- Track user activity + +**2. Wallet Overview** +- List all user wallets +- View wallet addresses +- Monitor wallet creation + +**3. Transaction History** +- All system transactions +- Filter by status +- Export capabilities (future) + +**4. System Statistics** +- Total users +- Total transactions +- Total USDC processed +- Credit circulation + +### Admin Wallet + +**Purpose:** Receives all USDC payments from users + +**Creation:** Automatically generated on first app startup + +**Management:** +- Stored in database (wallets table) +- Address accessible to all API routes +- Used as destination for all purchases + +--- + +## Circle Wallets Integration + +### Wallet Types + +**1. Admin Wallet** +- Single wallet for entire system +- Receives all user payments +- Created automatically on startup + +**2. User Wallets** +- One wallet per user +- Created on first purchase +- Stored with user ID + +### Wallet Creation Flow + +```typescript +import { initiateDeveloperControlledWalletsClient } from '@circle-fin/developer-controlled-wallets' + +const client = initiateDeveloperControlledWalletsClient({ + apiKey: process.env.CIRCLE_API_KEY!, + entitySecret: process.env.CIRCLE_ENTITY_SECRET!, +}) + +// Create wallet +const response = await client.createWallets({ + blockchains: ['ARC-TESTNET'], + count: 1, + walletSetId: 'default', +}) + +const wallet = response.data?.wallets?.[0] +// Store wallet.id and wallet.address in database +``` + +### USDC Transfer Flow + +```typescript +// Transfer USDC from user to admin +const transfer = await client.createTransaction({ + walletId: userWalletId, + blockchain: 'ARC-TESTNET', + tokenAddress: process.env.CIRCLE_USDC_TOKEN_ID, + destinationAddress: adminWalletAddress, + amounts: [usdcAmount.toString()], + fee: { + type: 'level', + config: { feeLevel: 'MEDIUM' }, + }, +}) + +// Returns transfer ID for tracking +const transferId = transfer.data?.id +``` + +### SDK Configuration + +```typescript +const client = initiateDeveloperControlledWalletsClient({ + apiKey: process.env.CIRCLE_API_KEY, + entitySecret: process.env.CIRCLE_ENTITY_SECRET, +}) +``` + +**Environment Variables:** +- `CIRCLE_API_KEY` - Circle API authentication +- `CIRCLE_ENTITY_SECRET` - Entity secret for wallet operations +- `CIRCLE_BLOCKCHAIN` - Target blockchain (ARC-TESTNET) +- `CIRCLE_USDC_TOKEN_ID` - USDC token address + +--- + +## Database Schema + +### Tables + +**1. users** +```sql +CREATE TABLE users ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + email TEXT UNIQUE NOT NULL, + created_at TIMESTAMPTZ DEFAULT NOW(), + credits INTEGER DEFAULT 0, + wallet_id TEXT, -- Circle wallet ID + wallet_address TEXT -- On-chain address +); +``` + +**2. transactions** +```sql +CREATE TABLE transactions ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + user_id UUID REFERENCES users(id), + credit_amount INTEGER NOT NULL, + usdc_cost NUMERIC(10,2) NOT NULL, + status TEXT NOT NULL, -- 'pending' | 'completed' | 'failed' + circle_transfer_id TEXT, -- Circle transaction ID + created_at TIMESTAMPTZ DEFAULT NOW(), + completed_at TIMESTAMPTZ +); +``` + +**3. wallets** +```sql +CREATE TABLE wallets ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + user_id UUID REFERENCES users(id), + wallet_id TEXT NOT NULL, -- Circle wallet ID + wallet_address TEXT NOT NULL, -- On-chain address + blockchain TEXT DEFAULT 'ARC-TESTNET', + created_at TIMESTAMPTZ DEFAULT NOW(), + is_admin BOOLEAN DEFAULT FALSE +); +``` + +### Row-Level Security (RLS) + +**Users Table:** +```sql +-- Users can only see their own data +CREATE POLICY "Users can view own data" + ON users FOR SELECT + USING (auth.uid() = id); + +-- Admins can see all users +CREATE POLICY "Admins can view all users" + ON users FOR SELECT + USING ( + (SELECT email FROM users WHERE id = auth.uid()) = 'admin@admin.com' + ); +``` + +**Transactions Table:** +```sql +-- Users can view their own transactions +CREATE POLICY "Users can view own transactions" + ON transactions FOR SELECT + USING (user_id = auth.uid()); + +-- Admins can view all transactions +CREATE POLICY "Admins can view all transactions" + ON transactions FOR SELECT + USING ( + (SELECT email FROM users WHERE id = auth.uid()) = 'admin@admin.com' + ); +``` + +--- + +## Webhook System + +### Purpose + +Receive real-time notifications from Circle when transactions complete + +### Endpoint +POST /api/circle/webhook + +### Signature Verification + +```typescript +import crypto from 'crypto' + +function verifyWebhookSignature( + payload: string, + signature: string, + secret: string +): boolean { + const hmac = crypto.createHmac('sha256', secret) + const digest = hmac.update(payload).digest('hex') + return crypto.timingSafeEqual( + Buffer.from(signature), + Buffer.from(digest) + ) +} +``` + +### Event Types + +**transfer.completed** +```json +{ + "type": "transfer.completed", + "data": { + "id": "transfer-id", + "from": "user-wallet-address", + "to": "admin-wallet-address", + "amount": "10.00", + "status": "completed" + } +} +``` + +**transfer.failed** +```json +{ + "type": "transfer.failed", + "data": { + "id": "transfer-id", + "error": "insufficient_balance" + } +} +``` + +### Processing Flow + +1. Receive webhook POST request +2. Verify signature using Circle's public key +3. Parse event type and data +4. Match transfer ID to pending transaction +5. Update transaction status +6. If completed: credit user account +7. Return 200 OK to acknowledge receipt + +--- + +## Security Model + +### Authentication + +- **Supabase Auth** - User authentication +- **JWT tokens** - Session management +- **Email verification** - Account security + +### Authorization + +- **RLS policies** - Database access control +- **Admin checks** - Admin-only routes +- **User isolation** - Users can only access their own data + +### API Security + +- **Environment variables** - Secrets never committed +- **Webhook signatures** - Verify Circle events +- **Input validation** - Sanitize all inputs +- **Error handling** - No sensitive data in errors + +### Wallet Security + +- **Server-side only** - Wallet operations in API routes +- **Entity secret** - Required for wallet operations +- **No private key storage** - Circle manages keys + +### Rate Limiting + +**Supabase:** +- Email signups: 2 per hour (default) +- Can be configured via Supabase dashboard + +**Future:** +- API route rate limiting +- Purchase limits per user + +--- + +## Deployment Considerations + +### Environment Variables + +All sensitive configuration via environment variables: +- Circle credentials +- Supabase credentials +- Admin email +- Webhook secrets + +### Database Migrations + +- Use Supabase migrations for schema changes +- Test migrations in dev before production +- Keep migration files in version control + +### Webhook Configuration + +- Use HTTPS in production +- Configure webhook URL in Circle Console +- Test with ngrok in development + +### Monitoring + +- Log all transactions +- Monitor webhook delivery +- Track failed purchases +- Alert on errors + +--- + +## Further Reading + +- [Circle Developer Controlled Wallets](https://developers.circle.com/wallets/dev-controlled) +- [Next.js Documentation](https://nextjs.org/docs) +- [Supabase Documentation](https://supabase.com/docs) +- [Arc Testnet](https://developers.circle.com/arc) + +--- + +**This architecture enables seamless USDC credit purchases with real-time updates and comprehensive admin oversight.** diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md new file mode 100644 index 0000000..149722c --- /dev/null +++ b/docs/TROUBLESHOOTING.md @@ -0,0 +1,727 @@ +# arc-commerce Troubleshooting Guide + +This guide helps you resolve common issues when developing with arc-commerce. + +## Table of Contents +- [Installation Issues](#installation-issues) +- [API Key Setup](#api-key-setup) +- [Database Issues](#database-issues) +- [Webhook Issues](#webhook-issues) +- [Credit Purchase Errors](#credit-purchase-errors) +- [Admin Dashboard Issues](#admin-dashboard-issues) +- [Runtime Errors](#runtime-errors) +- [Deployment Issues](#deployment-issues) +- [FAQ](#faq) + +--- + +## Installation Issues + +### Node Version Mismatch + +**Problem:** README requires Node v22+, but you have v20 + +**Error:** +Warning: The current Node version v20.x.x does not meet the required version v22+ + +**Solutions:** + +1. **Install Node v22 with nvm:** +```bash + nvm install 22 + nvm use 22 + node --version # Should show v22.x.x +``` + +2. **Or continue with v20:** (may work but not officially supported) +```bash + # arc-commerce likely works on v20, test it + npm install + npm run dev +``` + +### npm Install Warnings + +**Problem:** Deprecation warnings during `npm install` + +**Common warnings:** +npm warn deprecated inflight@1.0.6 +npm warn deprecated @humanwhocodes/config-array@0.11.14 + +**Solution:** These are generally safe to ignore. They're from dependencies and don't affect functionality. + +### npm Vulnerabilities + +**Problem:** `npm install` reports vulnerabilities + +**Output:** +21 vulnerabilities (15 moderate, 6 high) + +**Solution:** + +1. **Check if fixable:** +```bash + npm audit fix +``` + +2. **Most are in dev dependencies:** Generally safe for development + +3. **For production:** Address before deploying: +```bash + npm audit fix --force # Use with caution +``` + +### Docker Not Running + +**Problem:** `npx supabase start` fails + +**Error:** +Error: Cannot connect to the Docker daemon + +**Solution:** + +1. **Start Docker Desktop** +2. **Wait for Docker to fully start** (check icon) +3. **Try again:** +```bash + npx supabase start +``` + +--- + +## API Key Setup + +### Circle API Key Not Working + +**Problem:** API requests fail with authentication error + +**Error:** +Error: Invalid API key + +**Solutions:** + +1. **Verify API key format:** +```bash + # Should start with: TEST_API_KEY:xxx or LIVE_API_KEY:xxx + echo $CIRCLE_API_KEY +``` + +2. **Check environment file:** +```bash + cat .env.local | grep CIRCLE_API_KEY +``` + +3. **Regenerate key:** + - Go to https://console.circle.com + - Navigate to **Settings → API Keys** + - Create new **Sandbox** key (for testnet) + - Update `.env.local` + +### Entity Secret Issues + +**Problem:** Wallet creation fails + +**Error:** +Error: Invalid entity secret + +**Solutions:** + +1. **Verify entity secret exists:** +```bash + cat .env.local | grep CIRCLE_ENTITY_SECRET +``` + +2. **Generate new entity secret:** + - Go to Circle Console → **Settings → Entity Secrets** + - Click **"Generate Entity Secret"** + - **Copy immediately** (can't view again!) + - Update `.env.local` + +3. **Format check:** Should be a long alphanumeric string + +### Admin Wallet Not Created + +**Problem:** App starts but admin wallet missing + +**Error:** +Error: Admin wallet not found + +**Solutions:** + +1. **Check database:** +```bash + # Local Supabase + npx supabase db reset + npx supabase migration up + + # Then restart app + npm run dev +``` + +2. **Verify admin email:** +```bash + # Must match ADMIN_EMAIL in .env.local + cat .env.local | grep ADMIN_EMAIL +``` + +3. **Check logs:** Look for wallet creation errors on startup + +4. **Manual creation:** Check admin initialization code in `lib/admin.ts` + +--- + +## Database Issues + +### Supabase Connection Failed + +**Problem:** Can't connect to Supabase + +**Error:** +Error: Failed to connect to Supabase + +**Solutions:** + +**Local Supabase:** +```bash +# Check if running +npx supabase status + +# If not running, start it +npx supabase start + +# Verify URL matches .env.local +npx supabase status | grep "API URL" +``` + +**Remote Supabase:** +```bash +# Test connection +curl https://your-project.supabase.co/rest/v1/ + +# Verify credentials in Supabase dashboard: +# Settings → API → Project URL and keys +``` + +### Migration Errors + +**Problem:** Database migrations fail + +**Error:** +Error applying migration + +**Solutions:** + +1. **Reset database (local):** +```bash + npx supabase db reset + npx supabase migration up +``` + +2. **Check migration files:** +```bash + ls supabase/migrations/ + # Should see .sql files +``` + +3. **Manual migration (remote):** +```bash + npx supabase db push +``` + +### RLS Policy Errors + +**Problem:** "Row level security policy violation" + +**Error:** +Error: new row violates row-level security policy + +**Solutions:** + +1. **Verify RLS enabled:** +```sql + -- In Supabase SQL Editor + SELECT tablename, rowsecurity + FROM pg_tables + WHERE schemaname = 'public'; +``` + +2. **Check policies exist:** +```sql + SELECT * FROM pg_policies; +``` + +3. **Disable RLS temporarily (dev only):** +```sql + ALTER TABLE users DISABLE ROW LEVEL SECURITY; + -- Remember to re-enable! +``` + +### Email Rate Limit + +**Problem:** "Email rate limit exceeded" + +**Error:** +Error: Email rate limit exceeded. Please try again later. + +**Solutions:** + +**Local Supabase:** +```bash +# Check Inbucket for emails +open http://127.0.0.1:54324 + +# Adjust rate limit in supabase/config.toml +[auth.rate_limit] +emails = 10 # Increase from 2 +``` + +**Remote Supabase:** +- Use unique email addresses +- Wait 1 hour between signups +- Configure custom SMTP (Settings → Auth → SMTP) +- Manually add users via dashboard + +--- + +## Webhook Issues + +### Webhooks Not Received + +**Problem:** Transactions stuck in "pending" status + +**Checklist:** + +1. **ngrok running?** +```bash + # In separate terminal + ngrok http 3000 + # Copy HTTPS URL +``` + +2. **Webhook URL configured in Circle Console?** + - Go to Circle Console → **Webhooks** + - Add endpoint: `https://your-ngrok-url.ngrok.io/api/circle/webhook` + - Save changes + +3. **Test webhook endpoint:** +```bash + curl -X POST http://localhost:3000/api/circle/webhook \ + -H "Content-Type: application/json" \ + -d '{"type":"test"}' + + # Should return 200 OK +``` + +4. **Check Circle webhook logs:** + - Circle Console → Webhooks → Your endpoint + - View delivery attempts and errors + +### Webhook Signature Verification Failed + +**Problem:** Webhooks rejected + +**Error:** +Error: Invalid webhook signature + +**Solutions:** + +1. **Get webhook secret from Circle Console** +2. **Add to environment:** +```bash + # .env.local + CIRCLE_WEBHOOK_SECRET=your-webhook-secret +``` + +3. **Verify signature logic:** +```typescript + // Check implementation in /api/circle/webhook/route.ts + const signature = request.headers.get('circle-signature') + // Should match HMAC SHA256 of payload +``` + +4. **Test with Circle's test events** in Console + +--- + +## Credit Purchase Errors + +### Purchase Fails Immediately + +**Problem:** Purchase API returns error + +**Common errors:** + +**1. User wallet not found:** +Error: User wallet not created +**Solution:** +- Wallet should auto-create on first purchase +- Check wallet creation logic in `/api/purchase/route.ts` +- Verify Circle credentials + +**2. Insufficient USDC:** +Error: Insufficient balance +**Solution:** +- Get testnet USDC from [Circle Faucet](https://faucet.circle.com/) +- Enter your wallet address (shown in dashboard) +- Wait for transaction confirmation + +**3. Invalid amount:** +Error: Invalid credit amount +**Solution:** +- Check amount is positive number +- Verify USDC calculation logic + +### Transaction Stuck in Pending + +**Problem:** Purchase doesn't complete + +**Debugging:** + +1. **Check transaction status:** +```bash + # In Supabase SQL Editor + SELECT * FROM transactions + WHERE status = 'pending' + ORDER BY created_at DESC; +``` + +2. **Verify webhook received:** + - Check ngrok request log + - Check Circle webhook delivery status + - Check app logs for webhook processing + +3. **Manual completion (dev only):** +```sql + -- Update transaction + UPDATE transactions + SET status = 'completed', + completed_at = NOW() + WHERE id = 'transaction-id'; + + -- Credit user + UPDATE users + SET credits = credits + 100 + WHERE id = 'user-id'; +``` + +### Credits Not Added After Payment + +**Problem:** USDC transferred but credits not updated + +**Debugging:** + +1. **Check webhook processed:** +```bash + # Check app logs + # Should see: "Webhook received: transfer.completed" +``` + +2. **Verify transaction updated:** +```sql + SELECT * FROM transactions + WHERE circle_transfer_id = 'transfer-id'; +``` + +3. **Check user credits:** +```sql + SELECT id, email, credits + FROM users + WHERE id = 'user-id'; +``` + +4. **Manual fix:** +```sql + UPDATE users + SET credits = credits + [amount] + WHERE id = 'user-id'; +``` + +--- + +## Admin Dashboard Issues + +### Can't Access Admin Dashboard + +**Problem:** Redirected to user dashboard + +**Solutions:** + +1. **Verify admin email:** +```bash + cat .env.local | grep ADMIN_EMAIL + # Default: admin@admin.com +``` + +2. **Check logged-in email matches:** + - Log out + - Log in with admin@admin.com + - Password: 123456 (default) + +3. **Verify admin check logic:** +```typescript + // In app/admin/page.tsx + const isAdmin = user.email === process.env.ADMIN_EMAIL +``` + +### Admin Dashboard Shows No Data + +**Problem:** Dashboard empty despite having users/transactions + +**Solutions:** + +1. **Check RLS policies allow admin access:** +```sql + -- Admin should see all users + SELECT * FROM users; -- Run as admin +``` + +2. **Verify admin policy exists:** +```sql + SELECT * FROM pg_policies + WHERE tablename = 'users' + AND policyname LIKE '%admin%'; +``` + +3. **Add missing admin policy:** +```sql + CREATE POLICY "Admins can view all users" + ON users FOR SELECT + USING ( + (SELECT email FROM users WHERE id = auth.uid()) = 'admin@admin.com' + ); +``` + +--- + +## Runtime Errors + +### Wallet Creation Fails + +**Problem:** "Error creating wallet" + +**Solutions:** + +1. **Verify Circle credentials:** +```bash + cat .env.local | grep CIRCLE +``` + +2. **Check Circle SDK initialized:** +```typescript + import { initiateDeveloperControlledWalletsClient } from '@circle-fin/developer-controlled-wallets' + + const client = initiateDeveloperControlledWalletsClient({ + apiKey: process.env.CIRCLE_API_KEY!, + entitySecret: process.env.CIRCLE_ENTITY_SECRET!, + }) +``` + +3. **Test wallet creation:** +```bash + # Create test script + node scripts/test-wallet-creation.js +``` + +### USDC Transfer Fails + +**Problem:** Transfer API call fails + +**Common issues:** + +1. **Invalid wallet ID:** +Error: Wallet not found + - Verify wallet exists in database + - Check wallet ID format + +2. **Invalid token address:** +Error: Invalid token address + - Verify `CIRCLE_USDC_TOKEN_ID` in `.env.local` + - Should match Arc testnet USDC address + +3. **Insufficient balance:** +Error: Insufficient balance for transfer + - Get USDC from faucet + - Check actual wallet balance + +### Authentication Errors + +**Problem:** User not authenticated + +**Error:** +Error: Not authenticated + +**Solutions:** + +1. **Check Supabase client:** +```typescript + import { createClient } from '@/lib/supabase/client' + const supabase = createClient() + const { data: { user } } = await supabase.auth.getUser() +``` + +2. **Verify session:** +```bash + # Check browser localStorage + # Should have supabase.auth.token +``` + +3. **Re-login:** + - Log out + - Clear browser cache + - Log back in + +--- + +## Deployment Issues + +### Environment Variables Not Working + +**Problem:** App can't find environment variables in production + +**Solutions:** + +1. **Verify variables set in deployment platform:** + - Vercel: Settings → Environment Variables + - Add all from `.env.local` + +2. **Check variable names:** + - Must be EXACT match (case-sensitive) + - No typos + +3. **Redeploy after adding variables:** + - Changes require new deployment + +### Build Fails + +**Problem:** `npm run build` fails in production + +**Common issues:** + +1. **TypeScript errors:** +```bash + # Fix locally first + npx tsc --noEmit + # Fix all errors shown +``` + +2. **Missing environment variables:** +```bash + # Add all required vars to deployment platform +``` + +3. **Linting errors:** +```bash + npm run lint + # Fix all errors +``` + +--- + +## FAQ + +### Q: How do I get testnet USDC? + +**A:** Use the [Circle Faucet](https://faucet.circle.com/) +1. Get your wallet address from dashboard +2. Visit faucet +3. Select Arc Testnet +4. Request USDC +5. Wait for confirmation (~1 minute) + +### Q: Why is my purchase stuck? + +**A:** Usually webhook not received: +1. Check ngrok is running +2. Verify webhook URL in Circle Console +3. Check webhook logs in Circle Console +4. Test endpoint manually + +### Q: How do I reset everything? + +**A:** Fresh start: +```bash +# Stop everything +npx supabase stop + +# Clear database +rm -rf supabase/.branches + +# Restart +npx supabase start +npx supabase migration up +npm run dev +``` + +### Q: Can I test without real USDC? + +**A:** Yes, use Arc testnet: +- Testnet USDC is free (use faucet) +- No real money involved +- Reset anytime + +### Q: How do I add more admins? + +**A:** Current design: single admin +To add more: +1. Modify admin check to use array: +```typescript + const adminEmails = [ + 'admin@admin.com', + 'admin2@admin.com' + ] + const isAdmin = adminEmails.includes(user.email) +``` +2. Update RLS policies +3. Redeploy + +### Q: What's the credit-to-USDC ratio? + +**A:** Configurable in your code: +```typescript +// Example: 1 USDC = 10 credits +const USDC_PER_CREDIT = 0.1 +``` + +### Q: Can users withdraw USDC? + +**A:** Not in current implementation +- System is one-way (USDC → Credits) +- Add withdrawal feature requires: + - Reverse transfer logic + - Credit deduction + - Admin approval (optional) + +### Q: How do I handle refunds? + +**A:** Manual process currently: +1. Reverse credit transaction in database +2. Initiate USDC transfer back to user +3. Update transaction status + +### Q: Why do I see npm warnings? + +**A:** Common and usually safe: +- Deprecation warnings: Dependencies will update +- Vulnerabilities: Mostly in dev dependencies +- Ignore unless critical + +### Q: How do I monitor transactions? + +**A:** Multiple ways: +1. Admin dashboard (UI) +2. Supabase dashboard (database) +3. Circle Console (webhooks) +4. Application logs (errors) + +--- + +## Still Having Issues? + +1. **Check GitHub Issues:** https://github.com/circlefin/arc-commerce/issues +2. **Circle Documentation:** https://developers.circle.com +3. **Supabase Docs:** https://supabase.com/docs +4. **Open a Discussion:** Share your problem with the community + +--- + +**Remember:** This is a sample application for testnet. For production use, implement additional error handling, monitoring, and security measures.