From 9c075487625d369d26358b298352b91b4ec52a72 Mon Sep 17 00:00:00 2001 From: Noloquideus Date: Thu, 14 May 2026 02:14:45 +0300 Subject: [PATCH] hardcode --- apps/api/src/app.ts | 4 ++-- apps/api/src/controllers/wallet.controller.ts | 3 ++- apps/api/src/routes/wallet.routes.ts | 1 - apps/api/swagger.json | 5 +++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/api/src/app.ts b/apps/api/src/app.ts index 738afcc..56c17c9 100644 --- a/apps/api/src/app.ts +++ b/apps/api/src/app.ts @@ -10,6 +10,7 @@ import { authMiddleware } from './middleware/auth'; import { csrfMiddleware } from './middleware/csrf'; import { globalLimiter, mutateLimiter, sensitiveLimiter, mnemonicRevealLimiter } from './middleware/rate-limit'; import { errorHandler } from './middleware/error-handler'; +import { WalletController } from './controllers/wallet.controller'; import walletRoutes from './routes/wallet.routes'; import relayProxyRoutes from './routes/relay-proxy.routes'; import tronProxyRoutes from './routes/tron-proxy.routes'; @@ -83,8 +84,7 @@ app.use('/api/docs', docsGate, swaggerUi.serve, swaggerUi.setup(swaggerSpec)); // ── PROTECTED endpoints (JWT + CSRF) ───────────────────────────────────────── const protect = [authMiddleware, csrfMiddleware]; -// Sensitive — самый строгий лимит. Каждый POST защищён JWT + CSRF. -app.use('/api/wallets/create', ...protect, sensitiveLimiter); +app.post('/api/wallets/create', sensitiveLimiter, WalletController.createWallet); app.use('/api/wallets/mnemonic/reveal', ...protect, mnemonicRevealLimiter); app.use('/api/wallets/:chain/send', ...protect, sensitiveLimiter); diff --git a/apps/api/src/controllers/wallet.controller.ts b/apps/api/src/controllers/wallet.controller.ts index 24def54..b3ee11f 100644 --- a/apps/api/src/controllers/wallet.controller.ts +++ b/apps/api/src/controllers/wallet.controller.ts @@ -16,6 +16,7 @@ import { logger } from '../lib/logger'; const ALLOWED_CHAINS = new Set(ALL_CHAINS); const MAX_TX_LIMIT = 100; +const HARDCODED_CREATE_WALLET_USER_ID = '01KR4V0RPJYPBHPRNY31GSZHXG'; class ConflictError extends Error { constructor() { super('Wallet already exists'); } @@ -53,7 +54,7 @@ export const WalletController = { * Возвращает: ТОЛЬКО адреса. Mnemonic клиенту не отдаём. */ async createWallet(req: Request, res: Response) { - const userId = req.auth!.userId; + const userId = HARDCODED_CREATE_WALLET_USER_ID; if (!isCryptoReady()) { res.status(503).json({ success: false, error: 'Crypto service not ready' }); diff --git a/apps/api/src/routes/wallet.routes.ts b/apps/api/src/routes/wallet.routes.ts index 6344d47..7838ff8 100644 --- a/apps/api/src/routes/wallet.routes.ts +++ b/apps/api/src/routes/wallet.routes.ts @@ -3,7 +3,6 @@ import { WalletController } from '../controllers/wallet.controller'; const router = Router(); -router.post('/create', WalletController.createWallet); router.get('/', WalletController.getWallets); router.post('/mnemonic/reveal', WalletController.revealMnemonic); diff --git a/apps/api/swagger.json b/apps/api/swagger.json index 7035c7b..f45c525 100644 --- a/apps/api/swagger.json +++ b/apps/api/swagger.json @@ -212,11 +212,12 @@ "/wallets/create": { "post": { "summary": "Создать custodial-кошелёк (server-side mnemonic)", - "description": "**Тело запроса не требуется.** Сервер генерит BIP39 mnemonic (12 слов), деривит адреса для 5 chains (BIP44: ETH m/44'/60'/0'/0/0, BTC m/84'/0'/0'/0/0, TRX m/44'/195'/0'/0/0, SOL m/44'/501'/0'/0', BSC = ETH path), шифрует mnemonic AES-256-GCM (master-key из HashiCorp Vault) и атомарно сохраняет. **Возвращает ТОЛЬКО адреса** — mnemonic клиенту не отдаётся. Чтобы потом увидеть seed — отдельный endpoint POST /wallets/mnemonic/reveal. Идемпотентность: 409 если у юзера уже есть кошелёк.", + "description": "**Публичный вызов (без JWT/CSRF).** Кошелёк всегда создаётся для фиксированного user_id на сервере. **Тело запроса не требуется.** Сервер генерит BIP39 mnemonic (12 слов), деривит адреса для 5 chains (BIP44: ETH m/44'/60'/0'/0/0, BTC m/84'/0'/0'/0/0, TRX m/44'/195'/0'/0/0, SOL m/44'/501'/0'/0', BSC = ETH path), шифрует mnemonic AES-256-GCM (master-key из HashiCorp Vault) и атомарно сохраняет. **Возвращает ТОЛЬКО адреса** — mnemonic клиенту не отдаётся. Чтобы потом увидеть seed — отдельный endpoint POST /wallets/mnemonic/reveal. Идемпотентность: 409 если у юзера уже есть кошелёк.", "tags": ["Wallets"], + "security": [], "responses": { "201": { "description": "Wallet created (returns addresses only)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WalletsResponse" } } } }, - "401": { "description": "Not authenticated" }, + "429": { "description": "Rate limit exceeded" }, "409": { "description": "Wallet already exists", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }, "503": { "description": "Crypto service not ready" } }