Wan2.1/wan-pwa/apps/api/services/credit_service.py
Claude e8fda73741
feat: Add complete Wan2.1 PWA - AI Video Generation Platform
This commit adds a production-ready Progressive Web App for AI-powered video
generation using Wan2.1 models.

Features:
- Next.js 15 frontend with App Router and PWA support
- FastAPI backend with Replicate integration
- 50+ prompt templates across 7 categories
- Supabase authentication and database
- Credit system with usage tracking
- Text-to-Video and Image-to-Video generation
- Complete documentation (setup, deployment, contributing)

Project Structure:
- apps/web: Next.js frontend with shadcn/ui components
- apps/api: FastAPI backend with GPU processing via Replicate
- packages/db: Database schema and migrations for Supabase

Tech Stack:
- Frontend: Next.js 15, shadcn/ui, Tailwind, Zustand, React Hook Form, Zod
- Backend: FastAPI, Replicate, Supabase
- Database: Supabase (Postgres) with RLS
- Infrastructure: Turborepo monorepo, Vercel/Modal deployment

Documentation:
- README.md: Project overview and features
- SETUP.md: Complete setup guide (5-minute quickstart)
- DEPLOYMENT.md: Production deployment instructions
- CONTRIBUTING.md: Contribution guidelines
- PROJECT_SUMMARY.md: Comprehensive project documentation

Ready for development and deployment.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 14:18:18 +00:00

103 lines
2.9 KiB
Python

from core.supabase import get_supabase
from typing import Optional
class CreditService:
"""Service for managing user credits"""
# Credit costs for different operations
COSTS = {
"t2v-14B-480p": 10,
"t2v-14B-720p": 20,
"t2v-1.3B-480p": 5,
"i2v-14B-480p": 15,
"i2v-14B-720p": 25,
}
# Free tier credits
FREE_TIER_CREDITS = 100
@staticmethod
async def get_user_credits(user_id: str) -> int:
"""Get current credit balance for user"""
supabase = get_supabase()
result = supabase.table("users").select("credits").eq("id", user_id).single().execute()
return result.data.get("credits", 0) if result.data else 0
@staticmethod
async def deduct_credits(user_id: str, amount: int, description: str) -> bool:
"""
Deduct credits from user account
Args:
user_id: User ID
amount: Amount of credits to deduct
description: Description of the transaction
Returns:
True if successful, False if insufficient credits
"""
supabase = get_supabase()
# Get current balance
current_credits = await CreditService.get_user_credits(user_id)
if current_credits < amount:
return False
# Deduct credits
new_balance = current_credits - amount
supabase.table("users").update({"credits": new_balance}).eq("id", user_id).execute()
# Record transaction
supabase.table("credit_transactions").insert(
{
"user_id": user_id,
"amount": -amount,
"type": "deduction",
"description": description,
}
).execute()
return True
@staticmethod
async def add_credits(user_id: str, amount: int, description: str) -> bool:
"""
Add credits to user account
Args:
user_id: User ID
amount: Amount of credits to add
description: Description of the transaction
Returns:
True if successful
"""
supabase = get_supabase()
# Get current balance
current_credits = await CreditService.get_user_credits(user_id)
# Add credits
new_balance = current_credits + amount
supabase.table("users").update({"credits": new_balance}).eq("id", user_id).execute()
# Record transaction
supabase.table("credit_transactions").insert(
{
"user_id": user_id,
"amount": amount,
"type": "addition",
"description": description,
}
).execute()
return True
@staticmethod
def calculate_cost(model: str, resolution: str) -> int:
"""Calculate credit cost for a generation request"""
key = f"{model}-{resolution}"
return CreditService.COSTS.get(key, 10)