Token auto-discovery, tx history, balance polling, EIP-6963, UI overhaul
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:
2026-02-26 02:13:39 +07:00
parent 2b2137716c
commit 3bd2b58543
27 changed files with 978 additions and 420 deletions

View File

@@ -21,8 +21,21 @@
>@sneak</a
>
</h1>
<button
id="btn-settings"
class="bg-transparent border-none text-fg cursor-pointer text-2xl p-0 leading-none"
title="Settings"
>
&#9881;
</button>
</div>
<!-- ============ FLASH MESSAGE AREA ============ -->
<div
id="flash-msg"
class="text-xs text-muted min-h-[1.25rem] mb-1"
></div>
<!-- ============ WELCOME / FIRST USE ============ -->
<div id="view-welcome" class="view hidden">
<p class="mb-3">Welcome! To get started, add a wallet.</p>
@@ -36,6 +49,12 @@
<!-- ============ ADD WALLET (unified create/import) ============ -->
<div id="view-add-wallet" class="view hidden">
<button
id="btn-add-wallet-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer mb-2"
>
&lt; Back
</button>
<h2 class="font-bold mb-2">Add Wallet</h2>
<p class="mb-2">
Enter your 12 or 24 word recovery phrase below, or click the
@@ -62,10 +81,8 @@
id="add-wallet-phrase-warning"
class="text-xs mb-2 border border-border border-dashed p-2 hidden"
>
These words are your recovery phrase. Write them down on
paper and keep them somewhere safe. Anyone with these words
can access your funds. If you lose them, your wallet cannot
be recovered.
Write these words down and keep them safe. Anyone with them
can take your funds; if you lose them, your wallet is gone.
</div>
<div class="mb-2" id="add-wallet-password-section">
<label class="block mb-1">Choose a password</label>
@@ -87,24 +104,12 @@
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
/>
</div>
<div class="flex gap-2">
<button
id="btn-add-wallet-confirm"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Add
</button>
<button
id="btn-add-wallet-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Back
</button>
</div>
<div
id="add-wallet-error"
class="mt-2 border border-border border-dashed p-1 hidden"
></div>
<button
id="btn-add-wallet-confirm"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Add
</button>
<div class="mt-3 text-xs text-muted">
Have a private key instead?
<button
@@ -118,6 +123,12 @@
<!-- ============ IMPORT PRIVATE KEY ============ -->
<div id="view-import-key" class="view hidden">
<button
id="btn-import-key-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer mb-2"
>
&lt; Back
</button>
<h2 class="font-bold mb-2">Import Private Key</h2>
<p class="mb-2">
Paste your private key below. This wallet will have a single
@@ -151,84 +162,58 @@
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
/>
</div>
<div class="flex gap-2">
<button
id="btn-import-key-confirm"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Import
</button>
<button
id="btn-import-key-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Back
</button>
</div>
<div
id="import-key-error"
class="mt-2 border border-border border-dashed p-1 hidden"
></div>
<button
id="btn-import-key-confirm"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Import
</button>
</div>
<!-- ============ MAIN VIEW: ALL WALLETS & ADDRESSES ============ -->
<div id="view-main" class="view hidden">
<!-- total portfolio value -->
<div id="total-value" class="text-2xl font-bold mb-2"></div>
<div
id="total-value"
class="text-2xl font-bold mb-2 min-h-[2rem]"
></div>
<!-- wallet list -->
<div id="wallet-list"></div>
<div class="mt-3 border-t border-border pt-2 flex gap-2">
<button
id="btn-main-add-wallet"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
+ Add wallet
</button>
<button
id="btn-settings"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Settings
</button>
</div>
</div>
<!-- ============ ADDRESS DETAIL VIEW ============ -->
<div id="view-address" class="view hidden">
<button
id="btn-address-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer mb-2"
>
&lt; Back
</button>
<div
class="flex justify-between items-center border-b border-border pb-1 mb-2"
>
<h2 class="font-bold" id="address-title">Address</h2>
<button
id="btn-address-back"
class="border border-border px-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Back
</button>
</div>
<div id="address-ens" class="font-bold mb-1 hidden"></div>
<div
id="address-full"
class="text-xs break-all mb-1 cursor-pointer"
class="flex text-xs mb-3 cursor-pointer"
title="Click to copy"
></div>
<div
class="text-xs text-muted mb-3"
id="address-copied-msg"
></div>
<!-- balance -->
>
<span
id="address-full"
class="shrink-0"
style="width: 42ch"
></span>
<span
id="address-usd-total"
class="text-right text-muted flex-1"
></span>
</div>
<!-- balances -->
<div class="border-b border-border-light pb-2 mb-2">
<div class="text-base font-bold">
<span id="address-eth-balance">0.0000</span> ETH
</div>
<div
class="text-xs text-muted"
id="address-usd-value"
></div>
<div id="address-balances"></div>
</div>
<!-- actions -->
@@ -245,31 +230,33 @@
>
Receive
</button>
<button
id="btn-add-token"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer flex-1"
>
+ Token
</button>
</div>
<!-- tokens -->
<div>
<div
class="flex justify-between items-center border-b border-border pb-1 mb-1"
>
<h2 class="font-bold">Tokens</h2>
<button
id="btn-add-token"
class="border border-border px-1 hover:bg-fg hover:text-bg cursor-pointer text-xs"
>
+ Add
</button>
<!-- transactions -->
<div class="mt-3">
<div class="border-b border-border pb-1 mb-1">
<h2 class="font-bold">Transactions</h2>
</div>
<div id="token-list">
<div class="text-muted text-xs py-1">
No tokens added yet. Use "+ Add" to track a token.
</div>
<div id="tx-list">
<div class="text-muted text-xs py-1">Loading...</div>
</div>
</div>
</div>
<!-- ============ SEND ============ -->
<div id="view-send" class="view hidden">
<button
id="btn-send-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer mb-2"
>
&lt; Back
</button>
<h2 class="font-bold mb-2">Send</h2>
<div class="mb-2">
<label class="block mb-1">What to send</label>
@@ -290,7 +277,13 @@
/>
</div>
<div class="mb-2">
<label class="block mb-1">Amount</label>
<div class="flex justify-between mb-1">
<label>Amount</label>
<span
id="send-balance"
class="text-xs text-muted"
></span>
</div>
<input
type="text"
id="send-amount"
@@ -298,28 +291,22 @@
placeholder="0.0"
/>
</div>
<div class="flex gap-2">
<button
id="btn-send-review"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Review
</button>
<button
id="btn-send-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Cancel
</button>
</div>
<div
id="send-error"
class="mt-2 border border-border border-dashed p-1 hidden"
></div>
<button
id="btn-send-review"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Review
</button>
</div>
<!-- ============ CONFIRM TRANSACTION ============ -->
<div id="view-confirm-tx" class="view hidden">
<button
id="btn-confirm-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer mb-2"
>
&lt; Back
</button>
<h2 class="font-bold mb-2">Confirm Transaction</h2>
<div class="mb-2">
<div class="text-xs text-muted">From</div>
@@ -350,20 +337,12 @@
id="confirm-errors"
class="mb-2 border border-border border-dashed p-2 hidden"
></div>
<div class="flex gap-2">
<button
id="btn-confirm-send"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Send
</button>
<button
id="btn-confirm-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Back
</button>
</div>
<button
id="btn-confirm-send"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Send
</button>
<div
id="confirm-status"
class="mt-2 border border-border p-1 hidden"
@@ -408,6 +387,12 @@
<!-- ============ RECEIVE ============ -->
<div id="view-receive" class="view hidden">
<button
id="btn-receive-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer mb-2"
>
&lt; Back
</button>
<h2 class="font-bold mb-2">Receive</h2>
<p class="mb-2">
Share this address with the sender. Make sure you only use
@@ -420,24 +405,22 @@
id="receive-address"
class="border border-border p-2 break-all select-all mb-3"
></div>
<div class="flex gap-2">
<button
id="btn-receive-copy"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Copy address
</button>
<button
id="btn-receive-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Back
</button>
</div>
<button
id="btn-receive-copy"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Copy address
</button>
</div>
<!-- ============ ADD TOKEN ============ -->
<div id="view-add-token" class="view hidden">
<button
id="btn-add-token-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer mb-2"
>
&lt; Back
</button>
<h2 class="font-bold mb-2">Add Token</h2>
<p class="mb-2">
Enter the contract address of the token you want to track.
@@ -465,36 +448,44 @@
class="flex flex-wrap gap-1"
></div>
</div>
<div class="flex gap-2">
<button
id="btn-add-token-confirm"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Add
</button>
<button
id="btn-add-token-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Cancel
</button>
</div>
<div
id="add-token-error"
class="mt-2 border border-border border-dashed p-1 hidden"
></div>
<button
id="btn-add-token-confirm"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Add
</button>
</div>
<!-- ============ SETTINGS ============ -->
<div id="view-settings" class="view hidden">
<h2 class="font-bold mb-2">Settings</h2>
<button
id="btn-settings-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer mb-2"
>
&lt; Back
</button>
<h2 class="font-bold mb-3">Settings</h2>
<h2 class="font-bold mb-1">Network</h2>
<p class="text-xs text-muted mb-1">
The server used to talk to the Ethereum network. Change this
if you run your own node or prefer a different provider.
</p>
<div class="mb-3">
<div class="bg-well p-3 mx-1 mb-3">
<h3 class="font-bold mb-1">Wallets</h3>
<p class="text-xs text-muted mb-2">
Add a new wallet from a recovery phrase or private key.
</p>
<button
id="btn-main-add-wallet"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
>
+ Add wallet
</button>
</div>
<div class="bg-well p-3 mx-1 mb-3">
<h3 class="font-bold mb-1">Ethereum RPC</h3>
<p class="text-xs text-muted mb-1">
The server used to talk to the Ethereum network. Change
this if you run your own node or prefer a different
provider.
</p>
<input
type="text"
id="settings-rpc"
@@ -508,12 +499,22 @@
</button>
</div>
<div class="border-t border-border pt-2">
<div class="bg-well p-3 mx-1 mb-3">
<h3 class="font-bold mb-1">Blockscout API</h3>
<p class="text-xs text-muted mb-1">
Used to fetch token balances and transaction history.
Change this if you run your own Blockscout instance.
</p>
<input
type="text"
id="settings-blockscout"
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
/>
<button
id="btn-settings-back"
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
id="btn-save-blockscout"
class="border border-border px-2 py-1 mt-1 hover:bg-fg hover:text-bg cursor-pointer"
>
Back
Save
</button>
</div>
</div>