This is a Turborepo monorepo containing the ShapeShift backend microservices.
shapeshift-backend/
├── apps/
│ ├── user-service/ # User accounts microservice
│ ├── swap-service/ # Swap microservice
│ └── notifications-service/ # Notifications microservice
├── packages/
│ ├── shared-types/ # Shared TypeScript types
│ └── shared-utils/ # Shared utilities
├── turbo.json # Turborepo configuration
├── package.json # Root package.json
└── docker-compose.yml # Docker Compose for development
- Port: 3002
- Purpose: Manages user accounts, devices, and authentication
- Database: SQLite (development) / PostgreSQL (production)
- API:
/users/*
- Port: 3001
- Purpose: Handles swaps and WebSocket connections
- Database: SQLite (development) / PostgreSQL (production)
- API:
/swaps/* - WebSocket: Real-time updates
- Dependencies: User Service, Notifications Service
- Port: 3003
- Purpose: Manages notifications and push notifications
- Database: SQLite (development) / PostgreSQL (production)
- API:
/notifications/* - WebSocket: Real-time notifications
- Dependencies: User Service
┌─────────────────┐ HTTP ┌─────────────────┐
│ User Service │◄──────────►│ Swap Service │
│ (Port 3002) │ │ (Port 3001) │
└─────────────────┘ └─────────────────┘
▲ ▲
│ HTTP │ HTTP
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Notifications │ │ Notifications │
│ Service │ │ Service │
│ (Port 3003) │ │ (Port 3003) │
└─────────────────┘ └─────────────────┘
- Node.js 22+
- Yarn 4+
- Docker (optional, for containerized development)
-
Copy the environment variables Copy
.env.exampleinto.envat the root of the repository Ask the team for the EXPO token used to launch notifications -
Install dependencies:
yarn install
-
Build shared packages:
yarn build
-
Set up databases:
# Generate Prisma clients yarn db:generate # Push db structure yarn db:push # Run migrations yarn db:migrate
# Start all services in development mode
yarn start:dev
# Or start individual services
yarn workspace @shapeshift/user-service start:dev
yarn workspace @shapeshift/swap-service start:dev
yarn workspace @shapeshift/notifications-service start:dev# Start all services with Docker
docker-compose up -d
# View logs
docker-compose logs -fyarn build- Build all packages and appsyarn dev- Start all services in development modeyarn test- Run tests for all packagesyarn lint- Lint all packagesyarn db:generate- Generate Prisma clientsyarn db:push- Push default database structureyarn db:migrate- Run database migrationsyarn clean- Clean all builds and node_modules
yarn workspace @shapeshift/user-service dev- Start user serviceyarn workspace @shapeshift/swap-service dev- Start swap serviceyarn workspace @shapeshift/notifications-service dev- Start notifications serviceyarn workspace @shapeshift/shared-types build- Build shared typesyarn workspace @shapeshift/shared-utils build- Build shared utils
POST /users # Create user
GET /users # Get all users
GET /users/:userId # Get user by ID
POST /users/get-or-create # Get or create user
GET /users/account/:accountId # Get user by account ID
POST /users/:userId/account-id # Add account ID
POST /users/:userId/devices # Register device
GET /users/:userId/devices # Get user devices
POST /swaps # Create swap
GET /swaps # Get all swaps
GET /swaps/:swapId # Get swap by ID
GET /swaps/user/:userId # Get swaps by user
PUT /swaps/:swapId # Update swap
POST /notifications # Create notification
POST /notifications/register-device # Register device
GET /notifications/user/:userId # Get user notifications
PUT /notifications/:id/read # Mark notification as read
GET /notifications/devices/:userId # Get user devices
POST /notifications/send-to-user # Send notification to user
POST /notifications/send-to-device # Send notification to device
PORT=3001
DATABASE_URL=file:./dev.db
USER_SERVICE_URL=http:/localhost:3001
NOTIFICATIONS_SERVICE_URL=http:/localhost:3003PORT=3002
DATABASE_URL=file:./user-service.db
ACCOUNT_ID_SALT=your-salt-herePORT=3003
DATABASE_URL=file:./notifications-service.db
USER_SERVICE_URL=http:/localhost:3001
EXPO_ACCESS_TOKEN=your-expo-tokenUpdate the DATABASE_URL in each service's environment to point to your PostgreSQL instance.
Services communicate via HTTP APIs using the service clients in @shapeshift/shared-utils:
import { UserServiceClient, NotificationsServiceClient } from '@shapeshift/shared-utils';
const userClient = new UserServiceClient();
const notificationsClient = new NotificationsServiceClient();
/ Get user from user service
const user = await userClient.getUserById(userId);
/ Send notification
await notificationsClient.createNotification({
userId,
title: 'Swap Completed',
body: 'Your swap has been completed successfully',
type: 'SWAP_COMPLETED',
swapId: swapId
});- Swap Service: Handles swap-related WebSocket connections
- Notifications Service: Handles notification-related WebSocket connections
# Build production images
docker-compose -f docker-compose.prod.yml build
# Deploy
docker-compose -f docker-compose.prod.yml up -dEach service can be deployed independently as they are separate NestJS applications.
- Create a feature branch
- Make your changes
- Run tests:
yarn test - Run linting:
yarn lint - Submit a pull request
- Port conflicts: Make sure ports 3001, 3002, and 3003 are available
- Database issues: Run
yarn db:generateandyarn db:migrate - Build issues: Clean and rebuild:
yarn clean && yarn build - Service communication: Check environment variables for service URLs
# View service logs
yarn workspace @shapeshift/user-service logs
yarn workspace @shapeshift/swap-service logs
yarn workspace @shapeshift/notifications-service logs
# Docker logs
docker-compose logs -f user-service
docker-compose logs -f swap-service
docker-compose logs -f notifications-service