Two more resolvers under Settings › Names & Certificates. SNS — .sol names resolve through Bonfida's public SDK proxy, preferring an explicit URL record over an IPFS record (served via a configurable IPFS gateway). Unstoppable Domains — the full UD TLD roster (.crypto, .nft, .wallet, .bitcoin, .blockchain, .dao, …) through resolve.unstoppabledomains.com; browser.redirect_url takes precedence over an ipfs record. .x stays with BNS — the UD adapter explicitly skips it so a Sirius registration can never be shadowed by an Unstoppable one. Both proxies are Cloudflare-fronted; users on blocked IPs can swap the endpoint in Advanced. The handshake adapter's skip-list grows to cover .sol and every UD TLD so a user with HNS + UD + SNS all enabled gets the specific adapter, never the generic hns.to gateway, for those names. Hermes.X moves from the home page's Silent Mode card grid to the Theseus left-sidebar quick-link strip, slotting in right after Proton Mail. The default list grows to 6 entries; existing profiles pick it up through the LATER_DEFAULTS one-time offer (same mechanism Proton used in 0.3.88). Users who still have Hermes on their custom home page can remove it manually.
68 lines
6.7 KiB
JavaScript
68 lines
6.7 KiB
JavaScript
"use strict";
|
|
// Handshake resolver — routes non-ICANN TLDs through a public HNS web
|
|
// gateway (hns.to by default). hns.to receives `foo.<tld>.hns.to`, looks up
|
|
// the Handshake TLD, fetches the on-chain site, and serves it back. From
|
|
// Theseus's side the adapter is a one-liner URL rewrite + a collision check
|
|
// to decide whether to touch the hostname at all.
|
|
//
|
|
// The collision check matters: Handshake auctioned on-chain TLDs that
|
|
// collide with real DNS names (e.g. ".app", ".dev"). We don't want to
|
|
// hijack those by default. With collision_policy = "icann-wins" (default),
|
|
// the adapter returns null for any TLD in a bundled "common ICANN" list so
|
|
// clearnet takes over. With "hns-wins", we always try HNS first.
|
|
//
|
|
// The list isn't the full IANA root zone (~1600 entries). It's the few
|
|
// hundred TLDs real users actually see: original gTLDs, popular new gTLDs,
|
|
// every ccTLD. If a TLD escapes the list and happens to collide with an
|
|
// HNS registration, the user can switch to "icann-wins" and whitelist via
|
|
// per-host overrides (future). Nothing breaks silently — the collision is
|
|
// opt-in by the user turning HNS on.
|
|
|
|
const CACHE_TTL_MS = 10 * 60 * 1000;
|
|
const CACHE = new Map();
|
|
|
|
// Common ICANN TLDs — the ones a browser would actually see in practice.
|
|
// Not exhaustive; grown as needed.
|
|
const ICANN_TLDS = new Set([
|
|
// original gTLDs
|
|
"com","org","net","edu","gov","mil","int","arpa","info","biz","name","pro","museum","aero","coop","jobs","mobi","tel","travel","cat","asia","post","tv","me","cc","ws","bz","su","ac",
|
|
// common new gTLDs
|
|
"app","dev","io","co","xyz","online","site","shop","store","tech","cloud","blog","news","world","world","global","global","email","agency","media","design","photo","art","gallery","pub","bar","cafe","wine","rest","restaurant","hotel","travel","fitness","gym","run","bike","boats","car","cars","fish","flight","flights","garden","farm","pet","pizza","realtor","salon","school","soccer","software","solar","taxi","vet","yoga","academy","band","bank","beer","beauty","best","buzz","build","builders","cash","chat","church","city","claims","clinic","clothing","club","coach","codes","coffee","community","company","computer","construction","contact","contractors","cool","country","credit","dance","deals","delivery","dental","dentist","digital","direct","directory","discount","doctor","download","education","energy","engineer","engineering","enterprises","equipment","events","expert","exposed","express","family","fashion","finance","financial","fit","fitness","food","foundation","fund","furniture","games","gift","glass","gold","graphics","group","guide","guru","haus","healthcare","help","holdings","holiday","home","host","house","icu","immo","industries","ink","insurance","international","investments","jewelry","kitchen","land","lawyer","legal","life","lighting","limited","limo","link","live","loan","loans","lol","love","ltd","management","market","marketing","marketplace","mba","media","medical","money","mortgage","movie","music","network","ninja","parts","party","photo","photography","photos","pics","pictures","plumbing","plus","press","productions","properties","pub","quest","radio","recipes","reviews","rip","run","sale","salon","school","science","security","services","shoes","shop","show","singles","soccer","software","solar","solutions","space","sport","store","studio","style","supplies","supply","support","surgery","systems","taxi","team","tech","technology","theatre","tickets","today","tools","tours","town","trade","training","transfer","travel","tv","university","vacations","ventures","vet","video","villas","vision","vote","voyage","watch","website","wedding","wiki","win","work","works","world","xxx","zone","gay","ltda","health","hiphop","fail","flowers","forsale","free","garden","gives","giving","golf","loan","map","mom","organic","place","play","promo","review","rodeo","show","shows","sky","soccer","social","spa","style","sucks","survey","tech","tires","top","vote","wtf","vip","hey","kiwi","earth",
|
|
// common ccTLDs (two-letter)
|
|
"ac","ad","ae","af","ag","ai","al","am","ao","aq","ar","as","at","au","aw","ax","az","ba","bb","bd","be","bf","bg","bh","bi","bj","bm","bn","bo","br","bs","bt","bv","bw","by","bz","ca","cc","cd","cf","cg","ch","ci","ck","cl","cm","cn","co","cr","cu","cv","cw","cx","cy","cz","de","dj","dk","dm","do","dz","ec","ee","eg","er","es","et","eu","fi","fj","fk","fm","fo","fr","ga","gb","gd","ge","gf","gg","gh","gi","gl","gm","gn","gp","gq","gr","gs","gt","gu","gw","gy","hk","hm","hn","hr","ht","hu","id","ie","il","im","in","io","iq","ir","is","it","je","jm","jo","jp","ke","kg","kh","ki","km","kn","kp","kr","kw","ky","kz","la","lb","lc","li","lk","lr","ls","lt","lu","lv","ly","ma","mc","md","me","mg","mh","mk","ml","mm","mn","mo","mp","mq","mr","ms","mt","mu","mv","mw","mx","my","mz","na","nc","ne","nf","ng","ni","nl","no","np","nr","nu","nz","om","pa","pe","pf","pg","ph","pk","pl","pm","pn","pr","ps","pt","pw","py","qa","re","ro","rs","ru","rw","sa","sb","sc","sd","se","sg","sh","si","sj","sk","sl","sm","sn","so","sr","ss","st","sv","sx","sy","sz","tc","td","tf","tg","th","tj","tk","tl","tm","tn","to","tr","tt","tv","tw","tz","ua","ug","uk","us","uy","uz","va","vc","ve","vg","vi","vn","vu","wf","ws","ye","yt","za","zm","zw",
|
|
]);
|
|
|
|
async function resolve(host, { endpoint, collision_policy } = {}) {
|
|
if (!host || !host.includes(".")) return null;
|
|
const name = String(host).toLowerCase();
|
|
// Collision gate — only skip ICANN TLDs when icann-wins is set (the default).
|
|
const tld = name.split(".").pop();
|
|
if ((collision_policy || "icann-wins") === "icann-wins" && ICANN_TLDS.has(tld)) return null;
|
|
// Other extra-resolver TLDs run before HNS in tryExtraResolvers — return
|
|
// null here so Handshake doesn't shadow them when their toggle is off and
|
|
// the user's intent was clearnet (e.g. a .crypto name that's not registered
|
|
// on UD should 404 clearnet, not get hijacked into HNS).
|
|
const CLAIMED = new Set([
|
|
"eth", "bit", "sol",
|
|
// Unstoppable Domains TLDs
|
|
"crypto","nft","wallet","bitcoin","blockchain","dao","888","polygon",
|
|
"klever","hi","kresus","anime","manga","go","unstoppable","pudgy",
|
|
"binanceus","austin","bitget","tball","secret","farms","raiin","stepn",
|
|
"emir","smokey","lfg","pog","witg","metropolis","wrkx","benji","altimist",
|
|
"ethermail",
|
|
]);
|
|
if (CLAIMED.has(tld)) return null;
|
|
|
|
const cached = CACHE.get(name);
|
|
if (cached && cached.exp > Date.now()) return cached.result;
|
|
|
|
const gw = (endpoint || "https://hns.to").replace(/\/+$/, "").replace(/^https?:\/\//, "");
|
|
const url = `https://${name}.${gw}`;
|
|
const result = { url, protocol: "handshake", gateway: gw };
|
|
CACHE.set(name, { result, exp: Date.now() + CACHE_TTL_MS });
|
|
return result;
|
|
}
|
|
|
|
function clearCache() { CACHE.clear(); }
|
|
|
|
module.exports = { resolve, clearCache, ICANN_TLDS };
|