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:
@@ -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"
|
||||
>
|
||||
⚙
|
||||
</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"
|
||||
>
|
||||
< 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"
|
||||
>
|
||||
< 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"
|
||||
>
|
||||
< 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"
|
||||
>
|
||||
< 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"
|
||||
>
|
||||
< 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"
|
||||
>
|
||||
< 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"
|
||||
>
|
||||
< 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"
|
||||
>
|
||||
< 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>
|
||||
|
||||
Reference in New Issue
Block a user