diff --git a/addon.json b/addon.json index 7c8edf0..59cfa0c 100644 --- a/addon.json +++ b/addon.json @@ -1,14 +1,14 @@ { "id": "aegis", "name": "Aegis Wallet", - "version": "0.8.9", + "version": "0.9.0", "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", "icon": "data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' fill='none'%3E%3Cpolygon points='16,2 28,9 28,23 16,30 4,23 4,9' fill='%230a0a0d' stroke='%23D6FF3D' stroke-width='1.6' stroke-linejoin='round'/%3E%3Ccircle cx='16' cy='16' r='4.5' fill='none' stroke='%23D6FF3D' stroke-width='1.4'/%3E%3Ccircle cx='16' cy='16' r='1.6' fill='%23D6FF3D'/%3E%3C/svg%3E", "main": "index.js", "updateURL": "https://navigate.st/bns/theseus.x/extensions/aegis/updates.json", - "capabilities": ["sidebar-panel", "vault-derive", "page-inject", "approval-modal"], + "capabilities": ["sidebar-panel", "vault-derive", "page-inject", "approval-modal", "scan-page"], "absorbs": ["bchwallet", "siawallet"], "page-inject": { "preload": "wallet-inject.js", diff --git a/index.js b/index.js index c6ca833..002e684 100644 --- a/index.js +++ b/index.js @@ -1585,6 +1585,20 @@ function registerPanelMessages(api) { return fullState(); }); + // Scan the open dapp tab for a wiz:// pairing code, for dapps that render + // one but haven't adopted window.wizardconnect. Strictly user-initiated — + // it runs when someone presses "Scan page", never on a timer and never in + // the background. The host does the matching and returns only the URIs, so + // Aegis never receives page content. + api.onMessage("wcScanPage", async (_p, m) => { + fromPanel(m); + if (typeof api.scanActiveTabForUris !== "function") { + throw new Error("This Theseus build can't scan pages yet — update Theseus, or paste the wiz:// code manually."); + } + const { origin, uris } = await api.scanActiveTabForUris({ scheme: "wiz", limit: 10 }); + return { origin: origin || null, uris: Array.isArray(uris) ? uris : [] }; + }); + // ---- WizardConnect from the page (0.8.8) -------------------------------- // // WC was built for cross-device pairing: the dapp renders a QR, a phone diff --git a/panel.js b/panel.js index 6df3079..cdb5f42 100644 --- a/panel.js +++ b/panel.js @@ -1892,7 +1892,7 @@ function renderConnectPane(bchWallets) { `).join("") : `
No dapps paired yet.
`; return `
-
Dapps that support Aegis directly can hand the pairing over with one click — no copying. Otherwise paste a wiz:// URI from the dapp's Connect dialog. Aegis signs every request after your approval.
+
Dapps that support Aegis hand the pairing over with one click. Otherwise open the dapp's Connect dialog and press Scan page, or paste its wiz:// code below. Aegis signs every request after your approval.
${blockedNote}
Sign with
@@ -1901,8 +1901,9 @@ function renderConnectPane(bchWallets) {
-
+
+
Paired dapps
@@ -1948,6 +1949,41 @@ function wireConnectPane() { fillPicker(); } catch (e) { msg.textContent = cleanErr(e); msg.hidden = false; } }); + const scanBtn = document.getElementById("pkConnectScanBtn"); + if (scanBtn) scanBtn.addEventListener("click", async (e) => { + e.stopPropagation(); + const msg = document.getElementById("pkConnectMsg"); msg.hidden = true; + const field = document.getElementById("pkConnectUri"); + const prev = scanBtn.textContent; + scanBtn.textContent = "Scanning…"; scanBtn.disabled = true; + try { + const res = await S.invoke("wcScanPage"); + const uris = res?.uris || []; + if (!uris.length) { + msg.textContent = res?.origin + ? `No wiz:// pairing code found on ${res.origin}. Open the dapp's Connect dialog first, then scan again.` + : "No pairing code found on the open tab."; + msg.hidden = false; + return; + } + // Fill the field rather than pairing outright: the user still picks + // which wallet signs, and still presses Connect. A scan that silently + // paired would be a click with a much larger consequence than the + // button implies. + field.value = uris[0]; + msg.textContent = uris.length > 1 + ? `Found ${uris.length} codes on ${res.origin || "the page"} — filled the first. Press Connect to pair.` + : `Found a pairing code on ${res.origin || "the page"}. Press Connect to pair.`; + msg.classList.remove("err"); + msg.hidden = false; + } catch (err) { + msg.textContent = cleanErr(err); + msg.classList.add("err"); + msg.hidden = false; + } finally { + scanBtn.textContent = prev; scanBtn.disabled = false; + } + }); document.querySelectorAll("[data-wcpick]").forEach((b) => b.addEventListener("click", async () => { const [walletId, connId] = b.dataset.wcpick.split("|"); try { state = await S.invoke("wcDisconnect", { walletId, connId }); fillPicker(); }