security: remove .env from tracking (contains secrets)
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "CryptoWallet API",
|
||||
"version": "2.1.0",
|
||||
"description": "Multi-chain crypto wallet API. Auth via JWT (cookie/Bearer), issued by external auth-service (BITOK). Non-custodial: server NEVER signs transactions, только строит unsigned tx + хранит зашифрованный vault."
|
||||
"version": "3.0.0",
|
||||
"description": "Multi-chain crypto wallet API. Auth via JWT (cookie/Bearer), issued by external auth-service (BITOK). CUSTODIAL: server генерит мнемонику, хранит её AES-GCM-зашифрованной (master-key из Vault) и сам подписывает транзакции."
|
||||
},
|
||||
"servers": [
|
||||
{ "url": "/api", "description": "API root" }
|
||||
@@ -56,22 +56,28 @@
|
||||
"derivationPath": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"WalletInput": {
|
||||
"MnemonicResponse": {
|
||||
"type": "object",
|
||||
"required": ["chain", "address", "derivationPath"],
|
||||
"properties": {
|
||||
"chain": { "$ref": "#/components/schemas/Chain" },
|
||||
"address": { "type": "string", "maxLength": 256 },
|
||||
"derivationPath": { "type": "string", "maxLength": 64 }
|
||||
"success": { "type": "boolean", "example": true },
|
||||
"data": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mnemonic": { "type": "string", "description": "BIP39 mnemonic (12 words)" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"CreateWalletsRequest": {
|
||||
"TxBroadcastResponse": {
|
||||
"type": "object",
|
||||
"required": ["wallets"],
|
||||
"properties": {
|
||||
"wallets": {
|
||||
"type": "array", "minItems": 1, "maxItems": 20,
|
||||
"items": { "$ref": "#/components/schemas/WalletInput" }
|
||||
"success": { "type": "boolean", "example": true },
|
||||
"data": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"txid": { "type": "string", "description": "Идентификатор отправленной транзакции" },
|
||||
"chain": { "$ref": "#/components/schemas/Chain" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -184,19 +190,49 @@
|
||||
"200": { "description": "List of wallets", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WalletsResponse" } } } },
|
||||
"401": { "description": "Not authenticated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
"/wallets/create": {
|
||||
"post": {
|
||||
"summary": "Upsert wallets for authenticated user",
|
||||
"description": "user_id берётся из JWT (sub). При первом обращении создаёт user-row автоматически. На конфликт (user_id, chain) — обновляет address + derivationPath.",
|
||||
"summary": "Создать custodial-кошелёк (mnemonic генерится на сервере)",
|
||||
"description": "Сервер генерит BIP39 mnemonic (12 слов), деривит адреса для 5 chains, шифрует mnemonic AES-GCM (master-key из Vault) и сохраняет. **Возвращает ТОЛЬКО адреса** — mnemonic клиенту НЕ отдаётся. Чтобы потом увидеть seed — отдельный endpoint GET /wallets/mnemonic. Идемпотентность: 409 если у юзера уже есть коша.",
|
||||
"tags": ["Wallets"],
|
||||
"responses": {
|
||||
"201": { "description": "Wallet created (returns addresses only)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WalletsResponse" } } } },
|
||||
"401": { "description": "Not authenticated" },
|
||||
"409": { "description": "Wallet already exists", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
|
||||
"503": { "description": "Crypto service not ready" }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"/wallets/mnemonic/reveal": {
|
||||
"post": {
|
||||
"summary": "Раскрыть mnemonic (settings-screen)",
|
||||
"description": "Расшифровывает и возвращает 12-словную BIP39 мнемонику юзера. POST + CSRF + рукопожатие в body — защита от случайного XHR / image-tag CSRF / стороннего origin. Rate-limit 5/час. Каждый запрос пишется в audit-log.",
|
||||
"tags": ["Wallets"],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateWalletsRequest" } } }
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["confirm"],
|
||||
"properties": {
|
||||
"confirm": { "type": "string", "enum": ["I_UNDERSTAND_SEED_IS_SECRET"] }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": { "description": "Created/updated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WalletsResponse" } } } },
|
||||
"400": { "description": "Invalid input", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
|
||||
"401": { "description": "Not authenticated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
|
||||
"200": { "description": "Mnemonic revealed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MnemonicResponse" } } } },
|
||||
"400": { "description": "Missing/invalid confirm token" },
|
||||
"401": { "description": "Not authenticated" },
|
||||
"404": { "description": "Wallet not created yet" },
|
||||
"429": { "description": "Rate limit (5/hour) exceeded" },
|
||||
"503": { "description": "Crypto service not ready" }
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -231,8 +267,8 @@
|
||||
|
||||
"/wallets/{chain}/send": {
|
||||
"post": {
|
||||
"summary": "Build unsigned send transaction (non-custodial)",
|
||||
"description": "Возвращает unsigned tx. Клиент подписывает приватным ключом и broadcast'ит через /api/{btc,tron}/broadcast или RPC своей цепи.",
|
||||
"summary": "Custodial send: server signs + broadcasts",
|
||||
"description": "Сервер расшифровывает мнемонику → деривит chain-privkey → подписывает → broadcast'ит через RPC. Возвращает txid.",
|
||||
"tags": ["Wallet Ops"],
|
||||
"parameters": [{ "name": "chain", "in": "path", "required": true, "schema": { "$ref": "#/components/schemas/Chain" } }],
|
||||
"requestBody": {
|
||||
@@ -240,10 +276,11 @@
|
||||
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/SendRequest" } } }
|
||||
},
|
||||
"responses": {
|
||||
"200": { "description": "Unsigned tx", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UnsignedTxResponse" } } } },
|
||||
"200": { "description": "Broadcast successful", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TxBroadcastResponse" } } } },
|
||||
"400": { "description": "Invalid input" },
|
||||
"404": { "description": "Wallet not found" },
|
||||
"502": { "description": "Upstream RPC error" }
|
||||
"404": { "description": "Wallet/mnemonic not found" },
|
||||
"502": { "description": "Broadcast failed (upstream RPC error / insufficient balance / unsupported token)" },
|
||||
"503": { "description": "Crypto service not ready" }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user