Реализация просмотра доходности DeFi-позиций в мобильном кошельке
DeFi-позиции — ликвидность в Uniswap v3, стейкинг в Lido, лендинг в Aave — у каждого протокола свои смарт-контракты, свои методы расчёта доходности и своя логика определения текущего баланса. Агрегировать это в единый экран «ваши позиции» без готового агрегатора сложно: нужно знать адреса контрактов каждого протокола, ABI-интерфейсы, формулы расчёта APY.
Источники данных для DeFi-позиций
DeFi Llama API — бесплатный агрегатор протоколов. Эндпоинт /tvl/{protocol} возвращает TVL, /yields — текущие APY по пулам. Хорошо подходит для отображения рыночных данных, но не даёт позиции конкретного адреса.
Zapper API / Zerion API — агрегаторы портфелей. Один запрос с адресом кошелька возвращает все DeFi-позиции по поддерживаемым протоколам с текущим балансом и P&L. Zerion поддерживает 400+ протоколов на 10+ сетях. Платные, но экономят месяц разработки.
Прямые вызовы смарт-контрактов через eth_call — для специфических протоколов или кастомных данных, которых нет в агрегаторах.
Читаем позицию напрямую из контракта: Aave v3
Для Aave v3 основной контракт — UiPoolDataProviderV3. Один eth_call возвращает все данные по всем резервам пользователя:
// Вызов через web3dart
final contract = DeployedContract(
ContractAbi.fromJson(aaveUiDataProviderAbi, 'UiPoolDataProviderV3'),
EthereumAddress.fromHex('0x91c0eA31b49B69Ea18607702c5d9aC360bf3dE7d'), // Ethereum mainnet
);
final result = await ethClient.call(
contract: contract,
function: contract.function('getUserReservesData'),
params: [
EthereumAddress.fromHex(poolAddressProvider), // Aave pool address provider
EthereumAddress.fromHex(userAddress),
],
);
// result[0] — List<UserReserveData>: токен, currentATokenBalance, currentVariableDebt, ...
Структура UserReserveData содержит currentATokenBalance (сколько депозитировано с учётом накопленных процентов) и currentVariableDebt (переменный долг). APY вычисляется из liquidityRate резерва через формулу APY = (1 + liquidityRate/10^27 / secondsPerYear)^secondsPerYear - 1.
Uniswap v3: позиции с диапазоном цен
Uniswap v3 — сложнее, потому что каждая позиция — NFT с индивидуальным диапазоном концентрированной ликвидности. NFT-позиции хранятся в NonfungiblePositionManager (адрес 0xC36442b4a4522E871399CD717aBDD847Ab11FE88 на mainnet).
Для получения позиций пользователя нужно:
-
balanceOf(userAddress)— количество NFT-позиций -
tokenOfOwnerByIndex(userAddress, index)— token IDs для каждой позиции -
positions(tokenId)— параметры позиции: token0/token1, fee tier, tickLower, tickUpper, liquidity
Расчёт текущего количества token0/token1 из liquidity и текущего sqrtPriceX96 — нетривиальная математика по формулам Uniswap v3 whitepaper. Правильнее использовать готовый @uniswap/v3-sdk на JS через WebView bridge или порт формул на Dart/Kotlin/Swift.
Проще: Uniswap Subgraph на The Graph возвращает position с уже посчитанным collectedFeesToken0, collectedFeesToken1, depositedToken0, depositedToken1.
Расчёт P&L по DeFi-позиции
P&L = (текущая стоимость позиции в USD) - (первоначально вложенная стоимость в USD)
Подводный камень: impermanent loss. Если вложили 1 ETH + 1000 USDC в пул на Uniswap v3, а ETH вырос — в пуле станет меньше ETH и больше USDC. Просто сравнить текущий баланс с начальным в USD недостаточно — нужно учитывать IL относительно hold-стратегии.
Для отображения P&L пользователю: показываем «fees earned» отдельно от «price change of underlying assets» — это понятнее, чем единое число P&L.
Обновление данных и кэширование
DeFi-данные меняются с каждым блоком (~12 секунд на Ethereum). Запрашивать их при каждом открытии экрана — достаточно, pull-to-refresh — стандартный UX-паттерн. Кэшировать с TTL 60 секунд: пользователи не ожидают real-time точности для лендинга.
Для стейкинга-позиций с медленным накоплением доходности (Lido stETH) — локально считаем накопленный yield по текущему APY и времени с последнего обновления, отображаем оптимистичную оценку без лишних запросов.
Что входит в работу
- Выбор и интеграция источников данных (агрегаторы или прямые контракты)
- Отображение позиций для приоритетных протоколов (Aave, Uniswap, Compound, Lido и др.)
- Расчёт текущего баланса и APY
- Отображение fees earned и P&L
- Кэширование с правильным TTL
- Поддержка нескольких сетей (Ethereum, Arbitrum, Optimism, Base)
Сроки
Интеграция через агрегатор (Zerion/Zapper) с отображением позиций: 1–2 недели. Прямая интеграция с 3–5 протоколами с кастомным расчётом P&L: 4–6 недель. Стоимость рассчитывается индивидуально.







