Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# 3. npm run setup
#
# That's it! The setup script will:
# - Generate all 19 wallet seeds/keys
# - Generate all required wallet seeds/keys
# - Start the API in the background
# - Wait for database tables and seed data
# - Register an admin user
Expand All @@ -31,13 +31,13 @@ REQUEST_LIMIT_CHECK=false

# Database (matches docker-compose.yml)
SQL_HOST=localhost
SQL_PORT=1433
SQL_PORT=5432
SQL_USERNAME=sa
SQL_PASSWORD=LocalDev2026@SQL
SQL_DB=dfx
SQL_SYNCHRONIZE=true
SQL_MIGRATE=false
SQL_ENCRYPT=false
SQL_SSL=false

# Auth
JWT_SECRET=local-dev-secret-change-in-production
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/api-migration-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ on:
- develop
paths:
- 'migration/**'
# The seed script and its data are actively maintained, not immutable schema migrations.
- '!migration/seed/**'

permissions:
contents: read
Expand All @@ -24,7 +26,8 @@ jobs:
- name: Block changes to existing migrations
run: |
git fetch origin ${{ github.base_ref }} --depth=100
CHANGED=$(git diff --name-status origin/${{ github.base_ref }}...HEAD -- migration/ \
# Protect immutable schema migrations only; the seed script/data may change freely.
CHANGED=$(git diff --name-status origin/${{ github.base_ref }}...HEAD -- migration/ ':(exclude)migration/seed/' \
| awk '$1 ~ /^[MDR]/ {print}')
if [ -n "$CHANGED" ]; then
echo "::error::Existing migrations must not be modified, renamed or deleted."
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,10 @@ npm run start:local # Restart API manually

The `npm run setup` command is an all-in-one script that:

1. **Generates All Wallet Seeds**: Creates 19 secure random seeds/keys and saves them to `.env`:
- 10 mnemonic seeds (ADMIN, EVM_DEPOSIT, EVM_CUSTODY, SOLANA, TRON, CARDANO, PAYMENT_*)
- 9 EVM private keys (shared across all EVM chains)
1. **Generates All Wallet Seeds**: Creates secure random seeds/keys and saves them to `.env`:
- Mnemonic seeds (ADMIN, EVM_DEPOSIT, EVM_CUSTODY, SOLANA, TRON, CARDANO, ICP, SPARK, BOLTZ, PAYMENT_*)
- EVM private keys (shared across all EVM chains)
- Service-specific keys (Ark hex, KuCoin Pay PKCS#8, payment-webhook PEM)
2. **Starts API**: Launches the API in the background (logs to `api.log`, PID saved to `.api.pid`)
3. **Registers Admin User**: Uses the API auth endpoint to create and authenticate the admin
4. **Sets Admin Role**: Grants admin privileges in the database
Expand Down Expand Up @@ -256,10 +257,9 @@ Seed data is stored in `migration/seed/` and can be customized as needed.

```bash
docker compose up -d # Start database
docker compose logs db-init # Check if database was created
docker compose down # Stop database
docker compose down -v # Stop and delete data
docker logs dfx-mssql # View database logs
docker logs dfx-postgres # View database logs
```

### Environment Configuration
Expand All @@ -269,7 +269,7 @@ The `.env.local.example` template contains minimal config for local development:
- `ENVIRONMENT=loc` - Enables mock mode for external services
- `DISABLED_PROCESSES=*` - Disables all background jobs
- `SQL_SYNCHRONIZE=true` - Auto-creates database tables from entities
- `SQL_ENCRYPT=false` - Trusts Docker's self-signed SSL certificate
- `SQL_SSL=false` - Disables SSL for the local Postgres connection

**Note:** The template does not contain wallet seeds. All seeds are generated securely by `npm run setup` and written to your local `.env` file.

Expand All @@ -283,7 +283,7 @@ When `ENVIRONMENT=loc`, external services are automatically mocked to simplify l
- **Mail service**: Mail sending is logged but not actually sent

**❌ What's NOT mocked:**
- **Database**: Requires running MSSQL instance (via Docker)
- **Database**: Requires running PostgreSQL instance (via Docker)
- **Blockchain services**: Still initialize with credentials from `.env`
- **Localhost calls**: Requests to localhost/127.0.0.1 are never mocked

Expand Down
34 changes: 9 additions & 25 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,37 +1,21 @@
services:
db:
image: mcr.microsoft.com/mssql/server:2022-latest
container_name: dfx-mssql
image: postgres:16
container_name: dfx-postgres
environment:
- ACCEPT_EULA=Y
- MSSQL_SA_PASSWORD=LocalDev2026@SQL
- MSSQL_PID=Developer
- POSTGRES_USER=sa
- POSTGRES_PASSWORD=LocalDev2026@SQL
- POSTGRES_DB=dfx
ports:
- "1433:1433"
- "5432:5432"
volumes:
- mssql_data:/var/opt/mssql
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "LocalDev2026@SQL" -C -Q "SELECT 1" || exit 1
test: ["CMD-SHELL", "pg_isready -U sa -d dfx"]
interval: 10s
timeout: 3s
retries: 10
start_period: 10s

db-init:
image: mcr.microsoft.com/mssql/server:2022-latest
depends_on:
db:
condition: service_healthy
entrypoint: ["/bin/bash", "-c"]
command:
- |
/opt/mssql-tools18/bin/sqlcmd -S db -U sa -P "LocalDev2026@SQL" -C -Q "
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = 'dfx')
BEGIN
CREATE DATABASE dfx
END
"
echo "Database 'dfx' ready"

volumes:
mssql_data:
postgres_data:
14 changes: 14 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ module.exports = tseslint.config(
rules: {
'no-return-await': 'off',
'no-console': ['warn'],
// The 'Config' singleton is undefined until ConfigService is constructed. Reading it in a
// field initializer of a Nest-instantiated class (@Injectable/@Controller) crashes app
// bootstrap when that provider is instantiated before ConfigService (provider ordering /
// circular dependency). Scoped to those decorators so request DTOs/entities (built at
// runtime, when Config is already set) are not affected. Use a getter or onModuleInit.
'no-restricted-syntax': [
'error',
{
selector:
"ClassDeclaration:has(Decorator[expression.callee.name=/^(Injectable|Controller)$/]) PropertyDefinition[value] MemberExpression[object.name='Config']",
message:
"Do not read the 'Config' singleton in a field initializer of an @Injectable/@Controller class: Config is undefined until ConfigService is constructed, which crashes app bootstrap if this provider is instantiated first. Use a getter or read Config in onModuleInit instead.",
},
],
'@typescript-eslint/return-await': ['warn', 'in-try-catch'],
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/explicit-function-return-type': 'off',
Expand Down
Loading
Loading