Compare commits
1 Commits
a655c546b7
...
fix/70-con
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc4e78c466 |
@@ -305,26 +305,6 @@
|
|||||||
>
|
>
|
||||||
+ Token
|
+ Token
|
||||||
</button>
|
</button>
|
||||||
<div class="relative">
|
|
||||||
<button
|
|
||||||
id="btn-more-menu"
|
|
||||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
||||||
aria-label="More actions"
|
|
||||||
>
|
|
||||||
···
|
|
||||||
</button>
|
|
||||||
<div
|
|
||||||
id="more-menu-dropdown"
|
|
||||||
class="hidden absolute right-0 top-full mt-1 border border-border bg-bg z-50 whitespace-nowrap py-1"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
id="btn-export-privkey"
|
|
||||||
class="block w-full text-left px-4 py-1.5 text-xs font-light text-muted hover:bg-hover hover:text-fg cursor-pointer"
|
|
||||||
>
|
|
||||||
Export Private Key
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- transactions -->
|
<!-- transactions -->
|
||||||
@@ -338,60 +318,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ============ EXPORT PRIVATE KEY VIEW ============ -->
|
|
||||||
<div id="view-export-privkey" class="view hidden">
|
|
||||||
<button
|
|
||||||
id="btn-export-privkey-back"
|
|
||||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer mb-2"
|
|
||||||
>
|
|
||||||
< Back
|
|
||||||
</button>
|
|
||||||
<div
|
|
||||||
id="export-privkey-jazzicon"
|
|
||||||
class="flex justify-center mt-1 mb-3"
|
|
||||||
></div>
|
|
||||||
<h2 class="font-bold mb-1">Export Private Key</h2>
|
|
||||||
<p class="text-xs mb-1" id="export-privkey-title"></p>
|
|
||||||
<p class="text-xs mb-3">
|
|
||||||
<span id="export-privkey-dot"></span>
|
|
||||||
<span
|
|
||||||
id="export-privkey-address"
|
|
||||||
class="cursor-pointer"
|
|
||||||
title="Click to copy"
|
|
||||||
></span>
|
|
||||||
</p>
|
|
||||||
<p class="text-xs mb-3 text-muted">
|
|
||||||
Warning: anyone with this private key can access and
|
|
||||||
transfer all funds from this address. Never share it.
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
id="export-privkey-flash"
|
|
||||||
class="text-xs mb-2 hidden"
|
|
||||||
></div>
|
|
||||||
<div id="export-privkey-password-section" class="mb-2">
|
|
||||||
<label class="block mb-1">Password</label>
|
|
||||||
<input
|
|
||||||
type="password"
|
|
||||||
id="export-privkey-password"
|
|
||||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
|
||||||
placeholder="Enter your password to continue"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
id="btn-export-privkey-confirm"
|
|
||||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer mt-2"
|
|
||||||
>
|
|
||||||
Reveal
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div id="export-privkey-result" class="hidden">
|
|
||||||
<div
|
|
||||||
id="export-privkey-value"
|
|
||||||
class="bg-danger-well rounded p-2 font-mono text-xs break-all cursor-pointer mb-1"
|
|
||||||
title="Click to copy"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ============ ADDRESS-TOKEN DETAIL VIEW ============ -->
|
<!-- ============ ADDRESS-TOKEN DETAIL VIEW ============ -->
|
||||||
<div id="view-address-token" class="view hidden">
|
<div id="view-address-token" class="view hidden">
|
||||||
<button
|
<button
|
||||||
@@ -537,12 +463,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ERC-20 token contract (hidden for ETH) -->
|
<!-- ERC-20 token contract (hidden for ETH) -->
|
||||||
<div id="confirm-token-section" class="mb-3 hidden">
|
<div
|
||||||
<div class="text-xs text-muted mb-1">Token contract</div>
|
id="confirm-token-section"
|
||||||
<div
|
class="bg-hover rounded-md mx-1 p-3 mb-3 text-xs hidden"
|
||||||
id="confirm-token-contract"
|
>
|
||||||
class="text-xs break-all"
|
<div class="font-bold mb-2">Token Contract</div>
|
||||||
></div>
|
<div id="confirm-token-contract" class="break-all"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
--color-border-light: #cccccc;
|
--color-border-light: #cccccc;
|
||||||
--color-hover: #eeeeee;
|
--color-hover: #eeeeee;
|
||||||
--color-well: #f5f5f5;
|
--color-well: #f5f5f5;
|
||||||
--color-danger-well: #fef2f2;
|
|
||||||
--color-section: #dddddd;
|
--color-section: #dddddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ const { resolveEnsNames } = require("../../shared/ens");
|
|||||||
const { updateSendBalance, renderSendTokenSelect } = require("./send");
|
const { updateSendBalance, renderSendTokenSelect } = require("./send");
|
||||||
const { log } = require("../../shared/log");
|
const { log } = require("../../shared/log");
|
||||||
const makeBlockie = require("ethereum-blockies-base64");
|
const makeBlockie = require("ethereum-blockies-base64");
|
||||||
const { decryptWithPassword } = require("../../shared/vault");
|
|
||||||
const { getSignerForAddress } = require("../../shared/wallet");
|
|
||||||
|
|
||||||
let ctx;
|
let ctx;
|
||||||
|
|
||||||
@@ -267,102 +265,6 @@ function init(_ctx) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$("btn-add-token").addEventListener("click", ctx.showAddTokenView);
|
$("btn-add-token").addEventListener("click", ctx.showAddTokenView);
|
||||||
|
|
||||||
// More menu dropdown
|
|
||||||
const moreBtn = $("btn-more-menu");
|
|
||||||
const moreDropdown = $("more-menu-dropdown");
|
|
||||||
moreBtn.addEventListener("click", (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
const isOpen = !moreDropdown.classList.toggle("hidden");
|
|
||||||
moreBtn.classList.toggle("bg-fg", isOpen);
|
|
||||||
moreBtn.classList.toggle("text-bg", isOpen);
|
|
||||||
});
|
|
||||||
document.addEventListener("click", () => {
|
|
||||||
moreDropdown.classList.add("hidden");
|
|
||||||
moreBtn.classList.remove("bg-fg", "text-bg");
|
|
||||||
});
|
|
||||||
moreDropdown.addEventListener("click", (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
});
|
|
||||||
|
|
||||||
$("btn-export-privkey").addEventListener("click", () => {
|
|
||||||
moreDropdown.classList.add("hidden");
|
|
||||||
moreBtn.classList.remove("bg-fg", "text-bg");
|
|
||||||
const wallet = state.wallets[state.selectedWallet];
|
|
||||||
const addr = wallet.addresses[state.selectedAddress];
|
|
||||||
const blockieEl = $("export-privkey-jazzicon");
|
|
||||||
blockieEl.innerHTML = "";
|
|
||||||
const bImg = document.createElement("img");
|
|
||||||
bImg.src = makeBlockie(addr.address);
|
|
||||||
bImg.width = 48;
|
|
||||||
bImg.height = 48;
|
|
||||||
bImg.style.imageRendering = "pixelated";
|
|
||||||
bImg.style.borderRadius = "50%";
|
|
||||||
blockieEl.appendChild(bImg);
|
|
||||||
$("export-privkey-title").textContent =
|
|
||||||
wallet.name + " \u2014 Address " + (state.selectedAddress + 1);
|
|
||||||
$("export-privkey-dot").innerHTML = addressDotHtml(addr.address);
|
|
||||||
$("export-privkey-address").textContent = addr.address;
|
|
||||||
$("export-privkey-address").dataset.full = addr.address;
|
|
||||||
$("export-privkey-password").value = "";
|
|
||||||
$("export-privkey-flash").classList.add("hidden");
|
|
||||||
$("export-privkey-flash").textContent = "";
|
|
||||||
$("export-privkey-password-section").classList.remove("hidden");
|
|
||||||
$("export-privkey-result").classList.add("hidden");
|
|
||||||
$("export-privkey-value").textContent = "";
|
|
||||||
showView("export-privkey");
|
|
||||||
});
|
|
||||||
|
|
||||||
$("btn-export-privkey-confirm").addEventListener("click", async () => {
|
|
||||||
const password = $("export-privkey-password").value;
|
|
||||||
if (!password) {
|
|
||||||
$("export-privkey-flash").textContent = "Password is required.";
|
|
||||||
$("export-privkey-flash").classList.remove("hidden");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const wallet = state.wallets[state.selectedWallet];
|
|
||||||
try {
|
|
||||||
const secret = await decryptWithPassword(
|
|
||||||
wallet.encryptedSecret,
|
|
||||||
password,
|
|
||||||
);
|
|
||||||
const signer = getSignerForAddress(
|
|
||||||
wallet,
|
|
||||||
state.selectedAddress,
|
|
||||||
secret,
|
|
||||||
);
|
|
||||||
const privateKey = signer.privateKey;
|
|
||||||
$("export-privkey-password-section").classList.add("hidden");
|
|
||||||
$("export-privkey-value").textContent = privateKey;
|
|
||||||
$("export-privkey-result").classList.remove("hidden");
|
|
||||||
$("export-privkey-flash").classList.add("hidden");
|
|
||||||
} catch {
|
|
||||||
$("export-privkey-flash").textContent = "Wrong password.";
|
|
||||||
$("export-privkey-flash").classList.remove("hidden");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$("export-privkey-value").addEventListener("click", () => {
|
|
||||||
const key = $("export-privkey-value").textContent;
|
|
||||||
if (key) {
|
|
||||||
navigator.clipboard.writeText(key);
|
|
||||||
showFlash("Copied!");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$("export-privkey-address").addEventListener("click", () => {
|
|
||||||
const full = $("export-privkey-address").dataset.full;
|
|
||||||
if (full) {
|
|
||||||
navigator.clipboard.writeText(full);
|
|
||||||
showFlash("Copied!");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$("btn-export-privkey-back").addEventListener("click", () => {
|
|
||||||
$("export-privkey-value").textContent = "";
|
|
||||||
$("export-privkey-password").value = "";
|
|
||||||
show();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { init, show };
|
module.exports = { init, show };
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ const {
|
|||||||
showError,
|
showError,
|
||||||
hideError,
|
hideError,
|
||||||
showView,
|
showView,
|
||||||
showFlash,
|
|
||||||
addressTitle,
|
addressTitle,
|
||||||
addressDotHtml,
|
addressDotHtml,
|
||||||
escapeHtml,
|
escapeHtml,
|
||||||
@@ -99,19 +98,20 @@ function show(txInfo) {
|
|||||||
const dot = addressDotHtml(txInfo.token);
|
const dot = addressDotHtml(txInfo.token);
|
||||||
const link = etherscanTokenLink(txInfo.token);
|
const link = etherscanTokenLink(txInfo.token);
|
||||||
$("confirm-token-contract").innerHTML =
|
$("confirm-token-contract").innerHTML =
|
||||||
`<div class="flex items-center">${dot}` +
|
`<div class="flex items-center">` +
|
||||||
`<span class="break-all underline decoration-dashed cursor-pointer" data-copy="${escapeHtml(txInfo.token)}">${escapeHtml(txInfo.token)}</span>` +
|
dot +
|
||||||
|
`<span class="break-all underline decoration-dashed cursor-pointer" id="confirm-token-contract-copy" data-copy="${escapeHtml(txInfo.token)}">${escapeHtml(txInfo.token)}</span>` +
|
||||||
`<a href="${link}" target="_blank" rel="noopener" class="inline-flex items-center">${EXT_ICON}</a>` +
|
`<a href="${link}" target="_blank" rel="noopener" class="inline-flex items-center">${EXT_ICON}</a>` +
|
||||||
`</div>`;
|
`</div>`;
|
||||||
tokenSection.classList.remove("hidden");
|
if (txInfo.tokenName) {
|
||||||
// Attach click-to-copy on the contract address
|
$("confirm-token-contract").innerHTML +=
|
||||||
const copyEl = tokenSection.querySelector("[data-copy]");
|
`<div class="mt-1"><span class="text-muted">Name:</span> ${escapeHtml(txInfo.tokenName)}</div>`;
|
||||||
if (copyEl) {
|
|
||||||
copyEl.onclick = () => {
|
|
||||||
navigator.clipboard.writeText(copyEl.dataset.copy);
|
|
||||||
showFlash("Copied!");
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
if (txInfo.tokenSymbol) {
|
||||||
|
$("confirm-token-contract").innerHTML +=
|
||||||
|
`<div class="mt-1"><span class="text-muted">Symbol:</span> ${escapeHtml(txInfo.tokenSymbol)}</div>`;
|
||||||
|
}
|
||||||
|
tokenSection.classList.remove("hidden");
|
||||||
} else {
|
} else {
|
||||||
tokenSection.classList.add("hidden");
|
tokenSection.classList.add("hidden");
|
||||||
}
|
}
|
||||||
@@ -285,6 +285,13 @@ function hidePasswordModal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function init(ctx) {
|
function init(ctx) {
|
||||||
|
$("confirm-token-section").addEventListener("click", (e) => {
|
||||||
|
const copyEl = e.target.closest("[data-copy]");
|
||||||
|
if (copyEl) {
|
||||||
|
navigator.clipboard.writeText(copyEl.dataset.copy);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$("btn-confirm-send").addEventListener("click", () => {
|
$("btn-confirm-send").addEventListener("click", () => {
|
||||||
showPasswordModal();
|
showPasswordModal();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ const VIEWS = [
|
|||||||
"approve-site",
|
"approve-site",
|
||||||
"approve-tx",
|
"approve-tx",
|
||||||
"approve-sign",
|
"approve-sign",
|
||||||
"export-privkey",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
function $(id) {
|
function $(id) {
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ const {
|
|||||||
const { state, currentAddress } = require("../../shared/state");
|
const { state, currentAddress } = require("../../shared/state");
|
||||||
let ctx;
|
let ctx;
|
||||||
const { getProvider } = require("../../shared/balances");
|
const { getProvider } = require("../../shared/balances");
|
||||||
const { KNOWN_SYMBOLS, resolveSymbol } = require("../../shared/tokenList");
|
const {
|
||||||
|
KNOWN_SYMBOLS,
|
||||||
|
TOKEN_BY_ADDRESS,
|
||||||
|
resolveSymbol,
|
||||||
|
} = require("../../shared/tokenList");
|
||||||
|
|
||||||
const EXT_ICON =
|
const EXT_ICON =
|
||||||
`<span style="display:inline-block;width:10px;height:10px;margin-left:4px;vertical-align:middle">` +
|
`<span style="display:inline-block;width:10px;height:10px;margin-left:4px;vertical-align:middle">` +
|
||||||
@@ -124,6 +128,7 @@ function init(_ctx) {
|
|||||||
|
|
||||||
let tokenSymbol = null;
|
let tokenSymbol = null;
|
||||||
let tokenBalance = null;
|
let tokenBalance = null;
|
||||||
|
let tokenName = null;
|
||||||
if (token !== "ETH") {
|
if (token !== "ETH") {
|
||||||
const tb = (addr.tokenBalances || []).find(
|
const tb = (addr.tokenBalances || []).find(
|
||||||
(t) => t.address.toLowerCase() === token.toLowerCase(),
|
(t) => t.address.toLowerCase() === token.toLowerCase(),
|
||||||
@@ -134,6 +139,17 @@ function init(_ctx) {
|
|||||||
state.trackedTokens,
|
state.trackedTokens,
|
||||||
);
|
);
|
||||||
tokenBalance = tb ? tb.balance || "0" : "0";
|
tokenBalance = tb ? tb.balance || "0" : "0";
|
||||||
|
// Resolve token name from balances, tracked tokens, or known list
|
||||||
|
const lower = token.toLowerCase();
|
||||||
|
tokenName =
|
||||||
|
(tb && tb.name) ||
|
||||||
|
(
|
||||||
|
(state.trackedTokens || []).find(
|
||||||
|
(t) => t.address.toLowerCase() === lower,
|
||||||
|
) || {}
|
||||||
|
).name ||
|
||||||
|
(TOKEN_BY_ADDRESS.get(lower) || {}).name ||
|
||||||
|
null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.showConfirmTx({
|
ctx.showConfirmTx({
|
||||||
@@ -145,6 +161,7 @@ function init(_ctx) {
|
|||||||
balance: addr.balance,
|
balance: addr.balance,
|
||||||
tokenSymbol: tokenSymbol,
|
tokenSymbol: tokenSymbol,
|
||||||
tokenBalance: tokenBalance,
|
tokenBalance: tokenBalance,
|
||||||
|
tokenName: tokenName,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user