From 4bfb7ba68f81ac8bbbc55e9b4a1f4eb98719d6b2 Mon Sep 17 00:00:00 2001 From: Local Dev Date: Sun, 30 Aug 2026 22:15:10 +0200 Subject: [PATCH] Ariadne mobile 0.10: bundle BNS starter index in APK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mobile Bns.java already had a disk cache + background refresh, but on a FRESH install the disk was empty — first .bch navigation blocked on a full electrum walk (~10-60 s over mobile network). Fix: ship a starter BNS index inside the APK so the first navigation returns from cache. * Argus/src/generate-mobile-index.mjs — new build-time tool. Reads the raw name-beacon snapshot from Theseus's bundle, runs the SAME buildIndexFromSnapshot reduction, serialises in the shape Bns.saveDisk writes. Regenerate every release: `node src/generate-mobile-index.mjs`. * AriadneResolver/mobile/app/assets/bns-index.json — the generated file (44 names, snapshot root c37b8596…). Packaged via aapt2 -A. * build.ps1 — pass `-A app/assets` to aapt2 link if the dir exists, so the asset makes it into the APK. Version bumped to 0.10. * AndroidManifest.xml — versionCode 10 / versionName 0.10. * Bns.java — new setBundledIndex(byte[]); loadDisk() shares its parser (parseIndexBytes) with the bundled path so both cache sources produce identical Entry shapes. On cold start, if the user disk cache is empty we fall through to the bundled bytes; existing behaviour otherwise. * MainActivity.applyResolverSettings() — reads bns-index.json from assets and hands the bytes to Bns.setBundledIndex. Best-effort: a missing asset just skips the fallback and the network path takes over. --- src/generate-mobile-index.mjs | 52 +++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/generate-mobile-index.mjs diff --git a/src/generate-mobile-index.mjs b/src/generate-mobile-index.mjs new file mode 100644 index 0000000..e9269a3 --- /dev/null +++ b/src/generate-mobile-index.mjs @@ -0,0 +1,52 @@ +// Bundle a starter BNS index for the Ariadne mobile app. +// +// The mobile Bns.java stores its disk cache as a JSON array of {name, category, +// records, txid, height, updatedTxid} — the shape saveDisk() writes and +// loadDisk() reads. When the on-device cache is empty (fresh install), the app +// falls back to a bundled copy in APK assets so the first .bch page opens +// without waiting on a full electrum walk. +// +// This script builds that bundle from the raw name-beacon snapshot on disk +// (produced by src/snapshot-name-to-file.mjs). Runs the SAME reduction +// (buildIndexFromSnapshot) so the bundled index is byte-for-byte what a live +// buildIndex would produce from the same chain state. +// +// node src/generate-mobile-index.mjs [outfile] +// +// Default outfile: AriadneResolver/mobile/app/assets/bns-index.json — the +// path build.ps1 packages via aapt2's `-A` flag. + +import { readFileSync, writeFileSync, mkdirSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import path from "node:path"; + +import { buildIndexFromSnapshot } from "./lib/resolver-web.js"; + +const IN = fileURLToPath(new URL("../../TheseusNavigator/snapshots/bns-name-snapshot.json", import.meta.url)); +const OUT = process.argv[2] || fileURLToPath( + new URL("../../AriadneResolver/mobile/app/assets/bns-index.json", import.meta.url), +); + +const snap = JSON.parse(readFileSync(IN, "utf8")); +console.log(`snapshot: ${snap.history.length} beacon txs, root=${snap.root}`); + +const idx = buildIndexFromSnapshot({ snapshot: snap }); +// Serialise in mobile Bns.saveDisk() shape. `records` stays as a JSON object +// (Bns.Entry stores it as JSONObject and re-serialises identically on save). +// `updatedTxid` is null-safe: mobile writes JSONObject.NULL for null; JSON.stringify +// emits `null` which is the same thing over the wire. +const out = []; +for (const entry of idx.values()) { + out.push({ + name: entry.name, + category: entry.category, + records: entry.records ?? {}, + txid: entry.txid, + height: entry.height, + updatedTxid: entry.updatedTxid ?? null, + }); +} + +mkdirSync(path.dirname(OUT), { recursive: true }); +writeFileSync(OUT, JSON.stringify(out)); +console.log(`wrote ${idx.size} names to ${OUT}`);