如何使用Ethers.js获取指定钱包地址下的所有ENS域名?
用Ethers.js获取特定钱包下的所有ENS域名
要获取特定地址下的所有ENS域名,由于ENS合约未直接提供“按地址查询域名”的方法,我们需要通过查询ENS注册表合约的相关事件来实现——每次域名注册或所有权转移时,都会触发对应事件,过滤出目标地址作为所有者的事件后,再去重验证即可。
步骤说明
依赖与环境准备
先安装Ethers.js:npm install ethers同时需要连接一个以太坊节点(可使用Alchemy、Infura等第三方服务商节点,或本地节点)。
ENS注册表合约信息
ENS注册表的固定合约地址为:0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e,我们需要用该地址创建合约实例,并加载包含所需事件的简化ABI。事件过滤与查询
核心关注两个事件:NameRegistered(bytes32 indexed label, address indexed owner, uint expires):域名注册时触发,记录初始所有者NameTransferred(bytes32 indexed label, address indexed owner):域名所有权转移时触发,记录新所有者
过滤出这两个事件中
owner为目标地址的记录,再将事件中的label转换为可读的域名前缀(比如label对应vitalik,则完整域名为vitalik.eth)。去重与验证
同一个域名可能多次转移,需用去重逻辑保留最新记录;同时建议验证每个域名当前的所有者确实是目标地址,避免因查询块范围不全导致的错误。
代码示例(Ethers.js v6)
import { ethers } from "ethers"; // 目标地址 const targetAddress = "0x8f635716982B836c4eB47e2F5c7B007Dde278F99"; // ENS注册表合约地址和简化ABI(仅包含所需事件与方法) const ensRegistryAddress = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"; const ensRegistryAbi = [ "event NameRegistered(bytes32 indexed label, address indexed owner, uint expires)", "event NameTransferred(bytes32 indexed label, address indexed owner)", "function owner(bytes32 node) view returns (address)" ]; async function getENSNamesForAddress() { // 连接以太坊节点,替换为你的节点URL const provider = new ethers.JsonRpcProvider("https://eth-mainnet.g.alchemy.com/v2/your-api-key"); // 创建合约实例 const ensRegistry = new ethers.Contract(ensRegistryAddress, ensRegistryAbi, provider); // 构建事件过滤器,筛选目标地址作为owner的事件 const filterRegistered = ensRegistry.filters.NameRegistered(null, targetAddress); const filterTransferred = ensRegistry.filters.NameTransferred(null, targetAddress); // 查询事件,可指定块范围,默认查询全部历史 const registeredEvents = await ensRegistry.queryFilter(filterRegistered); const transferredEvents = await ensRegistry.queryFilter(filterTransferred); // 合并事件并去重,保留最新记录 const allEvents = [...registeredEvents, ...transferredEvents]; const domainMap = new Map(); for (const event of allEvents) { const label = event.args.label; // 按块高排序,块高更大的事件为最新记录 if (!domainMap.has(label) || event.blockNumber > domainMap.get(label).blockNumber) { domainMap.set(label, event); } } // 转换label为可读域名,并验证当前所有者 const ensNames = []; for (const [label] of domainMap) { const name = ethers.decodeBytes32String(label); const fullDomain = `${name}.eth`; // 验证当前所有者是否为目标地址 const node = ethers.namehash(fullDomain); const currentOwner = await ensRegistry.owner(node); if (currentOwner.toLowerCase() === targetAddress.toLowerCase()) { ensNames.push(fullDomain); } } return ensNames; } // 执行查询并输出结果 getENSNamesForAddress() .then(names => console.log("目标地址下的ENS域名:", names)) .catch(err => console.error("查询出错:", err));
注意事项
- 需将代码中的节点URL替换为你自己的API地址(如Alchemy/Infura的密钥地址)
- 若查询历史事件量过大,建议分块查询以避免超时
- 上述代码主要针对
.eth后缀域名,其他后缀的ENS域名需额外处理解析逻辑
内容的提问来源于stack exchange,提问作者Ose Daniel Okojie
相关产品推荐
相关产品推荐

