@ens-rush-resolution/auto-resolve
Version:
Auto-detection and resolution of Ethereum addresses in web pages
167 lines (164 loc) • 5.89 kB
JavaScript
;
var ENSRushResolution = (() => {
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
autoResolve: () => autoResolve
});
// ../core/dist/index.mjs
var DEFAULT_API_ENDPOINT = "https://ens-api.gregskril.com";
async function resolve(addresses, options = {}) {
const { apiEndpoint = DEFAULT_API_ENDPOINT } = options;
if (addresses.length === 0) {
return [];
}
try {
const response = await fetch(`${apiEndpoint}/batch/addresses`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ addresses })
});
if (!response.ok) {
throw new Error(`API request failed: ${response.status}`);
}
const data = await response.json();
return addresses.map((address, index) => ({
address,
name: data[index] || null
}));
} catch (error) {
console.warn("ENS resolution failed:", error);
return addresses.map((address) => ({
address,
name: null
}));
}
}
// src/index.ts
var ETHEREUM_ADDRESS_REGEX = /0x[a-fA-F0-9]{40}/g;
function findAddressesInTextNode(textNode) {
const text = textNode.textContent || "";
const addresses = [];
let match;
ETHEREUM_ADDRESS_REGEX.lastIndex = 0;
while ((match = ETHEREUM_ADDRESS_REGEX.exec(text)) !== null) {
addresses.push({
address: match[0],
element: textNode.parentElement,
textNode,
startIndex: match.index,
endIndex: match.index + match[0].length
});
}
return addresses;
}
function findAllAddresses(root = document.body) {
const walker = document.createTreeWalker(
root,
NodeFilter.SHOW_TEXT,
{
acceptNode(node2) {
let parent = node2.parentElement;
while (parent) {
if (parent.dataset.ensRush === "false" || parent.dataset.ensRush === "skip") {
return NodeFilter.FILTER_REJECT;
}
parent = parent.parentElement;
}
return NodeFilter.FILTER_ACCEPT;
}
}
);
const allAddresses = [];
let node;
while (node = walker.nextNode()) {
const textNode = node;
const addresses = findAddressesInTextNode(textNode);
allAddresses.push(...addresses);
}
return allAddresses;
}
function updateAddressInDOM(addressElement, ensName) {
const { textNode, startIndex, endIndex, address } = addressElement;
const text = textNode.textContent || "";
if (!ensName) {
return;
}
const beforeText = text.substring(0, startIndex);
const afterText = text.substring(endIndex);
const ensSpan = document.createElement("span");
ensSpan.textContent = ensName;
ensSpan.title = address;
const parentElement = textNode.parentElement;
if (beforeText) {
parentElement.insertBefore(document.createTextNode(beforeText), textNode);
}
parentElement.insertBefore(ensSpan, textNode);
if (afterText) {
parentElement.insertBefore(document.createTextNode(afterText), textNode);
}
parentElement.removeChild(textNode);
}
async function autoResolve(options = {}) {
const { selector, onResolve, ...resolveOptions } = options;
const root = selector ? document.querySelector(selector) : document.body;
if (!root) {
console.warn("Auto-resolve: Root element not found");
return;
}
const addressElements = findAllAddresses(root);
if (addressElements.length === 0) {
console.log("Auto-resolve: No Ethereum addresses found");
return;
}
const uniqueAddresses = [...new Set(addressElements.map((ae) => ae.address))];
console.log(`Auto-resolve: Found ${addressElements.length} addresses (${uniqueAddresses.length} unique)`);
try {
const resolutions = await resolve(uniqueAddresses, resolveOptions);
const resolutionMap = new Map(resolutions.map((r) => [r.address, r.name]));
addressElements.forEach((addressElement) => {
const ensName = resolutionMap.get(addressElement.address);
if (onResolve) {
onResolve(addressElement.address, ensName || null, addressElement.element);
}
updateAddressInDOM(addressElement, ensName || null);
});
const resolvedCount = resolutions.filter((r) => r.name).length;
console.log(`Auto-resolve: Resolved ${resolvedCount}/${uniqueAddresses.length} addresses to ENS names`);
} catch (error) {
console.error("Auto-resolve: Failed to resolve addresses", error);
}
}
if (typeof window !== "undefined") {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => {
console.log("Auto-resolve: DOM loaded, starting auto-resolution...");
autoResolve();
});
} else {
console.log("Auto-resolve: DOM already loaded, starting auto-resolution...");
autoResolve();
}
}
return __toCommonJS(index_exports);
})();
//# sourceMappingURL=index.global.js.map