Two more adapters under Settings › Names & Certificates:
Namecoin — .bit names resolve by calling name_show "d/<name>" on the
configured JSON-RPC endpoint and following `translate` or `alias` records
to a clearnet host. Pure IP records aren't followed yet (that needs
in-browser DNS override + TLS pinning, which comes later). Namecoin has
no free public RPC, so the toggle is off by default and the row carries a
"Needs an RPC URL" note instead of a "Not wired yet" one; set yours in
Advanced.
Handshake — non-ICANN hostnames resolve through the public hns.to web
gateway (user-overridable in Advanced). hns.to proxies the request to a
Handshake node and serves the on-chain content. A bundled list of common
ICANN TLDs (original gTLDs + popular new gTLDs + every ccTLD) keeps the
default collision policy ("icann-wins") from hijacking clearnet names.
Setting the policy to "hns-wins" removes that gate.
Both adapters follow the ENS adapter's shape — tryExtraResolvers in main.js
calls each in turn after the BNS lookup; the first one that returns a URL
loads it. Settings copy on both rows updated.
58 lines
6.3 KiB
JavaScript
58 lines
6.3 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;
|
|
// BNS TLDs are already handled by the normal BNS path upstream; HNS adapter
|
|
// runs for every other dotted host. .eth / .bit go through their own adapters
|
|
// first, so by the time we get here they've been eliminated.
|
|
if (tld === "eth" || tld === "bit") 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 };
|