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

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка дашборду DeFi-портфелю
Середній
~1-2 тижні
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1288
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    902
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1122
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    859

Розробка дашборда 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(). Завжди актуально, але повільно: кожен протокол вимагає окремих вивізитів, при кількох десятках протоколів latency зростає лінійно.

Рішення — 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 для зберігання історичних portfolio snapshots (для побудови 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 дні). Список цільових протоколів та чейнів, пріоритизація за популярними audience use cases.

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

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

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

Орієнтири по строкам

MVP з 5–7 протоколами на 2–3 чейнах — 2–3 тижні. Повнофункціональний дашборд з історією, IL розрахунком, алертами та мобільним view — 6–8 тижнів.