// BNS wallet: a wallet app with an embedded .bch resolver and browser pane. // This is the "resolver inside the wallet" architecture: the wallet holds keys, // resolves names straight from the BCH chain, and renders the result in-app. import express from "express"; import { loadWallet } from "./lib/wallet.js"; import { buildIndex, resolveName, registerName, updateName, normalizeName } from "./lib/bns.js"; import { APP_PORT, TLD } from "./config.js"; const wallet = await loadWallet(); const app = express(); app.use(express.json()); // tiny index cache so browsing doesn't re-scan the beacon on every keystroke let cache = { at: 0, index: new Map() }; async function index() { if (Date.now() - cache.at > 15_000) { cache = { at: Date.now(), index: await buildIndex(wallet.provider) }; } return cache.index; } app.get("/api/status", async (_req, res) => { res.json({ cashaddr: wallet.cashaddr, tokenaddr: wallet.tokenaddr, balanceSat: String(await wallet.getBalance("sat")), names: [...(await index()).values()].map((e) => ({ ...e })), }); }); app.get("/api/resolve/:name", async (req, res) => { try { const entry = (await index()).get(normalizeName(req.params.name)); if (!entry) return res.status(404).json({ error: "NXDOMAIN" }); res.json(entry); } catch (e) { res.status(400).json({ error: e.message }); } }); app.post("/api/register", async (req, res) => { try { const { name, records } = req.body; cache.at = 0; res.json(await registerName(wallet, name, records)); } catch (e) { res.status(400).json({ error: e.message }); } }); app.post("/api/update", async (req, res) => { try { const { name, records } = req.body; cache.at = 0; res.json(await updateName(wallet, name, records)); } catch (e) { res.status(400).json({ error: e.message }); } }); // The "browser" endpoint: renders what a .bch name points to. app.get("/view/:name", async (req, res) => { let entry; try { entry = (await index()).get(normalizeName(req.params.name)); } catch (e) { return res.status(400).send(`
${e.message}`);
}
if (!entry) {
return res.status(404).send(
`${req.params.name} is not registered on the chain.
${JSON.stringify(entry, null, 2)}`);
});
app.get("/", (_req, res) => {
res.send(UI);
});
const UI = /* html */ `