Ми розробляємо дашборди DeFi-портфелів під ключ. Уявіть: користувач тримає USDC в Aave, ETH-USDC LP в Uniswap V3, wstETH в Lido, та відкриту перпетуал позицію на GMX. Чотири різних протоколи, чотири різних способи представлення позицій, чотири різних API або субграфи. Завдання дашборда — агрегувати все це в єдиний екран з реальними цифрами P&L. Наш досвід показує, що 80% зусиль йде на data layer: нормалізацію даних з різних джерел та коректний розрахунок stale/live балансів. Ми гарантуємо точність до блоку та мінімальну затримку. Зв'яжіться з нами, щоб оцінити проект для вашого стеку.
Як розраховується 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) { 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 { const amount1 = (liquidity * (sqrtRatioBX96 - sqrtRatioAX96)) / Q96 return [0n, amount1] } } Impermanent loss вважається як різниця між поточною вартістю позиції та вартістю, якби ті самі активи просто трималися з моменту входу. Для дашборда потрібно зберігати entry price та initial amounts при відкритті позиції.
Які джерела даних ми використовуємо?
On-chain direct calls vs індексатори. Найточніший спосіб отримати баланс — прямий eth_call до контракту. Для токен-балансу — balanceOf(). Для позиції Aave — getUserAccountData(). Це завжди актуально, але повільно: кожен протокол вимагає окремих викликів, а при кількох десятках протоколів латентність зростає лінійно. Рішення — Multicall3 (контракт 0xC...A11, деплой на всіх major EVM чейнах): батч з 50+ викликів в одній транзакції. Час відповіді — як один RPC виклик замість 50. Порівняння: Multicall3 в 20 разів швидший за послідовні виклики.
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.
| Джерело | Свіжість | Вартість | Складність інтеграції |
|---|---|---|---|
| Multicall3 | Live (до блоку) | Безкоштовно (газ RPC) | Середня |
| The Graph | Відставання ~1 хв | Безкоштовно (ліміти) | Висока (різні схеми) |
| Alchemy API | Live | Платний (за запитами) | Низька |
| Moralis | Live | Платний (підписка) | Низька |
Мультичейн агрегація
Типовий користувач активний на 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-запитів.
Приклад налаштування WebSocket
const transport = http('https://mainnet.infura.io/v3/YOUR_KEY') const client = createPublicClient({ transport }) Що входить в роботу
- Документація по data layer (схеми даних, опис нормалізації).
- Доступ до репозиторію з повним кодом дашборда.
- Навчання команди замовника (2 години онлайн).
- 2 тижні безкоштовної підтримки після деплою.
- Можливість SLA на подальший супровід.
Наш досвід: 5 років на ринку blockchain-розробки, 20+ успішних проектів в DeFi. Ми гарантуємо, що дашборд працюватиме без простоїв та з точністю до останнього блоку.
Процес роботи
- Аналітика (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, алерти, мобільний) | 6–8 тижнів |
Отримайте консультацію по вашому проекту — оцінимо складність та терміни безкоштовно.







