Files
cryptowallet/apps/api/swagger.json

398 lines
18 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"openapi": "3.0.0",
"info": {
"title": "CryptoWallet API",
"version": "5.0.0",
"description": "Multi-chain custodial wallet API (ETH/BSC/BTC/TRX/SOL). Сервер генерит mnemonic, шифрует AES-256-GCM (master-key из HashiCorp Vault), хранит её и сам подписывает транзакции. Auth via JWT (cookie/Bearer), issued by external auth-service (BITOK)."
},
"servers": [
{ "url": "/api", "description": "API root" }
],
"tags": [
{ "name": "System", "description": "Health & service info" },
{ "name": "Wallets", "description": "Custodial wallet lifecycle" },
{ "name": "Wallet Ops", "description": "Per-chain balance / transactions / send" },
{ "name": "BTC", "description": "Bitcoin RPC proxy (Blockstream)" },
{ "name": "TRON", "description": "TRON RPC proxy (TronGrid)" },
{ "name": "Solana", "description": "Solana swap proxy (Jupiter)" },
{ "name": "TRON Swap", "description": "TRON swap proxy (SunSwap + FeeSwapRouter)" },
{ "name": "BSC", "description": "BSC swap proxy (PancakeSwap V2)" },
{ "name": "Relay", "description": "Cross-chain bridges (Relay Protocol)" }
],
"components": {
"securitySchemes": {
"bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" },
"cookieAuth": { "type": "apiKey", "in": "cookie", "name": "access_token" }
},
"schemas": {
"Error": {
"type": "object",
"properties": {
"success": { "type": "boolean", "example": false },
"error": { "type": "string" }
}
},
"HealthResponse": {
"type": "object",
"properties": {
"success": { "type": "boolean", "example": true },
"data": { "type": "object", "properties": { "status": { "type": "string", "example": "ok" } } }
}
},
"Chain": {
"type": "string",
"enum": ["ETH", "BTC", "SOL", "TRX", "BSC"]
},
"Wallet": {
"type": "object",
"properties": {
"chain": { "$ref": "#/components/schemas/Chain" },
"address": { "type": "string" },
"derivationPath": { "type": "string", "description": "BIP32 path" }
}
},
"WalletsResponse": {
"type": "object",
"properties": {
"success": { "type": "boolean", "example": true },
"data": { "type": "array", "items": { "$ref": "#/components/schemas/Wallet" } }
}
},
"MnemonicResponse": {
"type": "object",
"properties": {
"success": { "type": "boolean", "example": true },
"data": {
"type": "object",
"properties": {
"mnemonic": { "type": "string", "description": "BIP39 mnemonic (12 words)" }
}
}
}
},
"TxBroadcastResponse": {
"type": "object",
"properties": {
"success": { "type": "boolean", "example": true },
"data": {
"type": "object",
"properties": {
"txid": { "type": "string", "description": "Идентификатор отправленной транзакции" },
"chain": { "$ref": "#/components/schemas/Chain" }
}
}
}
},
"BalanceResponse": {
"type": "object",
"properties": {
"success": { "type": "boolean", "example": true },
"data": {
"type": "object",
"properties": {
"chain": { "$ref": "#/components/schemas/Chain" },
"address": { "type": "string" },
"native": { "type": "string", "description": "Balance в smallest units (sat/wei/lamports/sun)" },
"tokens": {
"type": "object",
"additionalProperties": { "type": "string" },
"example": { "USDT": "12345678" }
}
}
}
}
},
"Transaction": {
"type": "object",
"properties": {
"txid": { "type": "string" },
"timestamp": { "type": "integer", "nullable": true, "description": "Unix seconds" },
"direction": { "type": "string", "enum": ["in", "out", "self"] },
"amount": { "type": "string", "nullable": true },
"token": { "type": "string", "nullable": true },
"from": { "type": "string", "nullable": true },
"to": { "type": "string", "nullable": true }
}
},
"TransactionsResponse": {
"type": "object",
"properties": {
"success": { "type": "boolean" },
"data": { "type": "array", "items": { "$ref": "#/components/schemas/Transaction" } }
}
},
"SendRequest": {
"type": "object",
"required": ["to", "amount"],
"properties": {
"to": { "type": "string", "description": "Recipient address" },
"amount": { "type": "string", "description": "Amount в smallest units" },
"token": { "type": "string", "nullable": true, "description": "USDT для TRC20/ERC20/BEP20. Без token = native." }
}
}
}
},
"security": [
{ "cookieAuth": [] },
{ "bearerAuth": [] }
],
"paths": {
"/health": {
"get": {
"summary": "Liveness check",
"tags": ["System"],
"security": [],
"responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthResponse" } } } } }
}
},
"/wallets": {
"get": {
"summary": "Get all wallets of authenticated user",
"tags": ["Wallets"],
"responses": {
"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": "Создать 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 если у юзера уже есть кошелёк.",
"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-confirmation. Rate-limit 5/час per-user. Каждый запрос пишется в audit-log.",
"tags": ["Wallets"],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["confirm"],
"properties": {
"confirm": { "type": "string", "enum": ["I_UNDERSTAND_SEED_IS_SECRET"] }
}
}
}
}
},
"responses": {
"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" }
}
}
},
"/wallets/{chain}/balance": {
"get": {
"summary": "Balance for user wallet in chain",
"tags": ["Wallet Ops"],
"parameters": [{ "name": "chain", "in": "path", "required": true, "schema": { "$ref": "#/components/schemas/Chain" } }],
"responses": {
"200": { "description": "Balance", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BalanceResponse" } } } },
"404": { "description": "Wallet for this chain not found" },
"502": { "description": "Upstream RPC error" }
}
}
},
"/wallets/{chain}/transactions": {
"get": {
"summary": "Transaction history for user wallet in chain",
"tags": ["Wallet Ops"],
"parameters": [
{ "name": "chain", "in": "path", "required": true, "schema": { "$ref": "#/components/schemas/Chain" } },
{ "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "minimum": 1, "maximum": 100 } }
],
"responses": {
"200": { "description": "List of transactions", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TransactionsResponse" } } } },
"404": { "description": "Wallet for this chain not found" }
}
}
},
"/wallets/{chain}/send": {
"post": {
"summary": "Custodial send: server signs + broadcasts",
"description": "Юзер на клиенте жмёт 'подтвердить' → клиент шлёт {to, amount, token?}. Сервер расшифровывает мнемонику, деривит chain privkey, подписывает, broadcast'ит. Возвращает txid. Защита: TRX MITM check, EVM gas cap 500 gwei, SOL confirmTransaction, BTC timeout + safety multiplier.",
"tags": ["Wallet Ops"],
"parameters": [{ "name": "chain", "in": "path", "required": true, "schema": { "$ref": "#/components/schemas/Chain" } }],
"requestBody": {
"required": true,
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/SendRequest" } } }
},
"responses": {
"200": { "description": "Broadcast successful", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TxBroadcastResponse" } } } },
"400": { "description": "Invalid input" },
"404": { "description": "Wallet/mnemonic not found" },
"502": { "description": "Broadcast failed (insufficient balance / RPC error / unsupported)" },
"503": { "description": "Crypto service not ready" }
}
}
},
"/btc/utxos/{address}": {
"get": {
"summary": "Confirmed UTXOs for Bitcoin address",
"tags": ["BTC"],
"parameters": [{ "name": "address", "in": "path", "required": true, "schema": { "type": "string" } }],
"responses": { "200": { "description": "UTXOs" }, "401": { "description": "Not authenticated" } }
}
},
"/btc/fee-estimates": {
"get": {
"summary": "Bitcoin fee estimates (sat/vB)",
"tags": ["BTC"],
"responses": { "200": { "description": "fast/normal/slow" }, "401": { "description": "Not authenticated" } }
}
},
"/btc/broadcast": {
"post": {
"summary": "Broadcast raw signed Bitcoin tx",
"tags": ["BTC"],
"requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["hex"], "properties": { "hex": { "type": "string" } } } } } },
"responses": { "200": { "description": "txid" }, "400": { "description": "Invalid hex" } }
}
},
"/tron/account/{address}": {
"get": {
"summary": "TRON account info + USDT (TRC20) balance",
"tags": ["TRON"],
"parameters": [{ "name": "address", "in": "path", "required": true, "schema": { "type": "string" } }],
"responses": { "200": { "description": "Account data" } }
}
},
"/tron/createtransaction": {
"post": {
"summary": "Build unsigned TRX transfer",
"tags": ["TRON"],
"requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["owner_address", "to_address", "amount"], "properties": { "owner_address": { "type": "string" }, "to_address": { "type": "string" }, "amount": { "type": "integer" } } } } } },
"responses": { "200": { "description": "Unsigned tx" } }
}
},
"/tron/triggersmartcontract": {
"post": {
"summary": "Build unsigned TRC20 contract call",
"tags": ["TRON"],
"requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object" } } } },
"responses": { "200": { "description": "Unsigned tx" } }
}
},
"/tron/broadcasttransaction": {
"post": {
"summary": "Broadcast signed TRON tx",
"tags": ["TRON"],
"requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object" } } } },
"responses": { "200": { "description": "Result" } }
}
},
"/sol/swap/quote": {
"get": {
"summary": "Jupiter swap quote (Solana)",
"tags": ["Solana"],
"parameters": [
{ "name": "inputMint", "in": "query", "required": true, "schema": { "type": "string" } },
{ "name": "outputMint", "in": "query", "required": true, "schema": { "type": "string" } },
{ "name": "amount", "in": "query", "required": true, "schema": { "type": "string" } },
{ "name": "slippageBps", "in": "query", "required": true, "schema": { "type": "integer" } }
],
"responses": { "200": { "description": "Quote" } }
}
},
"/sol/swap/build": {
"post": {
"summary": "Jupiter swap build",
"tags": ["Solana"],
"requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["quoteResponse", "userPublicKey"], "properties": { "quoteResponse": { "type": "object" }, "userPublicKey": { "type": "string" } } } } } },
"responses": { "200": { "description": "Swap tx" } }
}
},
"/tron/swap/quote": {
"get": {
"summary": "TRON swap quote (TRX <-> USDT)",
"tags": ["TRON Swap"],
"parameters": [
{ "name": "from", "in": "query", "required": true, "schema": { "type": "string", "enum": ["TRX", "USDT"] } },
{ "name": "to", "in": "query", "required": true, "schema": { "type": "string", "enum": ["TRX", "USDT"] } },
{ "name": "amount", "in": "query", "required": true, "schema": { "type": "string" } }
],
"responses": { "200": { "description": "Quote" } }
}
},
"/tron/swap/build": {
"post": {
"summary": "Build TRON swap transactions",
"tags": ["TRON Swap"],
"requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["from", "to", "amount", "amountOutMin", "userAddress"], "properties": { "from": { "type": "string" }, "to": { "type": "string" }, "amount": { "type": "string" }, "amountOutMin": { "type": "string" }, "userAddress": { "type": "string" } } } } } },
"responses": { "200": { "description": "Unsigned txs" } }
}
},
"/tron/swap/broadcast": {
"post": {
"summary": "Broadcast signed TRON swap",
"tags": ["TRON Swap"],
"requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["signedTransaction"], "properties": { "signedTransaction": { "type": "object" } } } } } },
"responses": { "200": { "description": "Result" } }
}
},
"/bsc/swap/quote": {
"get": {
"summary": "BSC swap quote (PancakeSwap V2)",
"tags": ["BSC"],
"parameters": [
{ "name": "from", "in": "query", "required": true, "schema": { "type": "string", "enum": ["BNB", "USDT", "DOGE"] } },
{ "name": "to", "in": "query", "required": true, "schema": { "type": "string", "enum": ["BNB", "USDT", "DOGE"] } },
{ "name": "amount", "in": "query", "required": true, "schema": { "type": "string" } }
],
"responses": { "200": { "description": "Quote" } }
}
},
"/bsc/swap/build": {
"post": {
"summary": "Build BSC swap transactions",
"tags": ["BSC"],
"requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["from", "to", "amount", "amountOutMin", "userAddress"], "properties": { "from": { "type": "string" }, "to": { "type": "string" }, "amount": { "type": "string" }, "amountOutMin": { "type": "string" }, "userAddress": { "type": "string" } } } } } },
"responses": { "200": { "description": "Unsigned txs" } }
}
},
"/relay/quote/v2": {
"get": { "summary": "Relay bridge quote", "tags": ["Relay"], "responses": { "200": { "description": "Quote" } } }
},
"/relay/intents/status/v3": {
"get": { "summary": "Relay intent status", "tags": ["Relay"], "responses": { "200": { "description": "Status" } } }
},
"/relay/execute/{action}": {
"post": {
"summary": "Relay execute",
"tags": ["Relay"],
"parameters": [{ "name": "action", "in": "path", "required": true, "schema": { "type": "string" } }],
"requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object" } } } },
"responses": { "200": { "description": "Result" } }
}
}
}
}