File Organization
Monorepo Structure
switchain-services/
├── apps/ # Deployable applications
│ ├── admin/ # Next.js 16 admin panel
│ ├── rates/ # Rates calculation API
│ ├── common-worker/ # Background event processor (BullMQ)
│ ├── wallets-worker/ # Background wallet tasks
│ └── sw-api/ # Core Switchain API
├── packages/ # Shared bounded contexts
│ ├── common/ # Shared abstractions, event system, logger
│ ├── database/ # Prisma schema and migrations
│ ├── cex-wallets/ # CEX integration (Binance, KuCoin, HTX)
│ ├── rates/ # Pricing, pairs, market data
│ ├── wallets/ # Crypto wallet operations
│ ├── shifts/ # Exchange shift transactions
│ └── partners/ # Partner account management
├── docs/ # Canonical conventions, commands, security, decisions, and development docs
├── .agents/ # Canonical shared agent definitions
├── CLAUDE.md # Claude Code instructions
└── .cursor/.rules/ # Cursor IDE rules (quick reference cards)Bounded Context Structure
Each package follows this DDD layer structure:
packages/<context>/
├── domain/
│ ├── entities/ # Domain entities — CexAccount.ts
│ ├── valueObjects/ # Value objects — CexAccountId.ts
│ ├── repositories/ # Interfaces — CexAccountRepository.ts
│ ├── services/ # Domain services — PairsBuilder.ts
│ ├── events/ # Domain events — CoinBlockchainCreatedDomainEvent.ts
│ └── ports/ # External service interfaces — CexSpotAccountPort.ts
├── application/
│ ├── services/ # Use cases — CoinBlockchainCreator.ts
│ └── eventSubscribers/ # Event handlers — UpdateCexCoinsBlockchainsOnCoinBlockchainCreated.ts
├── infrastructure/
│ ├── repositories/ # Prisma/InMemory repos — CexAccountPrismaRepository.ts
│ │ └── inMemory/ # In-memory repos — PairInMemoryRepository.ts
│ ├── adapters/ # External integrations — CctxCexSpotAccountAdapter.ts
│ ├── controllers/ # Thin HTTP layer — CexAccountFinderController.ts
│ └── factories/ # DI factories — CexAccountFactory.ts
├── test/
│ ├── mothers/ # Object Mother builders — CexAccountMother.ts
│ ├── application/
│ │ └── services/ # Application service tests
│ ├── domain/ # Domain service tests
│ └── test-constants.ts # Shared test data
└── index.ts # Public API exportsApp Structure
Applications in apps/ are thin consumers of packages:
apps/<app>/
├── infrastructure/
│ ├── factories/
│ │ └── EventsFactory.ts # Registers event subscribers
│ └── ...
├── application/
│ └── eventSubscribers/ # App-specific event handlers
└── index.tsImport Organization
Order imports as:
- External packages (
bun:test, third-party) - Internal
@sws/packages - Relative imports (same package)
typescript
import { describe, it, expect, mock } from 'bun:test'
import { LoggerFactory } from '@sws/common/logger'
import type { DomainEventSubscriber } from '@sws/common/domain'
import { CexAccount } from '../../domain/entities/CexAccount'
import { CexAccountMother } from '../../test/mothers/CexAccountMother'Public API Exports (index.ts)
Each package exports its public API through index.ts. Only export what external packages need:
typescript
// packages/cex-wallets/index.ts
export { UpdateCexCoinsBlockchainsOnCoinBlockchainCreated } from './application/eventSubscribers/UpdateCexCoinsBlockchainsOnCoinBlockchainCreated'
export { CexAccountTransferSender } from './application/services/transfers/CexAccountTransferSender'
export { CexAccountFactory } from './infrastructure/factories/CexAccountFactory'
export * from './domain'Test File Location
Tests live in packages/<context>/test/ mirroring the source structure:
test/
├── application/
│ └── services/
│ └── CoinBlockchainCreator.test.ts # mirrors application/services/
├── domain/
│ └── services/
│ └── PairsBuilder.test.ts # mirrors domain/services/
├── mothers/
│ └── CexAccountMother.ts
└── test-constants.ts