diff --git a/bundled-addons/aegis/addon.json b/bundled-addons/aegis/addon.json index d824c36c..a42a1fa8 100644 --- a/bundled-addons/aegis/addon.json +++ b/bundled-addons/aegis/addon.json @@ -1,13 +1,13 @@ { - "id": "bchwallet", + "id": "aegis", "name": "Aegis Wallet", - "version": "0.3.1", + "version": "0.4.0", "description": "Multi-chain wallet (BCH, BTC, TRX, ETH, SOL, SC, DGB) derived from your Theseus vault. Dapps get window.bitcoincash on .x sites; window.tronWeb / window.tronLink / window.ethereum / window.solana on any https page.", "author": "Silent Mode", "icon": "🛡", "main": "index.js", "capabilities": ["sidebar-panel", "vault-derive", "page-inject", "approval-modal"], - "absorbs": ["siawallet"], + "absorbs": ["bchwallet", "siawallet"], "page-inject": { "preload": "wallet-inject.js", "origins": ["https://*/*"] diff --git a/main.js b/main.js index df22655c..94abc628 100644 --- a/main.js +++ b/main.js @@ -1330,6 +1330,48 @@ function readAddonVersion(dir) { try { return JSON.parse(fs.readFileSync(path.join(dir, "addon.json"), "utf8"))?.version ?? null; } catch { return null; } } +// One-time migration for the bchwallet → aegis rename + the siawallet +// retirement. Idempotent: after the first run the sources are gone and +// subsequent runs are no-ops. +// +// - addons/bchwallet/ → addons-backups/bchwallet-migrated-/ +// (bundle folder is now aegis/; leaving the old dir active would load +// the pre-rename copy as a second addon under the same id and clash). +// - addons-data/bchwallet.json → addons-data/aegis.json (COPY, so any +// downgrade to a 0.3.x build can still read its own storage). +// - addons/siawallet/ → addons-backups/siawallet-migrated-/ +// (folded into Aegis via absorbs: ["siawallet"]; keeping it running +// would show duplicate Sia UI). Its data file stays under +// addons-data/ untouched — Aegis derives its own SC walletdUrl +// per-sub-wallet, so users re-paste their URL in Aegis Settings. +function migrateAegisRename() { + const stamp = new Date().toISOString().replace(/[:.]/g, "-"); + const backups = addonsBackupDir(); + try { fs.mkdirSync(backups, { recursive: true }); } catch {} + const addonsRoot = addonsUserDir(); + const dataRoot = addonsDataDir(); + + const bchDir = path.join(addonsRoot, "bchwallet"); + const aegisDir = path.join(addonsRoot, "aegis"); + const bchJson = path.join(dataRoot, "bchwallet.json"); + const aegisJson = path.join(dataRoot, "aegis.json"); + if (fs.existsSync(bchDir) && !fs.existsSync(aegisDir)) { + if (fs.existsSync(bchJson) && !fs.existsSync(aegisJson)) { + try { fs.copyFileSync(bchJson, aegisJson); console.log("[addons] migrated bchwallet.json -> aegis.json"); } + catch (err) { console.warn("[addons] migrate storage failed:", err?.message); } + } + const backup = path.join(backups, `bchwallet-migrated-${stamp}`); + try { fs.renameSync(bchDir, backup); console.log(`[addons] retired addons/bchwallet -> addons-backups/${path.basename(backup)} (folder renamed to aegis/)`); } + catch (err) { console.warn("[addons] retire bchwallet failed:", err?.message); } + } + + const siaDir = path.join(addonsRoot, "siawallet"); + if (fs.existsSync(siaDir)) { + const backup = path.join(backups, `siawallet-migrated-${stamp}`); + try { fs.renameSync(siaDir, backup); console.log(`[addons] retired addons/siawallet -> addons-backups/${path.basename(backup)} (absorbed by aegis)`); } + catch (err) { console.warn("[addons] retire siawallet failed:", err?.message); } + } +} function seedBundledAddons() { const dst = addonsUserDir(); try { fs.mkdirSync(dst, { recursive: true }); } catch {} @@ -1371,6 +1413,9 @@ function initAddons() { stagedDir: addonsStagedDir(), logger: (...a) => console.log("[addons]", ...a), }); + // Retire the pre-rename bundle layouts before reseeding so the fresh + // aegis/ + siawallet-less state is what AddonHost enumerates. + migrateAegisRename(); seedBundledAddons(); addonHost = new AddonHost({ addonsDir: addonsUserDir(), diff --git a/settings.html b/settings.html index 4edf5cbc..8749f121 100644 --- a/settings.html +++ b/settings.html @@ -998,14 +998,17 @@ arRefresh.onclick = refreshAriadne; refreshAriadne(); - // ---- Aegis (bchwallet) update card -------------------------------------- + // ---- Aegis update card -------------------------------------------------- // Aegis is a bundled add-on but its updates are shipped OTA via the signed // add-on update endpoint, so users can get new wallet versions without // updating Theseus. The same addons-check-updates IPC the Extensions page - // uses is filtered for the bchwallet id so this card only speaks for Aegis. + // uses is filtered for the aegis id so this card only speaks for Aegis. + // Legacy id "bchwallet" is also matched for upgrades from pre-rename + // installs (0.3.x); post-migration the entry lives at id="aegis". const aegisStatus = document.getElementById("aegisStatus"); const aegisCheck = document.getElementById("aegisCheck"); const aegisApply = document.getElementById("aegisApply"); + const isAegis = (a) => a && (a.id === "aegis" || a.id === "bchwallet"); async function refreshAegis() { aegisApply.hidden = true; try { @@ -1013,8 +1016,8 @@ C.listAddons ? C.listAddons() : Promise.resolve([]), C.listStagedAddonUpdates ? C.listStagedAddonUpdates() : Promise.resolve([]), ]); - const cur = (installed || []).find((a) => a.id === "bchwallet"); - const upd = (staged || []).find((a) => a.id === "bchwallet"); + const cur = (installed || []).find(isAegis); + const upd = (staged || []).find(isAegis); if (!cur) { aegisStatus.textContent = "Aegis isn't installed. Reinstall Theseus to add it back, or open Settings > Extensions to load it manually."; return; } const curVer = cur.version || "?"; if (upd && upd.version) { @@ -1031,7 +1034,7 @@ aegisStatus.textContent = "Checking…"; try { const staged = await (C.checkAddonUpdates ? C.checkAddonUpdates() : Promise.resolve([])); - const upd = (staged || []).find((a) => a.id === "bchwallet"); + const upd = (staged || []).find(isAegis); if (!upd) { aegisStatus.textContent = "You're on the latest Aegis."; } // refresh will populate everything else + toggle the Apply button refreshAegis();