Token auto-discovery, tx history, balance polling, EIP-6963, UI overhaul
All checks were successful
check / check (push) Successful in 14s
All checks were successful
check / check (push) Successful in 14s
Major changes: - Fetch token balances and tx history from Blockscout API (configurable) - Remove manual token discovery (discoverTokens) in favor of Blockscout - HD address gap scanning on mnemonic import - Duplicate mnemonic detection on wallet add - EIP-6963 multi-wallet discovery + selectedAddress updates in inpage - Two-tier balance refresh: 10s while popup open, 60s background - Fix $0.00 flash before prices load (return null when no prices) - No-layout-shift: min-height on total value element - Aligned balance columns (42ch address width, consistent USD column) - All errors use flash messages instead of off-screen error divs - Settings gear in global title bar, add-wallet moved to settings pane - Settings wells with light grey background, configurable Blockscout URL - Consistent "< Back" buttons top-left on all views - Address titles (Address 1.1, 1.2, etc.) on main and detail views - Send view shows current balance of selected asset - Clickable affordance policy added to README - Shortened mnemonic backup warning - Fix broken background script constant imports
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
const { $, showError, hideError, showView } = require("./helpers");
|
||||
const { $, showView, showFlash } = require("./helpers");
|
||||
const {
|
||||
generateMnemonic,
|
||||
hdWalletFromMnemonic,
|
||||
@@ -6,13 +6,13 @@ const {
|
||||
} = require("../../shared/wallet");
|
||||
const { encryptWithPassword } = require("../../shared/vault");
|
||||
const { state, saveState } = require("../../shared/state");
|
||||
const { scanForAddresses } = require("../../shared/balances");
|
||||
|
||||
function show() {
|
||||
$("wallet-mnemonic").value = "";
|
||||
$("add-wallet-password").value = "";
|
||||
$("add-wallet-password-confirm").value = "";
|
||||
$("add-wallet-phrase-warning").classList.add("hidden");
|
||||
hideError("add-wallet-error");
|
||||
showView("add-wallet");
|
||||
}
|
||||
|
||||
@@ -25,16 +25,14 @@ function init(ctx) {
|
||||
$("btn-add-wallet-confirm").addEventListener("click", async () => {
|
||||
const mnemonic = $("wallet-mnemonic").value.trim();
|
||||
if (!mnemonic) {
|
||||
showError(
|
||||
"add-wallet-error",
|
||||
"Please enter a recovery phrase or press the die to generate one.",
|
||||
showFlash(
|
||||
"Enter a recovery phrase or press the die to generate one.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
const words = mnemonic.split(/\s+/);
|
||||
if (words.length !== 12 && words.length !== 24) {
|
||||
showError(
|
||||
"add-wallet-error",
|
||||
showFlash(
|
||||
"Recovery phrase must be 12 or 24 words. You entered " +
|
||||
words.length +
|
||||
".",
|
||||
@@ -42,34 +40,42 @@ function init(ctx) {
|
||||
return;
|
||||
}
|
||||
if (!isValidMnemonic(mnemonic)) {
|
||||
showError(
|
||||
"add-wallet-error",
|
||||
"Invalid recovery phrase. Please check for typos.",
|
||||
);
|
||||
showFlash("Invalid recovery phrase. Check for typos.");
|
||||
return;
|
||||
}
|
||||
const pw = $("add-wallet-password").value;
|
||||
const pw2 = $("add-wallet-password-confirm").value;
|
||||
if (!pw) {
|
||||
showError("add-wallet-error", "Please choose a password.");
|
||||
showFlash("Please choose a password.");
|
||||
return;
|
||||
}
|
||||
if (pw.length < 8) {
|
||||
showError(
|
||||
"add-wallet-error",
|
||||
"Password must be at least 8 characters.",
|
||||
);
|
||||
showFlash("Password must be at least 8 characters.");
|
||||
return;
|
||||
}
|
||||
if (pw !== pw2) {
|
||||
showError("add-wallet-error", "Passwords do not match.");
|
||||
showFlash("Passwords do not match.");
|
||||
return;
|
||||
}
|
||||
hideError("add-wallet-error");
|
||||
const encrypted = await encryptWithPassword(mnemonic, pw);
|
||||
const { xpub, firstAddress } = hdWalletFromMnemonic(mnemonic);
|
||||
const duplicate = state.wallets.find(
|
||||
(w) =>
|
||||
w.type === "hd" &&
|
||||
w.addresses[0] &&
|
||||
w.addresses[0].address.toLowerCase() ===
|
||||
firstAddress.toLowerCase(),
|
||||
);
|
||||
if (duplicate) {
|
||||
showFlash(
|
||||
"This recovery phrase is already added (" +
|
||||
duplicate.name +
|
||||
").",
|
||||
);
|
||||
return;
|
||||
}
|
||||
const encrypted = await encryptWithPassword(mnemonic, pw);
|
||||
const walletNum = state.wallets.length + 1;
|
||||
state.wallets.push({
|
||||
const wallet = {
|
||||
type: "hd",
|
||||
name: "Wallet " + walletNum,
|
||||
xpub: xpub,
|
||||
@@ -78,11 +84,28 @@ function init(ctx) {
|
||||
addresses: [
|
||||
{ address: firstAddress, balance: "0.0000", tokenBalances: [] },
|
||||
],
|
||||
});
|
||||
};
|
||||
state.wallets.push(wallet);
|
||||
state.hasWallet = true;
|
||||
await saveState();
|
||||
ctx.renderWalletList();
|
||||
showView("main");
|
||||
|
||||
// Scan for used HD addresses beyond index 0.
|
||||
showFlash("Scanning for addresses...", 30000);
|
||||
const scan = await scanForAddresses(xpub, state.rpcUrl);
|
||||
if (scan.addresses.length > 1) {
|
||||
wallet.addresses = scan.addresses.map((a) => ({
|
||||
address: a.address,
|
||||
balance: "0.0000",
|
||||
tokenBalances: [],
|
||||
}));
|
||||
wallet.nextIndex = scan.nextIndex;
|
||||
await saveState();
|
||||
ctx.renderWalletList();
|
||||
}
|
||||
|
||||
ctx.doRefreshAndRender();
|
||||
});
|
||||
|
||||
$("btn-add-wallet-back").addEventListener("click", () => {
|
||||
|
||||
Reference in New Issue
Block a user