ENS Domain Resolution System Development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
ENS Domain Resolution System Development
Simple
from 1 business day to 3 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1214
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

ENS Domain Resolution System Development

ENS resolution is not just calling provider.resolveName(). For production systems, you need to account for caching, wildcard support, CCIP-Read (off-chain resolvers), and correct multi-chain address handling. Especially when resolution occurs not in a browser but in backend services or smart contracts.

Full Resolution Chain

A standard ENS lookup looks like:

  1. Name normalization by UTS-46 (lowercase + IDNA2008)
  2. Namehash computation
  3. Query to ENS Registry: registry.resolver(namehash)
  4. If resolver supports wildcard (supportsInterface(ENSIP-10)) — use extended resolution
  5. Query to Resolver: resolver.addr(namehash, coinType)
  6. If resolver returns OffchainLookup (EIP-3668) — perform CCIP-Read
  7. Final address

Most libraries (ethers.js, viem) handle steps 1-5. CCIP-Read is supported in ethers v6 and viem natively.

Custom Resolution Service

For high-load applications, it's worth implementing a custom resolution service with 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 minutes 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 for list of addresses
  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);
      }
    }
    
    // Parallel resolution for uncached
    await Promise.allSettled(
      uncached.map(async (addr) => {
        const name = await this.lookupAddress(addr);
        results.set(addr, name);
      })
    );
    
    return results;
  }
}

Multi-chain Addresses (ENSIP-9)

ENS stores addresses for different networks via 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),
  };
}

Development timeline for a custom resolution service with caching and multi-chain support — 3-5 working days. Integration into existing backend — 1-2 days additional.