Розробка системи резолвінгу ENS-доменів під навантаженням

Розробка системи резолвінгу ENS-доменів під навантаженням ## Проблема: стандартний резолвінг не витримує навантаження Уявіть DApp з 100 000 щоденних користувачів. Кожен виклик `provider.resolveName()` йде в RPC-ноду. Без кеша ви швидко впретеся в ліміти запитів — типовий Infura/Alchemy tier до

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

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    998
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1267
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    713
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1003

Розробка системи резолвінгу ENS-доменів під навантаженням

Проблема: стандартний резолвінг не витримує навантаження

Уявіть DApp з 100 000 щоденних користувачів. Кожен виклик provider.resolveName() йде в RPC-ноду. Без кеша ви швидко впретеся в ліміти запитів — типовий Infura/Alchemy tier допускає 100 000 запитів на добу. При піку в 10 000 одночасних користувачів резолвінг може займати до 500 мс на ім'я, а при batch-обробці списку з 1000 адрес послідовний виклик бібліотеки ethers займає 2–5 хвилин. Це неприйнятно для real-time додатків. Крім того, потрібно підтримувати multi-chain адреси (ETH, BSC, Polygon), обробляти wildcard-домени (ENSIP-10) та off-chain дані через CCIP-Read. Стандартні бібліотеки не оптимізовані під такі сценарії.

Ми розробляємо кастомні ENS-резолвери, які вирішують ці проблеми. На нашому рахунку 30+ проектів, де ми впроваджували надійну інтеграцію ENS під високими навантаженнями. Кешування скорочує час резолвінгу до 1–5 мс, а batch-обробка 1000 адрес укладається у 2 секунди. Зниження витрат на RPC-провайдера досягає 40%, що при масштабуванні дає економію до $500 на місяць. При навантаженні 200 000 запитів на добу економія сягає $6000 на рік. Завдяки 30+ успішним впровадженням, ми гарантуємо надійність та продуктивність вашого резолвінгу.

Процес резолвінгу ENS

Повний ланцюжок ENS lookup включає кроки: нормалізація імені за UTS-46, обчислення namehash (keccak256), запит до ENS Registry для отримання адреси резолвера, перевірка підтримки wildcard (ENSIP-10), запит до резолвера з coinType, і якщо резолвер повертає OffchainLookup (EIP-3668), виконання CCIP-Read. Кожен крок може бути вузьким місцем. Наш кастомний сервіс бере на себе весь ланцюжок, кешуючи проміжні результати.

Деталі про обробку помилокВ нашому сервісі ми обробляємо помилки за допомогою try-catch, повертаючи null для неіснуючих імен. При помилках CCIP-Read ми повторюємо запит з більшим таймаутом.

Кастомний резолвер сервіс з кешуванням

Для production-систем ми реалізуємо власний резолвінг-сервіс з розподіленим кешем (Redis + in-memory cache). Приклад на TypeScript з viem (версія 2.x) та node-cache:

import { createPublicClient, http, normalize } from "viem"; import { mainnet } from "viem/chains"; import NodeCache from "node-cache"; class ENSResolutionService { private client = createPublicClient({ chain: mainnet, transport: http(RPC_URL) }); private cache = new NodeCache({ stdTTL: 300 }); // 5 хвилин TTL async resolveName(name: string): Promise<string | null> { const normalized = normalize(name); const cacheKey = `addr:${normalized}`; const cached = this.cache.get<string>(cacheKey); if (cached !== undefined) return cached; try { const address = await this.client.getEnsAddress({ name: normalized }); this.cache.set(cacheKey, address ?? null); return address; } catch (e) { return null; } } async lookupAddress(address: `0x${string}`): Promise<string | null> { const cacheKey = `name:${address.toLowerCase()}`; const cached = this.cache.get<string>(cacheKey); if (cached !== undefined) return cached; const name = await this.client.getEnsName({ address }); this.cache.set(cacheKey, name ?? null); return name; } async batchLookup(addresses: `0x${string}`[]): Promise<Map<string, string | null>> { const results = new Map<string, string | null>(); const uncached: `0x${string}`[] = []; for (const addr of addresses) { const cached = this.cache.get<string>(`name:${addr.toLowerCase()}`); if (cached !== undefined) { results.set(addr, cached); } else { uncached.push(addr); } } await Promise.allSettled( uncached.map(async (addr) => { const name = await this.lookupAddress(addr); results.set(addr, name); }) ); return results; } } 

Цей код легко інтегрується в бекенд. Кеш з TTL 5 хвилин знижує навантаження на RPC в десятки разів. Для розподіленого середовища використовуємо Redis з таким же TTL. Для складних сценаріїв ми також розробляємо Solidity-резолвери, які можуть бути розгорнуті як власні контракти.

Як реалізувати multi-chain адреси?

ENS підтримує зберігання адрес для різних блокчейнів через coinType (SLIP-44). Наприклад, ETH = 60, BTC = 0, SOL = 501, MATIC = 966. Наш сервіс дозволяє отримувати адреси для будь-якого coinType однією функцією:

const COIN_TYPES = { ETH: 60, BTC: 0, SOL: 501, MATIC: 966, ARB: 9001 }; async function getMultiChainAddresses(name: string) { const resolver = await provider.getResolver(name); if (!resolver) return null; const eth = await resolver.getAddress(COIN_TYPES.ETH); const btc = await resolver.getAddress(COIN_TYPES.BTC); const sol = await resolver.getAddress(COIN_TYPES.SOL); return { eth, btc, sol }; } 

Ви можете додати будь-які coinType, включаючи MATIC, ARB, OP. Ми надаємо єдиний інтерфейс для роботи з кількома мережами.

Як обробляти CCIP-Read в кастомному резолвері?

CCIP-Read (EIP-3668) дозволяє резолверу повертати посилання на off-chain дані замість адреси. Клієнт повинен виконати HTTP-запит за цим посиланням та верифікувати підпис. У нашому сервісі ми автоматично обробляємо OffchainLookup: після отримання помилки ми витягуємо URL та дані, завантажуємо їх, перевіряємо підпис (якщо потрібно) та кешуємо результат. Детальніше в EIP-3668. Для wildcard-резолверів (ENSIP-10) ми реалізували повну підтримку — дивіться ENSIP-10.

Прискорення резолвінгу з кастомним сервісом

Візьмемо реальний кейс: клієнтський додаток резолвить імена 10 000 користувачів при завантаженні. З ethers послідовно — ~50 секунд. З кастомним сервісом з кешем та паралельними запитами — 2 секунди. Різниця в 25 разів. Досягається це за рахунок кешування часто запитуваних імен, паралельної обробки batch-запитів через Promise.allSettled та відсутності повторних RPC-викликів для вже відомих адрес. При пікових навантаженнях кожна мілісекунда на рахунку, тому ми оптимізуємо сервіс до максимальної продуктивності. Кешування знижує час резолвінгу до 1–5 мс, що в 100 разів швидше за стандартний підхід.

Переваги кастомного сервісу перед бібліотеками

Готові бібліотеки (ethers, viem) працюють в браузері, але на бекенді без кеша швидко вичерпують ліміти RPC. Кастомний сервіс дає повний контроль над кешуванням, підтримку wildcard, паралельний batch-резолвінг та єдину точку інтеграції для кількох мереж. Нижче порівняння:

Критерій ethers/viem Кастомний сервіс
Кешування Немає (або ручне) Вбудоване з TTL
Batch-резолвінг Послідовний Паралельний
Wildcard (ENSIP-10) Часткова Повна підтримка
Multi-chain Тільки ETH Будь-які coinType
Таймаути За замовчуванням Гнучке налаштування

Кастомний сервіс обробляє batch-запити в 5–10 разів швидше, ніж ethers/viem.

Етапи розробки кастомного резолвінгу

Розробка кастомного резолвінгу проходить такі кроки:

  1. Аналіз архітектури (0.5 дня)
  2. Проектування сервісу (1 день)
  3. Реалізація ядра (2-3 дні)
  4. Інтеграція в бекенд (1-2 дні)
  5. Моніторинг та оптимізація (1 день)
Етап Тривалість Результат
Аналіз архітектури 0.5 дня Технічне завдання з метриками
Проектування сервісу 1 день Документація API, схема кешування
Реалізація ядра 2–3 дні Працюючий резолвер з тестами
Інтеграція в бекенд 1–2 дні Готовий endpoint
Моніторинг та оптимізація 1 день Dashboard, алерти, навантажувальне тестування

Що входить в роботу

  • Документація API резолвера — REST або JSON-RPC специфікація з прикладами запитів
  • Розгортання сервісу на вашій інфраструктурі (Docker, Kubernetes, Lambda) з моніторингом та алертингом
  • Інтеграція з існуючим бекендом — адаптація під fastify, express, serverless
  • Навчання команди — воркшоп з використання резолвера та troubleshooting
  • Технічна підтримка — місяць після впровадження

Строки та вартість

Розробка кастомного резолвінг-сервісу з кешем та multi-chain підтримкою займає від 3 до 5 робочих днів. Інтеграція в існуючий бекенд — ще 1–2 дні. Вартість такого сервісу зазвичай становить від $1500 до $5000 залежно від складності. Отримайте консультацію щодо вашого проекту — ми оцінимо архітектуру та запропонуємо оптимізацію. Зв'яжіться з нами для аналізу поточної системи ENS-інтеграції: виявимо вузькі місця та прискоримо резолвінг.