Розробка платформи аналітики NFT
Аналітика NFT складніша за DeFi-аналітику в одному конкретному аспекті: у кожного токена унікальна ціна. У DeFi пул Uniswap дає вам чіткий price feed. У NFT вам потрібно оцінити актив, у якого остання продаж була три місяці тому, а floor це floor всієї колекції, а не цього конкретного токена з рідким ознакою. Побудова коректної моделі оцінки — половина роботи.
Джерела даних та їхні обмеження
On-chain подіїї
Базові події, які потрібно індексувати:
-
Transfer(address from, address to, uint256 tokenId)— для ERC-721 -
TransferSingle/TransferBatch— для ERC-1155 -
OrderFulfilled(Seaport 1.5) — продажі через OpenSea -
TakerBid/TakerAsk— LooksRare v2 -
EvProfit— Blur
Проблема: у кожного маркетплейсу свої події зі своєю структурою. Seaport — найскладніший, там одна подія OrderFulfilled може кодувати bundle-продаж кількох NFT в одній транзакції з довільними ERC-20. Розбір цих даних потребує повного декодування масивів consideration та offer за ABI.
The Graph vs. self-hosted індексування
The Graph — очевидний вибір для початку. Існуючі субграфи: OpenSea (неофіційний), NFT sales aggregator субграфи на hosted service. Обмеження: hosted service закривається на користь децентралізованої мережі, де запити коштують GRT. Для високонавантаженої аналітики вартість запитів стає значущою.
Self-hosted через Ponder або Envio — Ponder (TypeScript-фреймворк для on-chain індексування) дозволяє писати обробники подій як звичайний TypeScript, зберігає дані в PostgreSQL. Envio — аналог з фокусом на швидкість (написаний на OCaml/Rust). Для платформи з користувацькими метриками self-hosted індексер переважніший: повний контроль над схемою даних.
Дуальний підхід: історичні дані з Dune Analytics або Reservoir API (агрегує продажі з усіх маркетплейсів), real-time через WebSocket підписку на події через Alchemy або QuickNode.
Моделі оцінки та метрики
Рейтинг рідкості
Стандартна формула — статистична рідкість:
rarity_score(token) = Σ (1 / trait_frequency) для всіх ознак
Це те, що робить rarity.tools. Проблема: не враховує кореляцію між ознаками. Токен з рідкою комбінацією двох звичайних ознак може бути рідше, ніж показує проста формула.
Покращений підхід — information content рідкість (IC score):
IC(trait) = -log2(P(trait))
rarity_score = Σ IC(trait_i)
Працює коректніше при нерівномірних розподілах.
Цінові метрики
| Метрика | Формула / джерело | Застосування |
|---|---|---|
| Floor price | min(активні листинги) | Базовий орієнтир |
| Trait floor | min(листинги з цією ознакою) | Оцінка конкретного токена |
| Wash trade adjusted volume | обсяг - підозрювані wash trades | Реальний обсяг |
| Holder distribution | унікальні кошельки / загальна пропозиція | Децентралізація |
| Listing depth | кількість листингів за цінові рівні | Liquidity профіль |
| Diamond hands ratio | % холдерів > 6 місяців | Утримання |
Детекція wash trade
Одна з ключових функцій аналітичної платформи. Патерни для детекції:
- Одні й ті ж адреси купують та продають один одному (граф транзакцій з циклами)
- Продажі через 1–3 блоки після покупки за ненринковою ціною
- Фінансування покупця з того ж джерела, що й продавець (Tornado Cash / mixer, або прямий переведення)
- Повторювані патерни: A→B→A→B з підвищенням ціни
Реалізується через граф-аналіз на адресах — Neo4j або вбудований граф у DuckDB достатньо ефективні. Для on-chain евристик використовують from/to у подіях Transfer + аналіз джерела фінансування через трасування транзакцій (trace_transaction у Geth/Erigon).
Технічний стек платформи
Інфраструктура індексування
Ethereum node (Erigon)
→ Ponder indexer (TypeScript)
→ PostgreSQL (TimescaleDB розширення для time-series)
→ Redis (кеш floor цін, популярні колекції)
→ ClickHouse (аналітичні агрегати, OLAP-запити)
TimescaleDB критична для метрик з часовими рядами: continuous aggregates дозволяють обчислювати hourly/daily OHLCV без перерахування при кожному запиті. ClickHouse виправдана при обсягах > 100M подій — аналітичні запити на ній у 10–100 разів швидше за PostgreSQL.
API шар
GraphQL через Hasura над PostgreSQL — для більшості запитів достатньо. Користувацькі resolver'и через Hasura Actions для складних обчислень (rarity score, wash trade score).
Для real-time даних — WebSocket через Hasura підписки або користувацький сервер на Node.js з pub/sub через Redis Streams.
Enrichment pipeline
NFT метаданні не завжди on-chain. Потрібен pipeline:
- З
tokenURI()контракту дістаємо URL (IPFS CID або HTTP) - Завантажуємо метаданні з IPFS gateway / HTTP
- Парсимо масив
attributes - Зберігаємо в PostgreSQL з обчисленим rarity score
- Оновлюємо при виявленні нових токенів (Transfer з нульової адреси)
Проблема: IPFS fetch ненадійний. Потрібні retry з exponential backoff, fallback на кілька gateway (Cloudflare, dweb.link, nftstorage.link), та timeout на рівні 5–10 секунд.
Frontend
Next.js 14 з App Router. Ключові сторінки:
- Collection overview: floor chart (Recharts/TradingView lightweight), volume bars, holder distribution pie
- Token detail: rarity rank, trait comparison, price history, similar sales
- Wallet analytics: portfolio valuation, P&L по колекціях, unrealized gains
- Market trends: trending за обсягом/floor зміною, new mints heatmap
Для чартів з великим обсягом даних — TradingView Lightweight Charts (WebGL-рендеринг) швидше за Recharts на 10k+ точках.
Що складно і займає багато часу
Історична синхронізація — індексування всіх NFT-транзакцій з 2017 року по сьогодні займає кілька тижнів навіть на швидкій ноді. Використовуйте снапшоти від Dune/Reservoir для бутстрапу, потім наздогонюйте live даними.
Multi-chain — підтримка Ethereum + Polygon + Base + Solana потребує 4 різних індексерів з різними ABI та структурами подій. Solana особливо болісна: там нема EVM, події це program logs в base64.
Точне ціноутворення — агрегація продажів правильно складна. Потрібно враховувати currency (ETH, WETH, USDC, BLUR токен), конвертувати в USD за історичним курсом на момент продажу, виключати wash trades. Кожен крок додає ймовірність помилки.
Реалістичний строк для MVP (одна мережа, базові метрики, простий UI): 6–8 тижнів. Повна мультичейн платформа з детекцією wash trade та аналітикою портфеля: 3–4 місяці.







