Граббинг данных NFT-коллекций (floor price, volume, holders)

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Граббинг данных NFT-коллекций (floor price, volume, holders)
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1221
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    855
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1056
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    828

Парсинг данных NFT-коллекций (floor price, volume, holders)

OpenSea API возвращает floor price с задержкой 5-15 минут и агрегирует данные по своей методологии. Для торговых ботов, аналитических платформ и minting dApps, которым нужен реальный floor — это неприемлемо. Единственный путь к точным данным: читать события прямо из блокчейна.

Источники данных: что откуда брать

On-chain события

Для ERC-721/ERC-1155 коллекций все продажи видны через события маркетплейсов. Каждый маркетплейс эмитирует собственное событие:

  • OpenSea Seaport: OrderFulfilled(bytes32 orderHash, address offerer, address zone, address recipient, SpentItem[] offer, ReceivedItem[] consideration) — контракт 0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC
  • Blur: TakerAsk / TakerBid на 0x000000000000Ad05Ccc4F10045630fb830B95127
  • LooksRare v2: TakerAsk / TakerBid
  • X2Y2: EvInventory

Floor price нельзя получить из событий напрямую — события показывают исполненные ордера, а не активные листинги. Для актуального floor нужно либо индексировать active listings через маркетплейс API, либо использовать агрегаторы.

Holders и transfers

Transfer(address indexed from, address indexed to, uint256 indexed tokenId) — стандарт ERC-721. Полный граф владения строится через replay всех Transfer событий от блока деплоя. Unique holders = уникальные адреса to за вычетом адресов, которые затем перевели токены на другой адрес.

Для ERC-1155: TransferSingle и TransferBatch. Здесь владение — это баланс, не бинарное состояние: balanceOf(address, tokenId).

Архитектура парсера

Стек

ethereum-node (Alchemy/Infura/Quicknode) 
  → ethers.js / viem (event filtering)
    → message queue (Redis Streams / BullMQ)
      → PostgreSQL / ClickHouse (storage)
        → REST/WebSocket API (выдача данных)

Для исторических данных — getLogs с фильтром по address и topics[0]. Блоки батчим по 2000 (ограничение большинства RPC провайдеров на eth_getLogs):

async function fetchTransferEvents(
  contract: string,
  fromBlock: number,
  toBlock: number,
  provider: JsonRpcProvider
) {
  const iface = new Interface(['event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)']);
  const filter = {
    address: contract,
    topics: [iface.getEventTopic('Transfer')],
    fromBlock,
    toBlock,
  };
  const logs = await provider.getLogs(filter);
  return logs.map(log => iface.parseLog(log));
}

Для real-time: WebSocket подписка через provider.on(filter, callback) или Alchemy eth_subscribe newLogs.

Вычисление floor price

Два подхода:

1. Маркетплейс API агрегация — запрашиваем floor у OpenSea, Blur, LooksRare, берём минимум. Проблема: rate limits и кэширование на стороне API.

2. Orderbook индексирование — подписываемся на события создания/отмены ордеров. Seaport: OrderValidated (создание), OrderCancelled, OrderFulfilled (исполнение). Строим локальный orderbook, вычисляем floor самостоятельно. Точнее, но сложнее в поддержке при обновлениях контрактов маркетплейса.

Для большинства задач достаточен первый подход с кэшем на 60 секунд.

Хранение и запросы

ClickHouse эффективнее PostgreSQL для time-series NFT данных — аналитические запросы на миллионах строк в 10-50x быстрее. Схема:

Колонка Тип Описание
block_number UInt64 Блок события
tx_hash FixedString(66) Хэш транзакции
contract FixedString(42) Адрес коллекции
token_id UInt256 ID токена
from FixedString(42) Продавец/отправитель
to FixedString(42) Покупатель/получатель
price_wei UInt256 Цена в wei
marketplace LowCardinality(String) Маркетплейс
timestamp DateTime Время блока

Партиционирование по месяцам (toYYYYMM(timestamp)), сортировочный ключ (contract, timestamp).

Решение типовых проблем

Rate limits: Alchemy Free — 330 CUPS, Growth — 660 CUPS. При историческом парсинге крупной коллекции (BAYC: 500k+ Transfer событий) без throttling получим 429. Реализуем exponential backoff + queue с concurrency control.

Реорганизации блокчейна: события из последних 12 блоков нужно помечать как «pending» и подтверждать только после finality. Для Ethereum PoS — 2 эпохи (64 блока) для экономического finality.

Wash trading: объём по адресам с циклическими переводами искажает статистику. Базовая эвристика: сделки где from и to — связанные адреса (получали ETH из одного источника) помечаются флагом.

Ориентиры по срокам

Парсер Transfer событий + holders tracker — 1 день. Добавление floor price через маркетплейс API + кэш — ещё полдня. Исторический бэкфилл для крупной коллекции + дашборд — 2-3 дня суммарно.