Разработка дашборда DeFi-портфеля

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка дашборда DeFi-портфеля
Средняя
~1-2 недели
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1258
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1170
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    873
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1092
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    563
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    830

Разработка дашборда DeFi-портфеля

Пользователь держит USDC в Aave, ETH-USDC LP в Uniswap V3, wstETH в Lido, и открытую перпетуал позицию на GMX. Четыре разных протокола, четыре разных способа представления позиций, четыре разных API или субграфа. Задача дашборда — агрегировать всё это в единый экран с реальными цифрами P&L.

Разработка такого инструмента — это не только фронтенд. 80% усилий уходит на data layer: нормализацию данных из разных источников и корректный расчёт stale/live балансов.

Источники данных и их специфика

On-chain direct calls vs индексаторы

Самый точный способ получить баланс — прямой eth_call к контракту. Для токен-баланса — balanceOf(). Для позиции Aave — getUserAccountData(). Это всегда актуально, но медленно: каждый протокол требует отдельных вызовов, а при нескольких десятках протоколов латентность растёт линейно.

Решение — Multicall3 (0xcA11bde05977b3631167028862bE2a173976CA11, деплой на всех major EVM чейнах): батч из 50+ вызовов в одной транзакции. Время ответа — как один RPC вызов вместо 50.

import { multicall } from 'viem'

const results = await multicall(client, {
  contracts: [
    { address: AAVE_POOL, abi: aavePoolAbi, functionName: 'getUserAccountData', args: [userAddress] },
    { address: USDC_TOKEN, abi: erc20Abi, functionName: 'balanceOf', args: [userAddress] },
    { address: UNISWAP_POSITION_MANAGER, abi: nftAbi, functionName: 'balanceOf', args: [userAddress] },
  ]
})

Для исторических данных (история транзакций, PnL по времени) прямые вызовы не работают — нужны индексаторы.

The Graph для исторических данных

Uniswap, Aave, Compound, Curve, Balancer — все имеют официальные subgraphs в The Graph Network. Subgraph предоставляет GraphQL API для запроса исторических событий: deposits, withdrawals, swaps, liquidations.

query UserPositions($user: String!) {
  aaveV3_deposits(where: { user: $user }, orderBy: timestamp, orderDirection: desc) {
    amount
    reserve { symbol, decimals, priceInUSD }
    timestamp
  }
  aaveV3_borrows(where: { user: $user }) {
    amount
    reserve { symbol }
    currentVariableBorrowRate
  }
}

Проблема: у разных версий протоколов разные subgraphs. Aave V2 на Ethereum, Aave V3 на Polygon, Aave V3 на Arbitrum — три разных субграфа с разными схемами. Нормализация — основная инженерная задача дашборда.

Alchemy и Moralis как API-over-RPC

Alchemy API предоставляет готовые методы: getTokenBalances() возвращает все ERC-20 балансы адреса без перебора контрактов. getAssetTransfers() — история трансферов. Это значительно упрощает начальную реализацию, но стоит денег при высокой нагрузке.

Moralis дополнительно агрегирует данные о NFT позициях и DeFi protocol positions через их DeFi API — платный, но экономит месяцы разработки кастомного data layer.

Для MVP оправдан Alchemy + The Graph для ключевых протоколов. Для production с десятками тысяч пользователей — собственный indexer.

Расчёт P&L и impermanent loss

Самая сложная часть — корректный расчёт unrealized P&L по LP позициям.

Для Uniswap V3 позиция — это NFT с определёнными tickLower, tickUpper, liquidity. Текущие amounts token0 и token1 зависят от текущего sqrtPriceX96 пула. Формула нетривиальна:

function getAmountsFromLiquidity(
  sqrtPriceX96: bigint,
  sqrtRatioAX96: bigint,
  sqrtRatioBX96: bigint,
  liquidity: bigint
): [bigint, bigint] {
  if (sqrtPriceX96 <= sqrtRatioAX96) {
    // Вся ликвидность в token0
    const amount0 = (liquidity * (sqrtRatioBX96 - sqrtRatioAX96) * Q96) 
                    / (sqrtRatioBX96 * sqrtRatioAX96)
    return [amount0, 0n]
  } else if (sqrtPriceX96 < sqrtRatioBX96) {
    const amount0 = (liquidity * (sqrtRatioBX96 - sqrtPriceX96) * Q96) 
                    / (sqrtRatioBX96 * sqrtPriceX96)
    const amount1 = (liquidity * (sqrtPriceX96 - sqrtRatioAX96)) / Q96
    return [amount0, amount1]
  } else {
    // Вся ликвидность в token1
    const amount1 = (liquidity * (sqrtRatioBX96 - sqrtRatioAX96)) / Q96
    return [0n, amount1]
  }
}

Impermanent loss считается как разница между текущей стоимостью позиции и стоимостью, если бы те же активы просто держались с момента входа. Для дашборда нужно хранить entry price и initial amounts при открытии позиции.

Мультичейн агрегация

Типичный пользователь активен на Ethereum mainnet, Arbitrum, Polygon, Base. Дашборд должен показывать суммарный портфель поперёк чейнов.

Схема: параллельные запросы к RPC каждого чейна через Promise.all(), нормализация балансов в USD через единый price oracle. Coingecko API или DefiLlama Price API для получения актуальных цен по token address + chain ID.

Проблема cross-chain identity: адрес пользователя одинаков на всех EVM чейнах (ECDSA), но смарт-контракт кошелёк (Safe, Argent) может иметь разные адреса на разных чейнах при несинхронизированном деплое. Нужно явно поддерживать multi-address mode.

Стек и производительность

Backend: Node.js + TypeScript с viem для RPC. Redis для кэша балансов (TTL 30 секунд для live данных, 5 минут для исторических). PostgreSQL для хранения исторических snapshot-ов портфеля (для построения equity curve).

Frontend: React + wagmi v2 для wallet connection, Recharts или TradingView Lightweight Charts для графиков, Tanstack Query для data fetching с автоматическим refetch каждые 30 секунд.

WebSocket для real-time обновлений: подписка на eth_subscribe("newHeads") для триггера обновления балансов при новом блоке — выглядит живо без лишних poll-запросов.

Процесс работы

Аналитика (1–2 дня). Список целевых протоколов и чейнов, приоритизация по popular use cases аудитории.

Data layer (5–7 дней). Multicall агрегатор, The Graph интеграции для ключевых протоколов, нормализация в единую схему позиции.

Backend API (3–5 дней). REST/GraphQL API для фронтенда, кэширование, история портфеля.

Frontend (5–7 дней). Wallet connection, суммарный balance view, детали по протоколам, графики.

Ориентиры по срокам

MVP с 5–7 протоколами на 2–3 чейнах — 2–3 недели. Полноценный дашборд с историей, IL расчётом, алертами и мобильным view — 6–8 недель.