Разработка кастомных дашбордов аналитики на Dune

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

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

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

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1286
  • 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

Разработка кастомных аналитик дашбордов на Dune

Dune Analytics — это SQL-движок поверх decoded blockchain данных. Если вы умеете писать SQL и понимаете структуру Ethereum транзакций, вы можете построить любую аналитику по любому протоколу без собственной инфраструктуры. Сложность не в инструменте — она в понимании того, как данные блокчейна устроены в реляционной модели, и в написании запросов, которые отдают результат за разумное время, а не по 5 минут.

Структура данных в Dune

Dune работает с двумя уровнями данных:

Raw tables — сырые данные цепи:

  • ethereum.transactions — все транзакции (from, to, value, gas, data...)
  • ethereum.logs — все события (address, topics[0..3], data)
  • ethereum.traces — internal transactions (call traces)
  • ethereum.blocks — блоки

Decoded tables — decoded события конкретных протоколов. Если ABI контракта загружен в Dune, все его события доступны как нормализованные таблицы:

  • uniswap_v3_ethereum.Pair_evt_Swap — все свапы Uniswap V3
  • aave_v3_ethereum.Pool_evt_LiquidationCall — ликвидации Aave
  • erc20_ethereum.evt_Transfer — все ERC-20 переводы

Всегда предпочитайте decoded таблицы — они быстрее и не требуют ручного парсинга data и topics.

Написание эффективных запросов

Основные антипаттерны

Полный скан без партиционирования по дате — самая частая причина таймаутов:

-- ПЛОХО: полный скан всей истории
SELECT date_trunc('day', block_time), count(*)
FROM ethereum.transactions
WHERE "to" = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48  -- USDC контракт

-- ХОРОШО: всегда фильтруем по block_time
SELECT date_trunc('day', block_time), count(*)
FROM ethereum.transactions
WHERE "to" = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
  AND block_time >= date_trunc('day', now()) - interval '90 days'

Избыточные JOIN на большие таблицыerc20_ethereum.evt_Transfer содержит миллиарды строк. JOIN с ней без жёсткой фильтрации убивает запрос:

-- ПЛОХО: JOIN на всю историю переводов
SELECT t.from, SUM(t.value)
FROM erc20_ethereum.evt_Transfer t
JOIN my_users u ON t."from" = u.address
WHERE t.contract_address = 0xdAC17F958D2ee523a2206206994597C13D831ec7  -- USDT
GROUP BY 1

-- ХОРОШО: добавляем временной диапазон
SELECT t.from, SUM(t.value / 1e6) as usdt_sent
FROM erc20_ethereum.evt_Transfer t
JOIN my_users u ON t."from" = u.address
WHERE t.contract_address = 0xdAC17F958D2ee523a2206206994597C13D831ec7
  AND t.evt_block_time >= now() - interval '30 days'
GROUP BY 1
ORDER BY 2 DESC

Паттерны для DeFi аналитики

TVL (Total Value Locked) — требует отслеживания балансов токенов на контракте:

-- TVL протокола через события Deposit/Withdraw
WITH deposits AS (
    SELECT
        date_trunc('day', evt_block_time) AS day,
        token,
        SUM(amount / POWER(10, decimals)) AS amount
    FROM protocol_ethereum.Pool_evt_Deposit
    JOIN tokens.erc20 ON token = contract_address AND blockchain = 'ethereum'
    WHERE evt_block_time >= now() - interval '180 days'
    GROUP BY 1, 2
),
withdrawals AS (
    SELECT
        date_trunc('day', evt_block_time) AS day,
        token,
        -SUM(amount / POWER(10, decimals)) AS amount
    FROM protocol_ethereum.Pool_evt_Withdraw
    JOIN tokens.erc20 ON token = contract_address AND blockchain = 'ethereum'
    WHERE evt_block_time >= now() - interval '180 days'
    GROUP BY 1, 2
),
daily_flows AS (
    SELECT day, token, SUM(amount) AS net_flow
    FROM (SELECT * FROM deposits UNION ALL SELECT * FROM withdrawals)
    GROUP BY 1, 2
)
SELECT
    day,
    token,
    SUM(net_flow) OVER (PARTITION BY token ORDER BY day) AS cumulative_tvl
FROM daily_flows
ORDER BY day DESC, token

DAU (Daily Active Users) — считаем уникальные адреса:

SELECT
    date_trunc('day', block_time) AS day,
    COUNT(DISTINCT "from") AS dau,
    COUNT(*) AS transactions,
    COUNT(*) / COUNT(DISTINCT "from") AS avg_txs_per_user
FROM ethereum.transactions
WHERE "to" IN (
    SELECT DISTINCT contract_address FROM protocol_ethereum.Pool_evt_Swap
)
  AND block_time >= now() - interval '90 days'
  AND success = TRUE
GROUP BY 1
ORDER BY 1

Revenue / Fee аналитика:

-- Комиссии протокола через PoolFeeUpdated и Swap события
SELECT
    date_trunc('week', s.evt_block_time) AS week,
    SUM(
        CASE
            WHEN s.token0 = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48  -- USDC
            THEN ABS(s.amount0) / 1e6 * p.fee / 1e6
            ELSE ABS(s.amount1) / 1e6 * p.fee / 1e6
        END
    ) AS protocol_fees_usd
FROM uniswap_v3_ethereum.Pair_evt_Swap s
JOIN uniswap_v3_ethereum.Factory_evt_PoolCreated p
    ON s.contract_address = p.pool
WHERE s.evt_block_time >= now() - interval '52 weeks'
GROUP BY 1
ORDER BY 1

Работа с Spellbook (Dune V2)

Spellbook — это dbt проект с переиспользуемыми моделями данных. Вместо того чтобы каждый раз писать логику декодирования цен или нормализации токенов, используем готовые таблицы:

-- prices.usd — нормализованные USD цены для всех токенов по часам
-- dex.trades — все DEX свапы в едином формате (Uniswap, Curve, Balancer...)
-- tokens.erc20 — символы, decimals всех ERC-20 токенов

SELECT
    date_trunc('day', dt.block_date) AS day,
    SUM(dt.amount_usd) AS volume_usd,
    COUNT(DISTINCT dt.taker) AS unique_traders,
    COUNT(*) AS trade_count
FROM dex.trades dt
WHERE dt.project = 'uniswap'
  AND dt.version = '3'
  AND dt.blockchain = 'ethereum'
  AND dt.block_date >= now() - interval '30 days'
GROUP BY 1
ORDER BY 1 DESC

Таблица dex.trades уже содержит нормализованные суммы в USD — не нужно самостоятельно джойниться с price feeds.

Дашборд: архитектура и UX

Хороший Dune дашборд — это продукт, а не набор графиков. Практические принципы:

Иерархия метрик: top-level KPI (TVL, Volume, Users) → drill-down (по сетям, токенам, временным периодам) → детали (топ адресов, конкретные транзакции).

Параметры для интерактивности: Dune поддерживает параметры в запросах ({{token_address}}, {{days_back}}). Это делает один дашборд применимым для разных активов:

SELECT *
FROM dex.trades
WHERE token_bought_address = {{token_address}}
  AND block_date >= now() - interval '{{days_back}} days'

Кешируемые запросы: тяжёлые исторические запросы (> 30 дней истории) лучше разделить на:

  1. Исторический snapshot (пересчитывается раз в день через scheduled query)
  2. Delta за последние 24h (быстрый, обновляется часто)

Объединяем через UNION в финальном запросе — пользователь видит актуальные данные без ожидания 5-минутного пересчёта.

Что входит в работу

  • Анализ протокола и определение ключевых метрик для дашборда
  • Написание SQL запросов с оптимизацией по времени выполнения
  • Визуализация: выбор типов графиков, настройка осей, цветов, легенд
  • Параметризация запросов для интерактивности
  • Настройка расписания обновления для тяжёлых запросов
  • Документация логики расчётов для команды