This document describes the architecture and design decisions of the Aqua Stark Backend API.
The Aqua Stark Backend API is a lightweight orchestration layer that coordinates actions between:
- Unity (frontend)
- Cartridge (authentication)
- Supabase (off-chain data)
- Dojo + Cairo contracts (on-chain)
┌─────────┐
│ Unity │
│(Client) │
└────┬────┘
│
│ HTTP/JSON
│
┌────▼─────────────────────┐
│ Aqua Stark Backend │
│ (Fastify API) │
└────┬─────────────────────┘
│
├──────────┬──────────┬──────────┐
│ │ │ │
┌────▼───┐ ┌───▼───┐ ┌────▼────┐ ┌───▼────┐
│Cartridge│ │Supabase│ │ Dojo │ │Starknet│
│ Auth │ │ DB │ │ ECS │ │ RPC │
└────────┘ └────────┘ └─────────┘ └────────┘
The application follows a layered architecture:
┌─────────────────────────────────────┐
│ API Layer │
│ (Routes, Request/Response) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Controller Layer │
│ (Extract params, call services) │
└──────────────┬──────────────────────┘
│
┌──────────────▼──────────────────────┐
│ Service Layer │
│ (Business logic, orchestration) │
└──────────────┬──────────────────────┘
│
┌─────────┴─────────┐
│ │
┌────▼────┐ ┌─────▼─────┐
│Supabase │ │ Dojo/ │
│ DB │ │ Starknet │
└─────────┘ └────────────┘
/src
├── api/ # Route definitions grouped by resource
│ └── index.ts # Route registration
├── controllers/ # Request handlers (no business logic)
│ └── *.controller.ts
├── services/ # Business logic and orchestration
│ └── *.service.ts
├── models/ # Domain entities and DTOs
│ └── *.model.ts
└── core/ # Core system components
├── types/ # Shared types (LOCKED)
├── errors/ # Custom error classes
├── responses/ # Response helpers (LOCKED)
├── middleware/ # Global middleware
├── utils/ # Pure utility functions
└── config/ # Configuration and constants
Client → Fastify → Route Handler
Controller extracts:
- URL parameters
- Query parameters
- Request body
- Headers
Service performs:
- Input validation
- Business logic
- Database operations (Supabase)
- On-chain operations (Dojo/Starknet)
Service returns data
↓
Controller wraps in standard response
↓
Fastify sends JSON response
Error occurs
↓
Error middleware catches it
↓
Transforms to standard error format
↓
Returns with appropriate HTTP status
Defines the locked response types that ensure consistency:
SuccessResponse<T>- Success response structureErrorResponse- Error response structureControllerResponse<T>- Mandatory controller return type
Status: LOCKED - Cannot be modified
Helper functions for creating standardized responses:
createSuccessResponse()- Creates success responsescreateErrorResponse()- Creates error responses
Status: LOCKED - Cannot be modified
Custom error classes for different error scenarios:
ValidationError(400)NotFoundError(404)ConflictError(409)OnChainError(500)
Global middleware for error handling:
errorHandler- Catches all errors and transforms to standard format
Each layer has a single, well-defined responsibility:
- Controllers: Request/response handling
- Services: Business logic
- Models: Data structures
- Core: System infrastructure
TypeScript strict mode ensures:
- All types are explicit
- No
anytypes - Compile-time error checking
- Response format enforcement
- All responses follow the same format
- All errors use custom error classes
- Consistent naming conventions
- Uniform code structure
- Modular architecture
- Easy to add new endpoints
- Clear separation allows parallel development
- Standardized patterns reduce learning curve
1. Unity opens Cartridge login WebView
2. User authenticates with Cartridge
3. Cartridge redirects with wallet address
4. Unity sends address to backend
5. Backend:
- Creates player if new (register_player on-chain)
- Returns player data if exists
No wallet or signing happens directly in Unity.
- Player profiles
- Fish data
- Tank configurations
- Game state
- Player registration
- Fish breeding
- Transactions
- Ownership records
- Backend executes on-chain action
- Saves
tx_hashto sync queue - Background process confirms transaction
- Updates Supabase if needed
| Component | Technology | Version | Purpose |
|---|---|---|---|
| Runtime | Node.js | 20.10.0 | JavaScript execution |
| Language | TypeScript | 5.3.x | Type safety |
| Framework | Fastify | 4.24.x | HTTP server |
| Database | Supabase | 2.38.3 | Off-chain data |
| Blockchain | Starknet.js | 5.14.x | On-chain interactions |
| Game Engine | Dojo | 0.4.x | ECS on-chain |
All configuration is centralized in /core/config/:
- Environment variables
- External endpoints
- Game constants
- Multipliers and limits
The architecture is designed to support:
- Horizontal scaling
- Microservices migration (if needed)
- Additional game features
- Multiple client types
- Real-time updates (WebSocket support)