initvglidrbtgrthijl;
This commit is contained in:
@@ -146,6 +146,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ChainPortfolio": {
|
||||
"type": "object",
|
||||
"description": "Балансе одной сети в составе portfolio. Расширяет BalanceResponse.data полями totalUsd, stale, lastUpdated, error.",
|
||||
"properties": {
|
||||
"chain": { "$ref": "#/components/schemas/Chain" },
|
||||
"address": { "type": "string" },
|
||||
"totalUsd": { "type": "number", "nullable": true, "description": "Сумма usdValue по native + всем токенам chain'а. null если все цены недоступны." },
|
||||
"native": { "$ref": "#/components/schemas/FormattedAmount" },
|
||||
"tokens": {
|
||||
"type": "object",
|
||||
"additionalProperties": { "$ref": "#/components/schemas/FormattedAmount" }
|
||||
},
|
||||
"stale": { "type": "boolean", "description": "true = данные из KeyDB cache (RPC chain'а упал в этом запросе)" },
|
||||
"lastUpdated": { "type": "integer", "description": "Unix ms когда данные были обновлены fresh fetch'ем" },
|
||||
"error": { "type": "string", "nullable": true, "description": "Причина почему stale (только если stale=true)" }
|
||||
}
|
||||
},
|
||||
"PortfolioResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"success": { "type": "boolean", "example": true },
|
||||
"data": {
|
||||
"type": "object",
|
||||
"required": ["totalUsd", "hasErrors", "perChain"],
|
||||
"properties": {
|
||||
"totalUsd": { "type": "number", "description": "Grand sum USD по всем сетям (rounded к 8 знакам). 0 если все сети упали и нет cache." },
|
||||
"hasErrors": { "type": "boolean", "description": "true если хотя бы одна сеть в stale/error состоянии" },
|
||||
"perChain": {
|
||||
"type": "object",
|
||||
"description": "Per-chain breakdown. Ключ = chain code (ETH/BSC/BTC/TRX/SOL). Значение null если ни fresh, ни cache недоступны.",
|
||||
"properties": {
|
||||
"ETH": { "$ref": "#/components/schemas/ChainPortfolio", "nullable": true },
|
||||
"BSC": { "$ref": "#/components/schemas/ChainPortfolio", "nullable": true },
|
||||
"BTC": { "$ref": "#/components/schemas/ChainPortfolio", "nullable": true },
|
||||
"TRX": { "$ref": "#/components/schemas/ChainPortfolio", "nullable": true },
|
||||
"SOL": { "$ref": "#/components/schemas/ChainPortfolio", "nullable": true }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Transaction": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -289,6 +331,41 @@
|
||||
}
|
||||
},
|
||||
|
||||
"/wallets/portfolio": {
|
||||
"get": {
|
||||
"summary": "Aggregate balance по всем 5 сетям (общий баланс)",
|
||||
"description": "Возвращает баланс всех 5 сетей + grand total USD в одном запросе. Параллельно дёргает `getBalance(chain, address)` для ETH/BSC/BTC/TRX/SOL. Каждая успешная сеть кэшируется в KeyDB (TTL 1 час). Если какая-то сеть упала (RPC timeout / network error) — возвращает последний кэшированный balance этой сети с пометкой `stale:true` и описанием `error`. UI всегда показывает осмысленный portfolio, не падая на 0 при transient outage.\n\n**Поведение при ошибках:**\n- 1 сеть упала + есть cache → totalUsd считается с cached + `hasErrors:true`\n- 1 сеть упала + НЕТ cache → perChain[chain]=null, остальное fresh\n- все 5 упали + нет cache → totalUsd=0, hasErrors=true, perChain[*]=null\n- 502 возвращается только при unrecoverable controller exception",
|
||||
"tags": ["Wallet Ops"],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Aggregate portfolio",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/PortfolioResponse" },
|
||||
"example": {
|
||||
"success": true,
|
||||
"data": {
|
||||
"totalUsd": 12.34,
|
||||
"hasErrors": false,
|
||||
"perChain": {
|
||||
"ETH": { "chain":"ETH", "address":"0x9dB8Af1B...", "totalUsd":4.81, "native":{"raw":"1500000000000000000","formatted":"1.5","decimals":18,"usdPrice":3210.45,"usdValue":4.81}, "tokens":{}, "stale":false, "lastUpdated":1715600000000 },
|
||||
"BSC": { "chain":"BSC", "address":"0x9dB8Af1B...", "totalUsd":2.10, "native":{"...":"..."}, "tokens":{"USDT":{"...":"..."}}, "stale":false, "lastUpdated":1715600000000 },
|
||||
"BTC": { "chain":"BTC", "address":"bc1q...", "totalUsd":3.96, "native":{"...":"..."}, "stale":false, "lastUpdated":1715600000000 },
|
||||
"TRX": { "chain":"TRX", "address":"T...", "totalUsd":0.49, "native":{"...":"..."}, "tokens":{"USDT":{"...":"..."}}, "stale":true, "lastUpdated":1715500000000, "error":"TronGrid timeout" },
|
||||
"SOL": { "chain":"SOL", "address":"3PJC...", "totalUsd":0.98, "native":{"...":"..."}, "tokens":{}, "stale":false, "lastUpdated":1715600000000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": { "description": "Not authenticated" },
|
||||
"404": { "description": "No wallets created (вызови POST /wallets/create сначала)" },
|
||||
"502": { "description": "Portfolio fetch error" }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"/wallets/{chain}/balance": {
|
||||
"get": {
|
||||
"summary": "Balance for user wallet in chain (с USD-ценами)",
|
||||
|
||||
Reference in New Issue
Block a user