web3-domain-resolver
Version:
Web3 Library that enable with just one function to resolve domains on multiple web3 providers such as ENS, UnstoppableDomains and Freename
135 lines (134 loc) • 5.43 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NameTools = void 0;
const resolved_resource_type_1 = require("../resolvers/types/resolved-resource-type");
const name_tools_types_1 = require("./name-tools.types");
const punycode = require("punycode");
class NameTools {
static mapName(domainOrTld) {
if (!domainOrTld) {
return undefined;
}
const detailedName = this.getDetailedName(domainOrTld);
if (!detailedName) {
return undefined;
}
//portions
let tld = null;
let tldAsciiName = null;
let secondLevelDomain = null;
let secondLevelDomainAsciiName = null;
if (detailedName.type === name_tools_types_1.NameType.TLD) {
tld = domainOrTld;
tldAsciiName = detailedName.asciiName;
}
else if (detailedName.type === name_tools_types_1.NameType.SECOND_LEVEL_DOMAIN || detailedName.type === name_tools_types_1.NameType.SUB_DOMAINED_DOMAIN) {
const nameSplitted = detailedName.name.split(".");
const asciiNameSplitted = detailedName.asciiName.split(".");
if (nameSplitted.length === 2 && asciiNameSplitted.length === 2) {
tld = nameSplitted[nameSplitted.length - 1];
secondLevelDomain = nameSplitted[nameSplitted.length - 2];
tldAsciiName = asciiNameSplitted[asciiNameSplitted.length - 1];
secondLevelDomainAsciiName = asciiNameSplitted[asciiNameSplitted.length - 2];
}
}
return {
domain: secondLevelDomainAsciiName,
fullname: domainOrTld,
tld: tldAsciiName,
type: detailedName.type,
};
}
static getItemTypeFromString(name) {
if (name.includes(".")) {
const splitted = name.split(".");
const cleanSplitted = splitted.filter(s => s !== "");
if (cleanSplitted.length === 2) {
return name_tools_types_1.NameType.SECOND_LEVEL_DOMAIN;
}
else if (cleanSplitted.length === 1) {
return name_tools_types_1.NameType.TLD;
}
else if (cleanSplitted.length > 2) {
return name_tools_types_1.NameType.SUB_DOMAINED_DOMAIN;
}
}
return name_tools_types_1.NameType.TLD;
}
static getDetailedName(name) {
let foundError = false;
const errors = [];
//We need the ascii string to avoid detecting emoji and other unicode characters as invalid
const asciiString = punycode.toASCII(name);
//Check if the search input contains forbidden characters
const isSearchStringAllowable = this.isNameAllowed(asciiString);
if (!isSearchStringAllowable?.isAllowable) {
errors.push("INVALID_NAME");
foundError = true;
}
//Check if the search input name has a repeated dot (es. app..cryptotld)
const dotCount = asciiString.split(".").length - 1;
if (dotCount > 1) {
errors.push("REPETED_DOT");
foundError = true;
}
if (!foundError) {
let asciiName = asciiString;
const itemType = this.getItemTypeFromString(asciiString);
if (itemType == name_tools_types_1.NameType.SUB_DOMAINED_DOMAIN) {
//The search input name is a sub domained domain (es. freename.app.cryptotld)
errors.push("SUB_DOMAINS_NOT_ALLOWED");
}
else {
if (itemType == name_tools_types_1.NameType.TLD) {
//remove the "." from the start of the tld (es .freename becomes freename)
if (name.includes(".")) {
name = name.replace(/\./g, "");
asciiName = asciiName.replace(/\./g, "");
}
}
return {
asciiName,
name,
type: itemType,
};
}
}
}
static isNameAllowed(name) {
//Check if search string contains only allowed characters
const allowedCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.";
let invalidCharacters = [];
let isAllowable = true;
let dotsOnly = true;
for (let i = 0; i < name.length; i++) {
const char = name.charAt(i);
if (allowedCharacters.indexOf(char) === -1) {
invalidCharacters.push(char);
isAllowable = false;
}
if (char !== ".") {
dotsOnly = false;
}
}
if (dotsOnly) {
invalidCharacters = ["."];
isAllowable = false;
}
return {
isAllowable,
invalidCharacters,
};
}
static getResolvedResourceType(type) {
switch (type) {
case name_tools_types_1.NameType.TLD:
return resolved_resource_type_1.ResolvedResourceType.TLD;
case name_tools_types_1.NameType.SECOND_LEVEL_DOMAIN:
return resolved_resource_type_1.ResolvedResourceType.SECOND_LEVEL_DOMAIN;
default:
return resolved_resource_type_1.ResolvedResourceType.UNTYPED;
}
}
}
exports.NameTools = NameTools;