Налаштування аналітики блокчейн-проекту (Dune Analytics)
Dune Analytics — це SQL-інтерфейс поверх декодованих блокчейн-даних. Замість того щоб розгортувати власний індексер та писати парсери подій, ви пишете SQL-запити до готових таблиць, де транзакції та события вже декодовані по ABI. Для більшості аналітичних задач це в рози швидше, ніж будувати власний стек.
Dune підтримує Ethereum, Arbitrum, Optimism, Base, Polygon, BSC, Solana та кілька десятків інших мереж в одному SQL-середовищі.
Структура даних у Dune
Таблиці організовані на кілька рівнів:
Raw дані — сирі блокчейн дані без декодування:
-
ethereum.blocks— блоки -
ethereum.transactions— транзакції -
ethereum.logs— сирі события (topics + data як байти) -
ethereum.traces— internal calls
Decoded дані — события та виклики декодовані по ABI:
-
uniswap_v3_ethereum.Factory_evt_PoolCreated— событие PoolCreated від Uniswap V3 Factory -
erc20_ethereum.evt_Transfer— усі ERC-20 Transfer события - Формат:
{protocol}_{network}.{contract}_{type}_{event/function}
Spells — аналітичні таблиці, підготовлені спільнотою:
-
dex.trades— усі DEX сделки по всіх мережах в єдиній схемі -
tokens.erc20— метадані токенів -
nft.trades— NFT сделки
Декодування вашого контракту
Щоб события вашого контракту з'явилися в decoded таблицях — завантажте ABI:
- Відкрити
dune.com/contracts/new - Вказати мережу та адресу контракту
- Вставити ABI (JSON)
- Дочекатися одобрення (зазвичай 1–3 робочих дні)
Після декодування з'явиться таблиця вида yourproject_ethereum.YourContract_evt_YourEvent.
Написання запитів: практичні паттерни
Базовий аналіз токена
-- Кількість унікальних власників ERC-20 токена
WITH transfers AS (
SELECT
"to" AS address,
value AS amount
FROM erc20_ethereum.evt_Transfer
WHERE contract_address = 0xYourTokenAddress
UNION ALL
SELECT
"from" AS address,
-value AS amount
FROM erc20_ethereum.evt_Transfer
WHERE contract_address = 0xYourTokenAddress
AND "from" != 0x0000000000000000000000000000000000000000
)
SELECT
COUNT(DISTINCT address) FILTER (WHERE balance > 0) AS holders
FROM (
SELECT address, SUM(amount) AS balance
FROM transfers
GROUP BY address
)
TVL (Total Value Locked) протоколу
-- TVL через декодовані Deposit/Withdraw события
SELECT
DATE_TRUNC('day', evt_block_time) AS day,
SUM(SUM(CAST(amount AS DOUBLE) / 1e18)) OVER (ORDER BY DATE_TRUNC('day', evt_block_time)) AS cumulative_tvl_eth
FROM yourproject_ethereum.Vault_evt_Deposit
GROUP BY 1
ORDER BY 1
Обсяг торгів через DEX
-- Використання Spell таблиці dex.trades
SELECT
DATE_TRUNC('week', block_time) AS week,
blockchain,
SUM(amount_usd) AS volume_usd,
COUNT(*) AS trades_count
FROM dex.trades
WHERE token_bought_address = 0xYourTokenAddress
OR token_sold_address = 0xYourTokenAddress
AND block_time >= NOW() - INTERVAL '90' day
GROUP BY 1, 2
ORDER BY 1 DESC
Cohort-аналіз користувачів
-- Перша транзакція користувача = дата вступлення в когорту
WITH first_tx AS (
SELECT
"from" AS user,
MIN(DATE_TRUNC('week', evt_block_time)) AS cohort_week
FROM yourproject_ethereum.YourContract_evt_SomeAction
GROUP BY 1
),
weekly_activity AS (
SELECT
"from" AS user,
DATE_TRUNC('week', evt_block_time) AS active_week
FROM yourproject_ethereum.YourContract_evt_SomeAction
GROUP BY 1, 2
)
SELECT
f.cohort_week,
DATE_DIFF('week', f.cohort_week, w.active_week) AS weeks_since_join,
COUNT(DISTINCT w.user) AS retained_users
FROM first_tx f
JOIN weekly_activity w ON f.user = w.user
GROUP BY 1, 2
ORDER BY 1, 2
Dune API: вбудовування даних в продукт
Для відображення аналітики у вашому додатку — використовуйте Dune API:
const DUNE_API_KEY = process.env.DUNE_API_KEY!
// Запуск запиту та отримання результату
async function getDuneQueryResult(queryId: number): Promise<DuneResult> {
// Запустити виконання
const execRes = await fetch(`https://api.dune.com/api/v1/query/${queryId}/execute`, {
method: 'POST',
headers: { 'X-Dune-API-Key': DUNE_API_KEY },
body: JSON.stringify({ performance: 'medium' }), // medium / large
})
const { execution_id } = await execRes.json()
// Ждати завершення
let status = 'QUERY_STATE_PENDING'
while (['QUERY_STATE_PENDING', 'QUERY_STATE_EXECUTING'].includes(status)) {
await new Promise(r => setTimeout(r, 2000))
const statusRes = await fetch(
`https://api.dune.com/api/v1/execution/${execution_id}/status`,
{ headers: { 'X-Dune-API-Key': DUNE_API_KEY } }
)
const statusData = await statusRes.json()
status = statusData.state
}
// Отримати результати
const resultRes = await fetch(
`https://api.dune.com/api/v1/execution/${execution_id}/results`,
{ headers: { 'X-Dune-API-Key': DUNE_API_KEY } }
)
return resultRes.json()
}
Для дашборду з оновленням раз на годину — кешуйте результати, не запускайте запит на кожен HTTP-запит клієнта.
Параметризовані запити
Dune підтримує параметри в запитах — зручно для універсальних дашбордів:
-- У запиті використовуємо {{parameter}}
SELECT *
FROM dex.trades
WHERE token_bought_address = {{token_address}}
AND block_time >= NOW() - INTERVAL '{{days}}' day
// При вызову через API передаємо параметри
const body = {
query_parameters: {
token_address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
days: 30,
},
performance: 'medium',
}
Альтернативи Dune для специфічних задач
| Задача | Інструмент |
|---|---|
| Real-time дані (< 1 хв затримка) | The Graph (subgraph) |
| SQL + швидше за Dune | Flipside Crypto, Allium |
| Власний індексер | Envio, Ponder, Goldsky |
| NFT аналітика | NFTGo, Reservoir |
| Cross-chain дані | Nansen, Messari |
Dune має затримку від кількох хвилин до години на безкоштовному плані. Для real-time метрик у production — використовуйте The Graph або власний індексер.
Типовий дашборд для DeFi протоколу
Набір метрик, які варто налаштувати з першого дня:
- Daily/Weekly Active Users (унікальні адреси)
- TVL в USD з розбиванням за токенами
- Обсяг транзакцій (count + USD value)
- Revenue (комісії протоколу)
- Retention cohorts
- Top users / whales
- Gas витрачено користувачами протоколу
Створення базового дашборду з 5–7 метриками, декодування контракту, налаштування Dune API для вбудовування в продукт: 1–2 дні.







