Разработка системы профилей на базе ENS
ENS хранит не только адреса — resolver поддерживает произвольные текстовые записи, IPFS contenthash, multi-chain адреса. Это готовая инфраструктура для decentralized identity: пользователь управляет своим профилем через ENS, приложения читают данные без централизованного хранилища.
Структура ENS профиля
Стандартные поля согласно EIP-634:
interface ENSProfile {
// Core identity
name: string; // display name
description: string; // bio
avatar: string; // URL или IPFS hash изображения
// Contact
email: string;
url: string; // website
// Social
"com.twitter": string;
"com.github": string;
"com.discord": string;
"org.telegram": string;
"com.reddit": string;
// Professional
keywords: string; // comma-separated теги
notice: string; // публичное уведомление
}
Чтение профиля
import { createPublicClient, http } from "viem";
import { mainnet } from "viem/chains";
import { normalize } from "viem/ens";
const client = createPublicClient({ chain: mainnet, transport: http(RPC_URL) });
async function getENSProfile(nameOrAddress: string) {
let ensName: string | null = null;
// Определяем: это имя или адрес?
if (nameOrAddress.endsWith(".eth")) {
ensName = normalize(nameOrAddress);
} else {
ensName = await client.getEnsName({ address: nameOrAddress as `0x${string}` });
}
if (!ensName) return null;
const [avatar, textRecords] = await Promise.all([
client.getEnsAvatar({ name: ensName }),
Promise.all([
client.getEnsText({ name: ensName, key: "description" }),
client.getEnsText({ name: ensName, key: "com.twitter" }),
client.getEnsText({ name: ensName, key: "com.github" }),
client.getEnsText({ name: ensName, key: "url" }),
]),
]);
return {
name: ensName,
avatar,
description: textRecords[0],
twitter: textRecords[1],
github: textRecords[2],
website: textRecords[3],
};
}
Avatar resolution
ENS поддерживает несколько форматов avatar:
- HTTP/HTTPS URL:
https://example.com/avatar.png - IPFS:
ipfs://QmHash... - NFT ссылка:
eip155:1/erc721:0xContractAddr/tokenId— автоматически читает tokenURI
// viem getEnsAvatar автоматически обрабатывает все форматы
// и возвращает конечный URL изображения
const avatarUrl = await client.getEnsAvatar({ name: "vitalik.eth" });
Для NFT аватаров: библиотека запрашивает tokenURI → парсит metadata → возвращает image URL. Важно: NFT должен принадлежать владельцу ENS имени — иначе аватар не показывается.
Запись профиля
import { createWalletClient, custom } from "viem";
const walletClient = createWalletClient({
chain: mainnet,
transport: custom(window.ethereum),
});
// ENS Public Resolver адрес (mainnet)
const RESOLVER = "0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63";
const ENS_ABI = [...] // ABI resolver
const { request } = await client.simulateContract({
address: RESOLVER,
abi: ENS_ABI,
functionName: "setText",
args: [namehash("alice.eth"), "description", "DeFi developer"],
account: walletClient.account,
});
await walletClient.writeContract(request);
Кеширование и производительность
ENS данные меняются редко. Агрессивное кеширование оправдано:
| Поле | TTL кеша |
|---|---|
| Адрес (forward resolution) | 10 минут |
| Reverse resolution | 10 минут |
| Avatar | 1 час |
| Текстовые записи | 30 минут |
Для приложений с высокой нагрузкой — Redis кеш перед RPC вызовами. Размер кеша минимален (несколько KB на профиль), можно хранить тысячи профилей.
Верификация linked accounts
Twitter/GitHub верификация в ENS — пользователь указывает handle, но любой может написать любой handle. Для верификации нужен дополнительный шаг:
Проверка через Keybase / Lens Protocol: пользователь публикует cryptographic proof (подпись кошелька) в Twitter/GitHub. Верификаторы (Keybase, Lens) проверяют ownership.
EAS attestation: доверенный верификатор выпускает attestation "адрес X владеет Twitter @Y" через EAS. Профиль читает attestation, не просто текстовую запись.
Разработка системы ENS-профилей с чтением данных, кешированием, avatar resolution и верификацией linked accounts — 1-3 недели в зависимости от глубины функций.







