diff --git a/bundled-addons/aegis/addon.json b/bundled-addons/aegis/addon.json
index f237fb85..faeb0158 100644
--- a/bundled-addons/aegis/addon.json
+++ b/bundled-addons/aegis/addon.json
@@ -1,7 +1,7 @@
{
"id": "aegis",
"name": "Aegis Wallet",
- "version": "0.9.5",
+ "version": "0.9.6",
"category": "plugin",
"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",
diff --git a/bundled-addons/aegis/panel.js b/bundled-addons/aegis/panel.js
index 98c3461c..1c54929b 100644
--- a/bundled-addons/aegis/panel.js
+++ b/bundled-addons/aegis/panel.js
@@ -595,10 +595,12 @@ function fillPicker() {
d.querySelectorAll("[data-browse-add]").forEach((row) => row.addEventListener("click", (e) => {
e.stopPropagation();
const chain = row.dataset.browseAdd;
- // Jump straight into the create-wallet flow for that coin. The
- // Add pane keys off `pickerTab = "add"` and reads the target
- // chain from a scratch field the coin-picker fills.
- pickerTab = "add";
+ // Offer the method chooser (New / Import / Connect) rather than
+ // dropping straight into create — "add a BCH wallet" is just as
+ // often "bring in the one I already have". pickerAddChain is
+ // module-level, so the coin stays preselected through whichever
+ // branch the user picks.
+ pickerTab = "method";
pickerAddChain = chain;
fillPicker();
}));
@@ -880,6 +882,56 @@ function aegisConfirm(opts) {
});
}
+// Pick-one-of-several sibling of aegisConfirm, for branches where the
+// honest answer is a question rather than a yes/no. Resolves the chosen
+// option's `id`, or null if dismissed.
+// opts: { title, body, icon, options: [{id, label, hint, primary}] }
+function aegisChoose(opts) {
+ const o = opts || {};
+ const options = Array.isArray(o.options) ? o.options : [];
+ return new Promise((resolve) => {
+ const overlay = document.createElement("div");
+ overlay.style.cssText = "position:fixed;inset:0;background:rgba(0,0,0,.55);display:flex;align-items:flex-start;justify-content:center;z-index:100000;padding-top:24px";
+ overlay.innerHTML = `
+
+
+ ${o.icon || "+"}
+
${esc(o.title || "Choose")}
+
+ ${o.body ? `
${o.body}
` : ""}
+
+ ${options.map((op) => `
+ `).join("")}
+
+
+
+
+
`;
+ document.body.appendChild(overlay);
+ let done = false;
+ const finish = (val) => {
+ if (done) return;
+ done = true;
+ document.removeEventListener("keydown", onKey, true);
+ try { overlay.remove(); } catch {}
+ resolve(val);
+ };
+ const onKey = (e) => { if (e.key === "Escape") { e.stopPropagation(); finish(null); } };
+ document.addEventListener("keydown", onKey, true);
+ overlay.addEventListener("click", (e) => { if (e.target === overlay) finish(null); });
+ overlay.querySelectorAll("[data-ac]").forEach((b) => b.addEventListener("click", (e) => {
+ e.stopPropagation();
+ finish(b.dataset.ac || null);
+ }));
+ const first = overlay.querySelector('[data-ac]:not([data-ac=""])');
+ if (first) first.focus();
+ });
+}
+
// Single-button sibling of aegisConfirm, for the error notices that used
// window.alert(). Fire-and-forget: callers don't need the result, so it
// works from sync handlers too.
@@ -2597,10 +2649,26 @@ function renderInlineCoinList(el, groupKey, group) {
// the coin list when the last address under a coin goes away.
el.querySelector("#stripAddMore").addEventListener("click", async () => {
- // Add another wallet of the same coin+network directly, without
- // opening the picker sheet — the user is already inside this coin's
- // address list so their intent is unambiguous.
+ // This used to create a fresh wallet immediately, on the reasoning
+ // that being inside a coin's address list made the intent
+ // unambiguous. It doesn't: "add another BCH wallet" is just as often
+ // "bring in the one I already have somewhere else". Creating instead
+ // of importing is not a harmless guess either — the user ends up with
+ // an empty new address and has to work out why their funds aren't
+ // there. So ask.
const first = gw[0];
+ const pick = await aegisChoose({
+ title: `Add another ${meta.ticker} wallet`,
+ // meta.coinName already carries the network ("TRX Nile"), so naming
+ // networkLabel again read "TRX Nile · Nile testnet".
+ body: `On ${esc(meta.coinName)}.`,
+ options: [
+ { id: "create", label: "Create a new wallet", hint: "Derived from your Theseus vault — nothing to write down", primary: true },
+ { id: "import", label: "Import an existing wallet", hint: "BIP39 mnemonic, or a chain-native private key" },
+ ],
+ });
+ if (!pick) return;
+ if (pick === "import") { openImportModal(first.chain); return; }
try {
state = await S.invoke("addWallet", { chain: first.chain, network: first.network });
settingsFilled = false; render();
@@ -2869,7 +2937,7 @@ function render() {
if (!ready && !fullLock) {
const copy = {
error: ["⚠", "This wallet could not start.", s?.error || ""],
- empty: ["🛡", "No wallets yet.", "Aegis derives every wallet from your Theseus password vault — there's no separate seed to import. Pick a coin below to create your first one."],
+ empty: ["🛡", "No wallets yet.", "Aegis can derive a fresh wallet from your Theseus password vault — nothing extra to write down — or import one you already have from its seed phrase or private key."],
}[phase] || ["…", "Starting…", ""];
let form = "";
if (phase === "empty") {
@@ -2880,7 +2948,11 @@ function render() {
const btn = $("gateAddWallet");
if (btn) btn.addEventListener("click", () => {
const d = $("drop");
- pickerTab = "add";
+ // First-run is the MOST important place to offer import: someone
+ // arriving with an existing seed who is handed a create-only flow
+ // ends up staring at an empty wallet wondering where their coins
+ // went. Method chooser, not straight to create.
+ pickerTab = "method";
d.hidden = false;
fillPicker();
});