Розробка портфельного трекера криптовалют

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

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

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

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

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

Розробка портфельного трекера криптовалют

Простий портфельний трекер — це агрегатор даних. Складний — це система реального часу, яка сводить on-chain баланси з десятків мереж, позиції на централізованих біржах, NFT, DeFi позиції і рахує все це в єдиній базовій валюті. Різниця в складності приблизно 10x.

Джерела даних

On-chain баланси

EVM-мережі: нативний баланс через eth_getBalance, ERC-20 баланси складніше — один RPC вклик повертає баланс одного токену на одній адресі. При 50 токенах × 5 мережах = 250 викликів. Рішення — Multicall3 (задеплоєний на всіх EVM-мережах за адресою 0xcA11bde05977b3631167028862bE2a173976CA11):

import { createPublicClient, http, parseAbi } from "viem";
import { mainnet } from "viem/chains";

const client = createPublicClient({ chain: mainnet, transport: http() });

const MULTICALL3 = "0xcA11bde05977b3631167028862bE2a173976CA11";
const ERC20_ABI = parseAbi(["function balanceOf(address) view returns (uint256)"]);

async function getTokenBalances(
  walletAddress: `0x${string}`,
  tokenAddresses: `0x${string}`[]
) {
  const calls = tokenAddresses.map((tokenAddress) => ({
    address: tokenAddress,
    abi: ERC20_ABI,
    functionName: "balanceOf" as const,
    args: [walletAddress],
  }));

  return client.multicall({ contracts: calls });
}

Один RPC вклик замість 50 — критично для rate limits і latency.

Альтернатива: Alchemy/Moralis Token API. Один запит повертає все ERC-20 баланси для адреси з метаданими (символ, decimals, USD вартість). Платно, але економить час розробки.

DeFi позиції

Це найскладніша частина трекера. Liquidity позиція в Uniswap V3, collateral в Aave, стейкнуті токени в Curve — кожен протокол зберігає дані по-своєму.

Підхід 1: прямі вклики до контрактів протоколів. Для Uniswap V3:

// Позиція за NFT ID
const position = await nftPositionManager.positions(tokenId);
// { token0, token1, fee, tickLower, tickUpper, liquidity, ... }

// Перерахунок в токени через математику тиків (складно)
// Краще через Uniswap V3 SDK
import { Pool, Position } from "@uniswap/v3-sdk";

Підхід 2: The Graph subgraphs. Більшість DeFi протоколів мають офіційні subgraph — GraphQL API поверх on-chain даних:

query GetAavePositions($address: String!) {
  user(id: $address) {
    reserves {
      reserve {
        symbol
        underlyingAsset
      }
      currentATokenBalance
      currentVariableDebt
      currentStableDebt
    }
  }
}

Підхід 3: агрегатори позицій — DeBank API, Zapper API, Zerion API. Вже інтегровані зі сотнями протоколів. Мають смисл якщо не хочете поддерживати кожну DeFi інтеграцію самостійно.

CEX баланси

Біржові API отдають баланси миттєво, але вимагають read-only API ключ від користувача:

import ccxt from "ccxt";

async function getBinanceBalances(apiKey: string, secret: string) {
  const exchange = new ccxt.binance({ apiKey, secret, sandbox: false });
  const balance = await exchange.fetchBalance();
  return balance.total; // { BTC: 0.5, ETH: 2.3, USDT: 1000 }
}

CCXT підтримує 100+ бірж з єдиним інтерфейсом — незамінна бібліотека для трекерів.

Ціни токенів

Для пересчету в USD потрібні актуальні ціни. Джерела:

CoinGecko API — бесплатний план 30 запитів/хв, 10k/місяць. Для невеликих трекерів достатньо. Pro план знімає ліміти.

async function getPrices(coinIds: string[]): Promise<Record<string, number>> {
  const ids = coinIds.join(",");
  const data = await fetch(
    `https://api.coingecko.com/api/v3/simple/price?ids=${ids}&vs_currencies=usd`
  ).then(r => r.json());

  return Object.fromEntries(
    Object.entries(data).map(([id, val]: [string, any]) => [id, val.usd])
  );
}

On-chain ціни (Chainlink): для реального часу без залежності від CoinGecko. Chainlink Price Feeds доступні на всіх крупных EVM-мережах.

Архітектура refresh pipeline

Дані потрібно оновлювати, але не молотити RPC кожну секунду. Стратегія:

Тип даних Частота оновлення Причина
On-chain баланси Кожні 30–60 сек Новий блок
CEX баланси Кожні 30 сек API ліміти
DeFi позиції Кожні 2–5 хв Медленно міняються
Ціни токенів Кожні 10–30 сек Критично для P&L
Historical P&L Фоновий job, 1/год Важкі обчислення

Background jobs через Redis + BullMQ з окремими чергами для різних типів даних. Результати кешуємо в Redis, фронтенд читає з кеша.

WebSocket для real-time

Для користувачів, відкривши трекер в браузері — Server-Sent Events або WebSocket з push-оновленнями замість polling:

// Server-Sent Events endpoint
app.get("/api/portfolio/stream", (req, res) => {
  res.setHeader("Content-Type", "text/event-stream");
  res.setHeader("Cache-Control", "no-cache");

  const interval = setInterval(async () => {
    const portfolio = await getPortfolioSnapshot(req.user.id);
    res.write(`data: ${JSON.stringify(portfolio)}\n\n`);
  }, 10000);

  req.on("close", () => clearInterval(interval));
});

Зберігання історичних даних

Для P&L трекингу потрібні снапшоти портфеля в часі. TimescaleDB (розширення PostgreSQL) ідеально підходить:

CREATE TABLE portfolio_snapshots (
  user_id UUID,
  snapshot_at TIMESTAMPTZ NOT NULL,
  total_usd NUMERIC(20, 2),
  breakdown JSONB -- { "ETH": { "amount": 2.3, "usd": 7820 }, ... }
);

SELECT create_hypertable('portfolio_snapshots', 'snapshot_at');

Запит P&L за період:

SELECT
  time_bucket('1 day', snapshot_at) AS day,
  last(total_usd, snapshot_at) AS end_of_day_value
FROM portfolio_snapshots
WHERE user_id = $1 AND snapshot_at > NOW() - INTERVAL '30 days'
GROUP BY day ORDER BY day;

Час розробки MVP з підтримкою 5–6 EVM мереж, основними DeFi протоколами та 3–4 біржами: 1–2 тижні.