swaggerready
This commit is contained in:
@@ -17,7 +17,8 @@
|
||||
{ "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)" }
|
||||
{ "name": "Relay", "description": "Cross-chain bridges (Relay Protocol)" },
|
||||
{ "name": "Prices", "description": "USD-цены (CoinGecko + KeyDB cache 5 мин)" }
|
||||
],
|
||||
"components": {
|
||||
"securitySchemes": {
|
||||
@@ -85,10 +86,45 @@
|
||||
},
|
||||
"FormattedAmount": {
|
||||
"type": "object",
|
||||
"description": "Сумма с метаданными формата + USD-цена. Поля `usdPrice`/`usdValue` всегда присутствуют, но могут быть `null` если symbol не в registry или upstream price oracle (CoinGecko) недоступен.",
|
||||
"required": ["raw", "formatted", "decimals", "usdPrice", "usdValue"],
|
||||
"properties": {
|
||||
"raw": { "type": "string", "description": "Smallest units (wei/sat/sun/lamports), string-encoded BigInt" },
|
||||
"formatted": { "type": "string", "description": "Human-readable decimal", "example": "0.003" },
|
||||
"decimals": { "type": "integer", "description": "Decimals of the chain/token", "example": 18 }
|
||||
"raw": { "type": "string", "description": "Smallest units (wei/sat/sun/lamports), string-encoded BigInt", "example": "1500000000000000000" },
|
||||
"formatted": { "type": "string", "description": "Human-readable decimal", "example": "1.5" },
|
||||
"decimals": { "type": "integer", "description": "Decimals of the chain/token", "example": 18 },
|
||||
"usdPrice": {
|
||||
"type": "number",
|
||||
"nullable": true,
|
||||
"description": "Цена 1 целой единицы в USD по данным CoinGecko (cache 5 мин, KeyDB). `null` если symbol не в registry или upstream недоступен.",
|
||||
"example": 3210.45
|
||||
},
|
||||
"usdValue": {
|
||||
"type": "number",
|
||||
"nullable": true,
|
||||
"description": "Совокупная стоимость holding'а в USD = `Number(formatted) × usdPrice`, округлено до 8 знаков. `null` если `usdPrice === null` или результат не finite.",
|
||||
"example": 4815.675
|
||||
}
|
||||
}
|
||||
},
|
||||
"PricesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"success": { "type": "boolean", "example": true },
|
||||
"data": {
|
||||
"type": "object",
|
||||
"description": "Map symbol → { usd: price | null }. `null` если symbol whitelist'ed но upstream не вернул котировку.",
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"usd": { "type": "number", "nullable": true, "example": 67432.12 }
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"BTC": { "usd": 67432.12 },
|
||||
"ETH": { "usd": 3210.45 },
|
||||
"USDT": { "usd": 1.0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"BalanceResponse": {
|
||||
@@ -255,11 +291,42 @@
|
||||
|
||||
"/wallets/{chain}/balance": {
|
||||
"get": {
|
||||
"summary": "Balance for user wallet in chain",
|
||||
"summary": "Balance for user wallet in chain (с USD-ценами)",
|
||||
"description": "Возвращает количество и USD-стоимость для native монеты + всех известных токенов сети. Каждый `FormattedAmount` содержит `raw` (smallest units), `formatted` (human-readable), `decimals`, `usdPrice` (цена 1 единицы), `usdValue` (стоимость holding'а). Цены — CoinGecko с 5-минутным KeyDB-кэшем. Если упал price oracle — `usdPrice`/`usdValue` = `null`, но количества всё равно возвращаются.\n\n**Пример curl:**\n```\ncurl -H \"Authorization: Bearer $JWT\" https://api.example.com/api/wallets/ETH/balance\n```",
|
||||
"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" } } } },
|
||||
"200": {
|
||||
"description": "Balance + USD prices",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/BalanceResponse" },
|
||||
"example": {
|
||||
"success": true,
|
||||
"data": {
|
||||
"chain": "ETH",
|
||||
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f4F45A",
|
||||
"native": {
|
||||
"raw": "1500000000000000000",
|
||||
"formatted": "1.5",
|
||||
"decimals": 18,
|
||||
"usdPrice": 3210.45,
|
||||
"usdValue": 4815.675
|
||||
},
|
||||
"tokens": {
|
||||
"USDT": { "raw": "1000000", "formatted": "1", "decimals": 6, "usdPrice": 1.0, "usdValue": 1.0 },
|
||||
"USDC": { "raw": "0", "formatted": "0", "decimals": 6, "usdPrice": 0.9999, "usdValue": 0 },
|
||||
"DAI": { "raw": "0", "formatted": "0", "decimals": 18, "usdPrice": 0.9998, "usdValue": 0 },
|
||||
"WBTC": { "raw": "0", "formatted": "0", "decimals": 8, "usdPrice": 67432.12, "usdValue": 0 },
|
||||
"LINK": { "raw": "0", "formatted": "0", "decimals": 18, "usdPrice": 14.32, "usdValue": 0 },
|
||||
"UNI": { "raw": "0", "formatted": "0", "decimals": 18, "usdPrice": 8.41, "usdValue": 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": { "description": "Not authenticated" },
|
||||
"404": { "description": "Wallet for this chain not found" },
|
||||
"502": { "description": "Upstream RPC error" }
|
||||
}
|
||||
@@ -337,8 +404,8 @@
|
||||
},
|
||||
"/wallets/{chain}/swap": {
|
||||
"post": {
|
||||
"summary": "Custodial chained swap (BSC PancakeSwap / TRX SunSwap / SOL Jupiter)",
|
||||
"description": "Полностью custodial swap в один HTTP-вызов. Никакого client-side signing. BSC: approve+swap chained (PancakeSwap V2, поддерживает BNB/USDT/USDC/DOGE/WBNB/BUSD). TRX: SunSwap TRX↔USDT. SOL: Jupiter aggregator (любые mints из registry). Slippage protection — server computes amountOutMin от actual quote с default 50 bps tolerance. Optional Idempotency-Key header для anti double-spend.",
|
||||
"summary": "Custodial chained swap (BSC PancakeSwap / TRX SunSwap+FeeSwapRouter / SOL Jupiter)",
|
||||
"description": "Полностью custodial swap в один HTTP-вызов. Никакого client-side signing.\n\n**BSC** — PancakeSwap V2 approve+swap chained. Пары: BNB/USDT/USDC/DOGE/WBNB/BUSD.\n\n**TRX** — SunSwap V2 через FeeSwapRouter (0.7% fee). Только пары TRX↔USDT. Server делает approve(infinite, FeeSwapRouter) (если allowance < amount) + wait inclusion + swap. 4-layer MITM defense (txID/expiration/type/selector verify) — компрометированный TronGrid не сможет подсунуть `transfer` вместо `swap`.\n\n**SOL** — Jupiter aggregator. Любые mints из registry (USDT/USDC/PUMP/JUP/WIF/POPCAT/TRUMP/PYTH/JTO/W/BONK/ORCA/PENGU/RAY).\n\n**Slippage protection** — server computes `amountOutMin = quote × (10000-slippageBps)/10000` от actual quote (default 50 bps = 0.5%). Клиент НЕ задаёт amountOutMin напрямую (защита от MEV-sandwich). Optional `Idempotency-Key` header для anti double-spend.",
|
||||
"tags": ["Wallet Ops"],
|
||||
"parameters": [{ "name": "chain", "in": "path", "required": true, "schema": { "type": "string", "enum": ["BSC", "TRX", "SOL"] } }],
|
||||
"requestBody": {
|
||||
@@ -352,11 +419,11 @@
|
||||
"title": "BSC/TRX swap (symbols)",
|
||||
"required": ["from", "to", "amount"],
|
||||
"properties": {
|
||||
"from": { "type": "string", "description": "BSC: BNB|USDT|USDC|DOGE|WBNB|BUSD; TRX: TRX|USDT" },
|
||||
"from": { "type": "string", "description": "BSC: BNB|USDT|USDC|DOGE|WBNB|BUSD; TRX: TRX|USDT (только эта пара поддерживается на TRON)" },
|
||||
"to": { "type": "string" },
|
||||
"amount": { "type": "string", "description": "Smallest units (wei для 18-dec, sun для TRX 6-dec)" },
|
||||
"slippageBps": { "type": "integer", "minimum": 1, "maximum": 1000, "description": "0.01%-10%. Default 50 (0.5%)." },
|
||||
"feeTier": { "type": "string", "enum": ["slow", "normal", "fast"] }
|
||||
"amount": { "type": "string", "description": "Smallest units (wei для 18-dec EVM, sun для TRX 6-dec). Max для TRX = 9_007_199_254_740_991 (~9B TRX)." },
|
||||
"slippageBps": { "type": "integer", "minimum": 1, "maximum": 1000, "description": "0.01%-10%. Default 50 (0.5%). Server вычислит amountOutMin сам — клиент НЕ задаёт его напрямую." },
|
||||
"feeTier": { "type": "string", "enum": ["slow", "normal", "fast"], "description": "Только BSC (ETH/BSC). На TRX игнорится." }
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -619,6 +686,60 @@
|
||||
"502": { "description": "Relay upstream error" }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"/prices": {
|
||||
"get": {
|
||||
"summary": "USD-цены для списка символов",
|
||||
"description": "Возвращает котировки USD для указанных символов (max 50). Символы должны быть из реестра поддерживаемых токенов (см. tag описание сетей в /wallets/{chain}/balance). Источник — CoinGecko free API, кэшируется в KeyDB 5 минут.\n\n**Resolution:**\n- Native символ совпадающий с chain code (BTC/ETH/BSC/TRX/SOL) → используется native CoinGecko id.\n- Иначе: ищется в реестре сети из `chain` query param.\n- Если `chain` не задан → fallback порядок ETH → BSC → SOL → TRX → BTC. Первый matched chain wins.\n\n**Безопасность:** symbols whitelisted, никакого user-input в URL CoinGecko (защита от SSRF). Max 50 символов на запрос. Auth обязательна (JWT Bearer или cookie).\n\n**Пример curl:**\n```\ncurl -H \"Authorization: Bearer $JWT\" \"https://api.example.com/api/prices?symbols=BTC,ETH,USDT,SOL,BONK\"\n```",
|
||||
"tags": ["Prices"],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "symbols",
|
||||
"in": "query",
|
||||
"required": true,
|
||||
"description": "Comma-separated список символов (макс 50). Каждый — `[A-Z0-9]{1,16}`. Только символы из registry: BTC, ETH, BSC, TRX, SOL (native) + USDT, USDC, DAI, WBTC, LINK, UNI, DOGE, WBNB, BUSD, PUMP, JUP, WIF, POPCAT, TRUMP, PYTH, JTO, W, BONK, ORCA, PENGU, RAY.",
|
||||
"schema": { "type": "string", "example": "BTC,ETH,USDT" }
|
||||
},
|
||||
{
|
||||
"name": "chain",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"description": "Опционально: для disambiguation если symbol присутствует в нескольких сетях (USDT/USDC). Если не задан — fallback порядок: ETH → BSC → SOL → TRX → BTC.",
|
||||
"schema": { "$ref": "#/components/schemas/Chain" }
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "USD prices",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/PricesResponse" },
|
||||
"example": {
|
||||
"success": true,
|
||||
"data": {
|
||||
"BTC": { "usd": 67432.12 },
|
||||
"ETH": { "usd": 3210.45 },
|
||||
"USDT": { "usd": 1.0 },
|
||||
"SOL": { "usd": 142.88 },
|
||||
"BONK": { "usd": 0.00002145 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Validation error: пустой/слишком большой/невалидный список, неизвестный chain или unknown symbol",
|
||||
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
|
||||
},
|
||||
"401": { "description": "Not authenticated", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
|
||||
"429": { "description": "Rate limit exceeded" },
|
||||
"502": {
|
||||
"description": "Upstream price oracle error (CoinGecko)",
|
||||
"content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user