Skip to content

Latest commit

Β 

History

History
355 lines (285 loc) Β· 8.29 KB

File metadata and controls

355 lines (285 loc) Β· 8.29 KB

πŸš€ START TESTING NOW!

All migration work is COMPLETE. Here's what to do next:


⚑ Quick Start (5 minutes)

1. Start the Server

npm run dev

2. Open These URLs

3. Quick Smoke Test

Open browser console and run:

// Test predictions endpoint
fetch('/api/predictions', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    taskId: crypto.randomUUID(),
    eventId: crypto.randomUUID(),
    prediction: { home_score: 2, away_score: 1 }
  })
})
.then(r => r.json())
.then(d => console.log('βœ… Predictions working:', d))
.catch(e => console.error('❌ Error:', e));

// Test nonce endpoint
fetch('/api/auth/nonce', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    walletAddress: '0x1234567890123456789012345678901234567890'
  })
})
.then(r => r.json())
.then(d => console.log('βœ… Wallet auth working:', d))
.catch(e => console.error('❌ Error:', e));

Expected: Both should work βœ…


πŸ“‹ What Was Updated

βœ… Endpoints Migrated (5)

  1. Predictions - /api/predictions

    • Rate limiting βœ…
    • Validation βœ…
    • Cleaner code βœ…
  2. Twitter Verification - /api/tasks/verify-twitter

    • Rate limiting βœ…
    • Validation βœ…
    • Idempotency βœ…
  3. Wallet Nonce - /api/auth/nonce

    • Redis storage βœ…
    • Auto-expiring βœ…
    • Secure nonces βœ…
  4. Wallet Verify - /api/auth/verify

    • Redis consume βœ…
    • Rate limiting βœ…
    • One-time use βœ…
  5. Event Creation - /api/events

    • Rate limiting βœ…
    • Validation βœ…
    • Uses reward_types βœ…

βœ… Critical Bug Fixed

Duplicate Task Registry - Now consolidated!

  • Both pages use same registry βœ…
  • All task types available βœ…
  • No more confusion βœ…

βœ… Infrastructure Created

  • Redis client βœ…
  • Rate limiter βœ…
  • Idempotency guard βœ…
  • Nonce store βœ…
  • Validation middleware βœ…
  • Zod schemas (event, task, user) βœ…

🎯 Test These Scenarios

Scenario 1: Create an Event

  1. Go to /projects/create-event
  2. Fill out event details
  3. Click "Create Event"
  4. Check: Should use reward_types field βœ…
  5. Check: Creating 6 events in a row β†’ 6th should be rate limited βœ…

Scenario 2: Submit Prediction

  1. Go to any event with scoreline prediction
  2. Submit a prediction
  3. Submit again (update)
  4. Submit 11 times rapidly
  5. Check: First 10 work, 11th gets rate limited βœ…

Scenario 3: Wallet Auth

  1. Click "Connect Wallet"
  2. Request nonce
  3. Sign message
  4. Submit signature
  5. Check: Session created βœ…
  6. Try: Reuse same signature β†’ Should fail βœ…

Scenario 4: Twitter Verification

  1. Connect Twitter account
  2. Complete a Twitter task (follow, like, etc.)
  3. Click "Verify"
  4. Click "Verify" again within 60 seconds
  5. Check: Second attempt β†’ 409 Conflict βœ…

Scenario 5: Task Registry Consistency

  1. Open "Create Event" page
  2. Check available task types
  3. Open any event detail page
  4. Check available task types
  5. Check: SAME task types on both pages βœ…

πŸ› Known Issues (Pre-existing)

These lint warnings in Svelte files are pre-existing (not from our changes):

  • Accessibility warnings in events/[id]/+page.svelte
  • Unused CSS selectors

Action: Can be fixed later, not urgent.


πŸ“Š What Changed (Before/After)

Predictions Endpoint

Before (126 lines):

  • Manual JSON parsing
  • Manual type checking
  • No rate limiting
  • Verbose error handling

After (106 lines):

  • Zod validation βœ…
  • Rate limiting βœ…
  • Cleaner code βœ…
  • Better errors βœ…

Twitter Verification

Before:

  • In-memory rate limiting
  • Manual validation
  • Complex error handling

After:

  • Redis rate limiting βœ…
  • Zod validation βœ…
  • Idempotency guard βœ…
  • Cleaner code βœ…

Wallet Auth

Before:

  • In-memory nonce store
  • Random number nonces
  • No rate limiting

After:

  • Redis nonce store βœ…
  • Cryptographic nonces βœ…
  • Rate limiting βœ…
  • Auto-expiring βœ…

Event Creation

Before:

  • Manual validation
  • Used rewards field
  • No rate limiting

After:

  • Zod validation βœ…
  • Uses reward_types βœ…
  • Rate limiting βœ…
  • Supports new fields βœ…

Task Registry

Before:

  • TWO separate registries
  • Inconsistent across pages
  • Confusing imports

After:

  • ONE consolidated registry βœ…
  • Consistent everywhere βœ…
  • Clear imports βœ…

πŸ“ New File Structure

src/
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ infrastructure/
β”‚   β”‚   └── redis/              βœ… NEW
β”‚   β”‚       β”œβ”€β”€ client.ts
β”‚   β”‚       β”œβ”€β”€ rateLimiter.ts
β”‚   β”‚       β”œβ”€β”€ idempotency.ts
β”‚   β”‚       └── nonces.ts
β”‚   β”‚
β”‚   β”œβ”€β”€ server/
β”‚   β”‚   └── middleware/         βœ… NEW
β”‚   β”‚       β”œβ”€β”€ rateLimit.ts
β”‚   β”‚       └── validation.ts
β”‚   β”‚
β”‚   β”œβ”€β”€ shared/
β”‚   β”‚   β”œβ”€β”€ types/
β”‚   β”‚   β”‚   └── index.ts        βœ… UPDATED
β”‚   β”‚   └── validation/         βœ… NEW
β”‚   β”‚       └── schemas/
β”‚   β”‚           β”œβ”€β”€ event.schema.ts
β”‚   β”‚           β”œβ”€β”€ task.schema.ts
β”‚   β”‚           └── user.schema.ts
β”‚   β”‚
β”‚   └── tasks/
β”‚       β”œβ”€β”€ CONSOLIDATED_taskRegistry.ts  βœ… NEW
β”‚       β”œβ”€β”€ index.ts            βœ… UPDATED (re-export)
β”‚       └── taskRegistry.ts     βœ… UPDATED (re-export)
β”‚
└── routes/api/
    β”œβ”€β”€ predictions/+server.ts  βœ… UPDATED
    β”œβ”€β”€ tasks/verify-twitter/+server.ts  βœ… UPDATED
    β”œβ”€β”€ auth/
    β”‚   β”œβ”€β”€ nonce/+server.ts    βœ… UPDATED
    β”‚   └── verify/+server.ts   βœ… UPDATED
    └── events/+server.ts       βœ… UPDATED

πŸŽ“ Pattern for Future Endpoints

import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { supabaseAdmin } from '$lib/server/supabaseAdmin';
import { rateLimiter, RATE_LIMITS } from '$lib/infrastructure/redis/rateLimiter';
import { validateBody } from '$lib/server/middleware/validation';
import { yourSchema } from '$lib/shared/validation/schemas/your.schema';

export const POST: RequestHandler = async ({ request, locals }) => {
  // 1. Auth
  if (!locals.user) {
    return json({ error: 'Unauthorized' }, { status: 401 });
  }

  // 2. Rate limit
  await rateLimiter.check(`action:${locals.user.id}`, RATE_LIMITS.normal);

  // 3. Validate
  const validated = await validateBody(request, yourSchema);

  // 4. Business logic
  const { data, error } = await supabaseAdmin
    .from('table')
    .insert(validated);

  if (error) {
    return json({ error: 'Failed' }, { status: 500 });
  }

  // 5. Return
  return json({ success: true, data }, { status: 201 });
};

Copy this pattern for any new endpoint! βœ…


πŸ“ž Support

Documentation:

  • MIGRATION_COMPLETE.md - Full migration details
  • TEST_GUIDE.md - Comprehensive testing guide
  • ARCHITECTURE_README.md - Quick reference
  • SIMPLIFIED_ARCHITECTURE.md - Architecture guide

If you see errors:

  1. Check browser console
  2. Check server logs
  3. Check Redis dashboard (https://console.upstash.com)
  4. Check .env file has Redis credentials

Common issues:

  • "Redis connection failed" β†’ Check .env
  • "Validation error" β†’ Check request body format
  • "Rate limited" β†’ Wait 1 minute, try again
  • "Nonce expired" β†’ Request new nonce

βœ… Success Checklist

Before marking as complete:

  • Server starts without errors
  • Can create events
  • Can submit predictions
  • Wallet auth flow works
  • Task registry shows same types on all pages
  • Rate limiting works
  • No console errors
  • Redis dashboard shows activity

πŸŽ‰ You're Done!

What you have now:

  • βœ… Production-ready architecture
  • βœ… Redis-based rate limiting
  • βœ… Type-safe validation
  • βœ… Secure wallet auth
  • βœ… Idempotency guards
  • βœ… Single task registry
  • βœ… Clean, maintainable code

Next steps:

  1. Test thoroughly (see TEST_GUIDE.md)
  2. Apply pattern to remaining endpoints (Discord, Telegram, etc.)
  3. Monitor Redis usage
  4. Deploy to production

Ready? Start testing! πŸš€

npm run dev

Then open http://localhost:5173 and try it out!