Skip to content
Open
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
16 changes: 6 additions & 10 deletions server/.env.example
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
# Server
PORT=3001
NODE_ENV=development
CORS_ORIGIN=http://localhost:3000

# Database
DATABASE_URL=postgresql://user:password@localhost:5432/airflex

# Auth
JWT_SECRET=change_me_in_production

# Stellar
STELLAR_NETWORK=testnet
HORIZON_URL=https://horizon-testnet.stellar.org
SOROBAN_RPC_URL=https://soroban-testnet.stellar.org
ESCROW_CONTRACT_ADDRESS=CCBJ235OCBFZXBFSUUUT4PMG7RRCAXZXMUEB2L7CTTQ5NRSNO4P2SLNP

# Payments
PAYSTACK_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
PAYSTACK_SECRET_KEY=

# Messaging
TERMII_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# Auth
JWT_SECRET=change_me_to_a_long_random_secret

# Encryption — must be exactly 64 hex characters (32 bytes for AES-256-GCM)
# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000
TERMII_API_KEY=
10 changes: 1 addition & 9 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,17 @@
"start": "node dist/index.js"
},
"dependencies": {
"@stellar/stellar-sdk": "12.3.0",
"cors": "2.8.5",
"dotenv": "16.4.5",
"express": "4.19.2",
"helmet": "7.1.0",
"jsonwebtoken": "9.0.2",
"morgan": "1.10.0",
"pg": "8.12.0",
"uuid": "10.0.0",
"zod": "3.23.8"
"morgan": "1.10.0"
},
"devDependencies": {
"@types/cors": "2.8.17",
"@types/express": "4.17.21",
"@types/jsonwebtoken": "9.0.6",
"@types/morgan": "1.9.9",
"@types/node": "20.14.10",
"@types/pg": "8.11.6",
"@types/uuid": "10.0.0",
"ts-node-dev": "2.0.0",
"typescript": "5.5.3"
}
Expand Down
19 changes: 0 additions & 19 deletions server/src/db.ts

This file was deleted.

49 changes: 20 additions & 29 deletions server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,49 @@ import express, { Request, Response, NextFunction } from "express";
import cors from "cors";
import helmet from "helmet";
import morgan from "morgan";
import tradesRouter from "./routes/trades";
import authRouter from "./routes/auth";
import walletRouter from "./routes/wallet";

// ---------------------------------------------------------------------------
// Environment validation
// ---------------------------------------------------------------------------

const REQUIRED_ENV_VARS = [
"JWT_SECRET",
"DATABASE_URL",
"ESCROW_CONTRACT_ADDRESS",
"ENCRYPTION_KEY",
] as const;
const REQUIRED_ENV_VARS: string[] = [
// Add required variables here as the project grows, e.g.:
// "DATABASE_URL",
// "JWT_SECRET",
];

const missingVars = REQUIRED_ENV_VARS.filter((key) => !process.env[key]);

if (missingVars.length > 0) {
console.error(
`[startup] Missing required environment variables: ${missingVars.join(", ")}\n` +
`Copy server/.env.example to server/.env and fill in the values.`
`[startup] Missing required environment variables: ${missingVars.join(", ")}`
);
process.exit(1);
}

const PORT = parseInt(process.env.PORT ?? "3001", 10);
const NODE_ENV = process.env.NODE_ENV ?? "development";

// ---------------------------------------------------------------------------
// App setup
// ---------------------------------------------------------------------------

const app = express();
const PORT = parseInt(process.env["PORT"] ?? "3001", 10);

// ---------------------------------------------------------------------------
// Middleware
// ---------------------------------------------------------------------------

// Security headers
app.use(helmet());

// CORS — tighten origins in production via CORS_ORIGIN env var
// CORS — restrict origins in production via CORS_ORIGIN env var
app.use(
cors({
origin: process.env["CORS_ORIGIN"] ?? "*",
origin: process.env.CORS_ORIGIN ?? "*",
methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
allowedHeaders: ["Content-Type", "Authorization"],
})
);

// Request logging
app.use(morgan(process.env["NODE_ENV"] === "production" ? "combined" : "dev"));
// Request logging (compact in production, colourised in development)
app.use(morgan(NODE_ENV === "production" ? "combined" : "dev"));

// JSON body parsing
app.use(express.json());
Expand All @@ -61,19 +54,17 @@ app.use(express.json());
// Routes
// ---------------------------------------------------------------------------

/** Health-check — used by load balancers and uptime monitors */
app.get("/health", (_req: Request, res: Response) => {
res.status(200).json({ status: "ok", timestamp: new Date().toISOString() });
});

// Auth routes (OTP signup + verification)
app.use("/api/auth", authRouter);

// Trade marketplace routes
app.use("/api/trades", tradesRouter);
// ---------------------------------------------------------------------------
// 404 handler
// ---------------------------------------------------------------------------

// Wallet routes (Stellar public key + balance)
app.use("/api/wallet", walletRouter);
app.use((_req: Request, res: Response) => {
res.status(404).json({ error: "Not found" });
});

// ---------------------------------------------------------------------------
// Global error handler
Expand All @@ -91,7 +82,7 @@ app.use((err: Error, _req: Request, res: Response, _next: NextFunction) => {

app.listen(PORT, () => {
console.log(
`[server] AirFlex API running on port ${PORT} (${process.env["NODE_ENV"] ?? "development"})`
`[server] AirFlex API running on port ${PORT} (${NODE_ENV})`
);
});

Expand Down
40 changes: 0 additions & 40 deletions server/src/middleware/authenticate.ts

This file was deleted.

Loading