Разработка кастомных аналитик дашбордов на 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 дней истории) лучше разделить на:
- Исторический snapshot (пересчитывается раз в день через scheduled query)
- Delta за последние 24h (быстрый, обновляется часто)
Объединяем через UNION в финальном запросе — пользователь видит актуальные данные без ожидания 5-минутного пересчёта.
Что входит в работу
- Анализ протокола и определение ключевых метрик для дашборда
- Написание SQL запросов с оптимизацией по времени выполнения
- Визуализация: выбор типов графиков, настройка осей, цветов, легенд
- Параметризация запросов для интерактивности
- Настройка расписания обновления для тяжёлых запросов
- Документация логики расчётов для команды







