diff --git a/bundled-addons/bchwallet/index.js b/bundled-addons/bchwallet/index.js index d0970fd..cfb221b 100644 --- a/bundled-addons/bchwallet/index.js +++ b/bundled-addons/bchwallet/index.js @@ -93,6 +93,20 @@ async function deriveAndStart() { catch (e) { setPhase("error", e?.message || String(e)); c.api.log("wallet build failed:", e?.message); } } +const fmtBch = (sats) => (Number(sats) / 1e8).toFixed(8).replace(/(\.\d*?[1-9])0+$|\.0+$/, "$1"); +function planFrom(p) { + const c = requireReady(); + const spec = p || {}; + const targets = Array.isArray(spec.outputs) && spec.outputs.length + ? spec.outputs.map((o) => ({ to: o.to, value: o.amount ?? o.value })) + : [{ to: spec.to, value: spec.amount ?? spec.value }]; + return c.wallet.plan({ targets, feeRate: spec.feeRate, sendMax: !!spec.sendMax }); +} +function describePlan(plan) { + const sent = plan.recipients.reduce((a, r) => a + r.value, 0); + return { recipients: plan.recipients, fee: plan.fee, feeRate: plan.feeRate, inputs: plan.inputs.length, change: plan.change, total: sent + plan.fee }; +} + function requireReady() { if (!ctx || ctx.phase !== "ready" || !ctx.wallet) throw new Error("wallet is not ready (vault locked?)"); return ctx; @@ -120,6 +134,28 @@ function registerPanelMessages(api) { if (ctx && ctx.root) buildWallet(); return snapshot(); }); + // Send preview — no side effects, used for the live fee/total summary. + api.onMessage("planSend", (p, m) => { fromPanel(m); return describePlan(planFrom(p)); }); + // Send for real: plan -> approval overlay -> sign -> broadcast. + api.onMessage("send", async (p, m) => { + fromPanel(m); + const c = requireReady(); + const plan = planFrom(p); + const d = describePlan(plan); + const pick = await api.approvalModal({ + title: "Send Bitcoin Cash?", + origin: "Theseus wallet panel", + rows: [ + { label: "To", value: d.recipients[0].to, mono: true }, + { label: "Amount", value: fmtBch(d.recipients[0].value) + " BCH", strong: true }, + { label: "Fee", value: `${d.fee} sat (${d.feeRate} sat/B)` }, + { label: "Total", value: fmtBch(d.total) + " BCH" }, + ], + actions: [{ id: "send", label: "Send", primary: true }], + }); + if (pick !== "send") throw new Error("cancelled"); + return c.wallet.signAndBroadcast(plan); + }); // Recovery info: xpub always; the account xprv only after an explicit // confirmation in the approval overlay. Import the xprv into any BIP32 // wallet (branch 0 receive / 1 change) to move funds without Theseus. diff --git a/bundled-addons/bchwallet/panel.html b/bundled-addons/bchwallet/panel.html index 7a6044c..39028b7 100644 --- a/bundled-addons/bchwallet/panel.html +++ b/bundled-addons/bchwallet/panel.html @@ -120,7 +120,32 @@