wallet-inject.js runs in the isolated world of https://*.x pages and exposes window.bitcoincash { isTheseus, version, network, getAddress, signAndSend, signMessage }. Every call is routed page -> addon-page-msg -> activate() handler -> approval overlay showing the requesting origin: - getAddress: approval with an "always allow" checkbox; grants persist in api.storage.permissions and are listed/revocable under Settings. - signAndSend / signMessage: approval on every call, never remembered. signMessage returns a BIP-137 recoverable signature (verified offline). - one pending approval per origin; page-facing errors never echo balance. Host fix: the inject IPC assigned event.returnValue twice, so pages always got an empty script list.
28 lines
1.4 KiB
JavaScript
28 lines
1.4 KiB
JavaScript
// Dapp bridge, run by Theseus in the isolated world of every tab whose URL
|
|
// matches addon.json "page-inject".origins. Exposes window.bitcoincash to the
|
|
// page. Every call crosses into the wallet's activate() context in main,
|
|
// which shows the approval overlay and enforces per-origin permissions —
|
|
// nothing here can sign or read anything on its own.
|
|
//
|
|
// `theseus` is provided by the host: { id, origin, contextBridge, invoke }.
|
|
const call = (msg, payload) =>
|
|
theseus.invoke(msg, payload).catch((e) => {
|
|
// Strip Electron's IPC wrapper so the page sees the wallet's own message.
|
|
const text = String(e && e.message || e).replace(/^Error invoking remote method '[^']+': (Error: )?/, "");
|
|
throw new Error(text);
|
|
});
|
|
|
|
theseus.contextBridge.exposeInMainWorld("bitcoincash", {
|
|
isTheseus: true,
|
|
version: "0.1.0",
|
|
network: "mainnet",
|
|
// Current receiving address (cashaddr). First call per origin asks the
|
|
// user; "always allow" makes later calls silent.
|
|
getAddress: () => call("getAddress"),
|
|
// txSpec: { to, amount } (sats) or { outputs: [{ to, amount }], feeRate }.
|
|
// Always approval-gated; resolves { txid }.
|
|
signAndSend: (txSpec) => call("signAndSend", txSpec && typeof txSpec === "object" ? txSpec : {}),
|
|
// BIP-137 signature over the message with the current address's key.
|
|
// Always approval-gated; resolves { address, signature (base64) }.
|
|
signMessage: (message) => call("signMessage", { message: String(message ?? "") }),
|
|
});
|