Skip to content

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 exports

App 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.ts

Import Organization

Order imports as:

  1. External packages (bun:test, third-party)
  2. Internal @sws/ packages
  3. 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