Разработка системы резолвинга ENS-доменов

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1Все 1306 услуг
Разработка системы резолвинга ENS-доменов
Простой
от 1 дня до 3 дней
Часто задаваемые вопросы

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

Этапы блокчейн-разработки

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1285
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    902
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1121
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    857

Разработка системы резолвинга ENS-доменов

ENS резолвинг — это не просто вызов provider.resolveName(). Для production систем нужно учесть кеширование, поддержку wildcard, CCIP-Read (off-chain resolvers), и корректную обработку multi-chain адресов. Особенно если резолвинг происходит не в браузере, а в backend сервисах или смарт-контрактах.

Полная цепочка резолвинга

Стандартный ENS lookup выглядит так:

  1. Нормализация имени по UTS-46 (lowercase + IDNA2008)
  2. Вычисление namehash
  3. Запрос к ENS Registry: registry.resolver(namehash)
  4. Если resolver поддерживает wildcard (supportsInterface(ENSIP-10)) — используем extended resolution
  5. Запрос к Resolver: resolver.addr(namehash, coinType)
  6. Если resolver возвращает OffchainLookup (EIP-3668) — выполняем CCIP-Read
  7. Финальный адрес

Большинство библиотек (ethers.js, viem) обрабатывают шаги 1-5. CCIP-Read поддерживается в ethers v6 и viem нативно.

Кастомный резолвер сервис

Для высоконагруженных приложений стоит реализовать собственный резолвинг сервис с кешем:

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;
  }
  
  // Batch resolution для списка адресов
  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;
  }
}

Multi-chain адреса (ENSIP-9)

ENS хранит адреса для разных сетей через coinType (SLIP-44):

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;
  
  return {
    eth: await resolver.getAddress(COIN_TYPES.ETH),
    btc: await resolver.getAddress(COIN_TYPES.BTC),
    sol: await resolver.getAddress(COIN_TYPES.SOL),
  };
}

Срок разработки кастомного резолвинг сервиса с кешем и multi-chain поддержкой — 3-5 рабочих дней. Интеграция в существующий бэкенд — 1-2 дня дополнительно.