Compare commits

...

3 Commits

Author SHA1 Message Date
65cb4d2f64 fix: add fallback popup window for tx and sign approval requests (closes #4)
All checks were successful
check / check (push) Successful in 22s
requestTxApproval and requestSignApproval were missing the
openApprovalWindow fallback that requestApproval (connection
requests) already had. When chrome.action.openPopup() fails
(which it does when not triggered by a user gesture in MV3),
no popup appeared — the user had to manually click the toolbar
icon to find the confirmation screen.

Now all three approval types use the same pattern: try
openPopup() first, fall back to a centered standalone window.
2026-02-27 12:54:25 -08:00
4eefe4c1af Merge pull request 'fix: pass UUID approval ID as string, not parseInt (closes #4)' (#18) from fix/approval-popup-uuid into main
All checks were successful
check / check (push) Successful in 8s
Reviewed-on: #18
2026-02-27 21:50:27 +01:00
8b7d73cc35 fix: pass UUID approval ID as string, not parseInt (closes #4)
All checks were successful
check / check (push) Successful in 22s
The approval ID was changed from sequential integers to crypto.randomUUID()
strings for security, but the popup still called parseInt() on it, which
converted the UUID to NaN. This caused every approval lookup to fail,
preventing the confirmation popup from displaying pending tx/sign requests.
2026-02-27 12:34:23 -08:00
2 changed files with 13 additions and 14 deletions

View File

@@ -148,7 +148,7 @@ function requestApproval(origin, hostname) {
}
// Open a tx-approval popup and return a promise that resolves with txHash or error.
// Uses the toolbar popup only — no fallback window.
// Tries the toolbar popup first, falls back to a standalone window.
function requestTxApproval(origin, hostname, txParams) {
return new Promise((resolve) => {
const id = crypto.randomUUID();
@@ -160,27 +160,26 @@ function requestTxApproval(origin, hostname, txParams) {
type: "tx",
};
if (actionApi && typeof actionApi.setPopup === "function") {
if (actionApi && typeof actionApi.openPopup === "function") {
actionApi.setPopup({
popup: "src/popup/index.html?approval=" + id,
});
}
if (actionApi && typeof actionApi.openPopup === "function") {
try {
const result = actionApi.openPopup();
if (result && typeof result.catch === "function") {
result.catch(() => {});
result.catch(() => openApprovalWindow(id));
}
} catch {
// openPopup unsupported — user clicks toolbar icon
openApprovalWindow(id);
}
} else {
openApprovalWindow(id);
}
});
}
// Open a sign-approval popup and return a promise that resolves with { signature } or { error }.
// Uses the toolbar popup only — no fallback window. If openPopup() fails the
// popup URL is still set, so the user can click the toolbar icon to respond.
// Tries the toolbar popup first, falls back to a standalone window.
function requestSignApproval(origin, hostname, signParams) {
return new Promise((resolve) => {
const id = crypto.randomUUID();
@@ -192,20 +191,20 @@ function requestSignApproval(origin, hostname, signParams) {
type: "sign",
};
if (actionApi && typeof actionApi.setPopup === "function") {
if (actionApi && typeof actionApi.openPopup === "function") {
actionApi.setPopup({
popup: "src/popup/index.html?approval=" + id,
});
}
if (actionApi && typeof actionApi.openPopup === "function") {
try {
const result = actionApi.openPopup();
if (result && typeof result.catch === "function") {
result.catch(() => {});
result.catch(() => openApprovalWindow(id));
}
} catch {
// openPopup unsupported — user clicks toolbar icon
openApprovalWindow(id);
}
} else {
openApprovalWindow(id);
}
});
}

View File

@@ -189,7 +189,7 @@ async function init() {
const params = new URLSearchParams(window.location.search);
const approvalId = params.get("approval");
if (approvalId) {
approval.show(parseInt(approvalId, 10));
approval.show(approvalId);
showView("approve-site");
return;
}