${dot}` +
+ const knownToken = TOKEN_BY_ADDRESS.get(tokenId.toLowerCase());
+ const projectUrl = knownToken && knownToken.url ? knownToken.url : null;
+ let infoHtml = `
Contract Address
`;
+ infoHtml +=
+ `
`;
- const details = [];
if (tokenName)
- details.push(`
Name: ${tokenName}`);
+ infoHtml += `
Name: ${tokenName}
`;
if (tokenSymbol)
- details.push(
- `
Symbol: ${tokenSymbol}`,
- );
+ infoHtml += `
Symbol: ${tokenSymbol}
`;
if (tokenDecimals != null)
- details.push(
- `
Decimals: ${tokenDecimals}`,
- );
+ infoHtml += `
Decimals: ${tokenDecimals}
`;
if (tokenHolders != null)
- details.push(
- `
Holders: ${Number(tokenHolders).toLocaleString()}`,
- );
- if (details.length > 0) {
- infoHtml += `
${details.join("")}
`;
- }
+ infoHtml += `
Holders: ${Number(tokenHolders).toLocaleString()}
`;
+ if (projectUrl)
+ infoHtml += `
`;
contractInfo.innerHTML = infoHtml;
contractInfo.classList.remove("hidden");
} else {
diff --git a/src/popup/views/deleteWallet.js b/src/popup/views/deleteWallet.js
new file mode 100644
index 0000000..49e47bf
--- /dev/null
+++ b/src/popup/views/deleteWallet.js
@@ -0,0 +1,90 @@
+const { $, showView, showFlash } = require("./helpers");
+const { state, saveState } = require("../../shared/state");
+const { decryptWithPassword } = require("../../shared/vault");
+
+let deleteWalletIndex = null;
+let ctx = null;
+
+function show(walletIdx) {
+ deleteWalletIndex = walletIdx;
+ const wallet = state.wallets[walletIdx];
+ $("delete-wallet-name").textContent =
+ wallet.name || "Wallet " + (walletIdx + 1);
+ $("delete-wallet-password").value = "";
+ $("delete-wallet-flash").textContent = "";
+ $("delete-wallet-flash").classList.add("hidden");
+ showView("delete-wallet-confirm");
+}
+
+function init(_ctx) {
+ ctx = _ctx;
+
+ $("btn-delete-wallet-back").addEventListener("click", () => {
+ deleteWalletIndex = null;
+ ctx.showSettingsView();
+ });
+
+ $("btn-delete-wallet-confirm").addEventListener("click", async () => {
+ const pw = $("delete-wallet-password").value;
+ if (!pw) {
+ $("delete-wallet-flash").textContent =
+ "Please enter your password.";
+ $("delete-wallet-flash").classList.remove("hidden");
+ return;
+ }
+
+ if (deleteWalletIndex === null) {
+ $("delete-wallet-flash").textContent =
+ "No wallet selected for deletion.";
+ $("delete-wallet-flash").classList.remove("hidden");
+ return;
+ }
+
+ const walletIdx = deleteWalletIndex;
+ const wallet = state.wallets[walletIdx];
+
+ // Verify password against the wallet's encrypted data
+ try {
+ await decryptWithPassword(wallet.encryptedSecret, pw);
+ } catch (_e) {
+ $("delete-wallet-flash").textContent = "Wrong password.";
+ $("delete-wallet-flash").classList.remove("hidden");
+ return;
+ }
+
+ // Collect addresses to clean up from allowedSites/deniedSites
+ const addresses = (wallet.addresses || []).map((a) => a.address);
+
+ // Remove wallet
+ state.wallets.splice(walletIdx, 1);
+
+ // Clean up site permissions for deleted addresses
+ for (const addr of addresses) {
+ delete state.allowedSites[addr];
+ delete state.deniedSites[addr];
+ }
+
+ deleteWalletIndex = null;
+
+ if (state.wallets.length === 0) {
+ // No wallets left — reset selection and show welcome
+ state.selectedWallet = null;
+ state.selectedAddress = null;
+ state.activeAddress = null;
+ await saveState();
+ showView("welcome");
+ } else {
+ // Switch to first wallet if deleted wallet was active
+ state.selectedWallet = 0;
+ state.selectedAddress = 0;
+ state.activeAddress =
+ state.wallets[0].addresses[0]?.address || null;
+ await saveState();
+ ctx.renderWalletList();
+ ctx.showSettingsView();
+ showFlash("Wallet deleted.");
+ }
+ });
+}
+
+module.exports = { init, show };
diff --git a/src/popup/views/helpers.js b/src/popup/views/helpers.js
index 5d9daa8..e5b71d0 100644
--- a/src/popup/views/helpers.js
+++ b/src/popup/views/helpers.js
@@ -25,6 +25,7 @@ const VIEWS = [
"receive",
"add-token",
"settings",
+ "delete-wallet-confirm",
"settings-addtoken",
"transaction",
"approve-site",
diff --git a/src/popup/views/settings.js b/src/popup/views/settings.js
index 8562b96..ea67337 100644
--- a/src/popup/views/settings.js
+++ b/src/popup/views/settings.js
@@ -2,6 +2,7 @@ const { $, showView, showFlash, escapeHtml } = require("./helpers");
const { state, saveState } = require("../../shared/state");
const { ETHEREUM_MAINNET_CHAIN_ID } = require("../../shared/constants");
const { log, debugFetch } = require("../../shared/log");
+const deleteWallet = require("./deleteWallet");
const runtime =
typeof browser !== "undefined" ? browser.runtime : chrome.runtime;
@@ -65,11 +66,68 @@ function renderTrackedTokens() {
});
}
+function renderWalletListSettings() {
+ const container = $("settings-wallet-list");
+ if (state.wallets.length === 0) {
+ container.innerHTML = '
No wallets.
';
+ return;
+ }
+ let html = "";
+ state.wallets.forEach((wallet, idx) => {
+ const name = escapeHtml(wallet.name || "Wallet " + (idx + 1));
+ html += `
`;
+ html += `${name}`;
+ html += ``;
+ html += `
`;
+ });
+ container.innerHTML = html;
+ container.querySelectorAll(".btn-delete-wallet").forEach((btn) => {
+ btn.addEventListener("click", () => {
+ const idx = parseInt(btn.dataset.idx, 10);
+ deleteWallet.show(idx);
+ });
+ });
+
+ // Inline rename on click
+ container.querySelectorAll(".settings-wallet-name").forEach((span) => {
+ span.addEventListener("click", () => {
+ const idx = parseInt(span.dataset.idx, 10);
+ const wallet = state.wallets[idx];
+ const input = document.createElement("input");
+ input.type = "text";
+ input.className =
+ "border border-border p-0 text-xs bg-bg text-fg w-full";
+ input.value = wallet.name || "Wallet " + (idx + 1);
+ span.replaceWith(input);
+ input.focus();
+ input.select();
+ const finish = async () => {
+ const val = input.value.trim();
+ if (val && val !== wallet.name) {
+ wallet.name = val;
+ await saveState();
+ }
+ renderWalletListSettings();
+ };
+ input.addEventListener("blur", finish);
+ input.addEventListener("keydown", (e) => {
+ if (e.key === "Enter") input.blur();
+ if (e.key === "Escape") {
+ input.value = wallet.name || "Wallet " + (idx + 1);
+ input.blur();
+ }
+ });
+ });
+ });
+}
+
function show() {
$("settings-rpc").value = state.rpcUrl;
$("settings-blockscout").value = state.blockscoutUrl;
renderTrackedTokens();
renderSiteLists();
+ renderWalletListSettings();
+
showView("settings");
}
@@ -83,6 +141,8 @@ function renderSiteLists() {
}
function init(ctx) {
+ deleteWallet.init(ctx);
+
$("btn-save-rpc").addEventListener("click", async () => {
const url = $("settings-rpc").value.trim();
if (!url) {