Instead of permanently reserving space with visibility:hidden, the warning
container now uses max-height + opacity transitions. Space is reserved during
the async check, then smoothly collapses to 0 if the warning isn't needed.
This reclaims ~40px of popup viewport in the common case.
Replace display:none with persistent visibility:hidden so the warning
area occupies the same vertical space regardless of API result.
This eliminates the layout shift that occurred when the container was
collapsed after the recipient history check returned.
- Reserve space for the warning upfront using visibility:hidden instead
of display:none, preventing layout shift per README policy
- Move warning HTML to index.html as a static element rather than
injecting dynamically
- Skip warning for contract addresses (check getCode first) since
getTransactionCount only returns outgoing tx nonce
- Collapse reserved space when warning is not needed (address has
history, is a contract, or on RPC error)
On the confirm-tx view, asynchronously check the recipient address
transaction count via getTransactionCount(). If zero, display a
prominent red warning advising the user to double-check the address.
Closes#82
List view rows (home, addressDetail, addressToken) should only be clickable
as a whole to navigate to the detail view. Click-to-copy on individual
elements belongs only in the transaction detail view.
Reverts timestamp click-to-copy changes in list views per review feedback.
Keeps blockNumberHtml() and detail-view timestamp changes.
Adds click-to-copy (copies ISO date string) to timestamp displays in:
- home view (relative time ago)
- addressDetail view (relative time ago)
- addressToken view (relative time ago)
- transactionDetail view (full ISO date)
All timestamps now show dashed underline to indicate copyability,
matching the existing UX pattern for addresses, tx hashes, and
block numbers.
Block numbers are blockchain entities like addresses and tx hashes. They now
receive the same treatment: click-to-copy and an external link icon pointing
to etherscan.io/block/{number}.
Closes#99
- Add underline + click-to-copy (data-copy) to addresses in toAddressHtml()
so they match the style used everywhere else in the extension
- Fix 'USDT ETH' display: add rawValue to Uniswap decoder Amount details
and extract Token In info for proper symbol resolution in approval.js
- Hide redundant top-level Amount/To when decoded details are present
(they already show the same info inside the decoded section)
- Wrap decoded calldata details in a bordered well for visual separation
Replace the modal overlay password dialog in the confirm-tx view with
an inline password field, matching the pattern used by approve-tx and
approve-sign views for consistency.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add confirm-tx to RESTORABLE_VIEWS and save pendingTx in
state.viewData so the confirmation screen survives the popup
lifecycle. On restore, re-render the full confirmation view
including gas estimate.
Add min-h-[1.25rem] and border styling to approve-tx-error and
approve-sign-error divs to prevent layout shift, matching the pattern
used by modal-password-error in confirm-tx view.
Replace direct DOM classList manipulation with showError()/hideError()
helpers from helpers.js for consistency.
Closes#84
Clears #approve-tx-password value and hides #approve-tx-error when the
transaction approval view is shown, matching the pattern used in
showSignApproval and confirmTx.show.
Closes#85
Clear the error/warning text and disable the review button when entering
the send view from home, address detail, or address token views. This
prevents stale validation messages from persisting after leaving and
returning to the send view.
- Validate Ethereum addresses (0x + 40 hex chars) and ENS names
- EIP-55 checksum validation for mixed-case addresses
- Block sending to zero address (0x0000...0000)
- Warn when sending to own address (allow but show warning)
- Inline error messages with reserved space (no layout shift)
- Disable Review button while address is invalid
Closes#67
Add color dot (addressDotHtml), dashed underline styling, and click-to-copy
functionality to the token contract address on the confirm-tx page, matching
the display pattern used in addressToken, txStatus, and other views.
Closes#70
A single transaction (e.g. a DEX swap) can produce multiple ERC-20
token transfers. The transaction merger was keyed by tx hash alone,
so only the last token transfer survived. This meant the address-token
view's contract-address filter often matched nothing.
Use a composite key (hash + contract address) so all token transfers
are preserved. Also remove the bare normal-tx entry when it gets
replaced by token transfers to avoid duplicates.
Closes#72
- Replace dashed border with light red well (bg-danger-well) and rounded corners
- Remove redundant 'Click to copy.' paragraph
- Add --color-danger-well theme token
The receive view was using raw textContent and a manually constructed
color dot instead of the shared formatAddressHtml helper used by other
views. This violated the display consistency policy ('Same data
formatted identically across all screens').
Changes:
- Use formatAddressHtml() to render address with color dot, title
(e.g. 'Wallet 1 — Address 1'), and ENS name — matching addressDetail
- Make the address block itself click-to-copy (matching policy:
'Clicking any address copies the full untruncated value')
- Replace separate receive-dot/receive-address spans with a single
receive-address-block element
- Address is still shown in full (no truncation) as appropriate for
the receive view
Closes#58
Add blockie identicon, wallet/address title, and color dot with full
address display to the export-privkey view, matching the pattern used
by AddressDetail and other views. Address is click-to-copy.
The transaction detail view was dynamically changing its title to match
the transaction type (e.g. 'Swap' for contract interactions), causing
inconsistency with the Screen Map specification. The heading is now
always 'Transaction' regardless of type. The action type is still
shown in the 'Action' detail section below.
Closes#65
When tokenBalances doesn't contain an entry for a token (e.g. before
balances are fetched), the symbol fell back to '?' in addressToken
and send views.
Add resolveSymbol() helper that checks tokenBalances → TOKEN_BY_ADDRESS
(known tokens) → trackedTokens → truncated address as last resort.
Fixes USDC and other known tokens showing '?' when balance data
hasn't loaded yet.
Carry decoded calldata info (action name, description, token details,
amounts, addresses) from the approval confirmation view through to the
success-tx view. For swap transactions, this now shows the same decoded
details (protocol, action, token symbols, amounts) that appeared on the
signing confirmation screen.
Changes:
- approval.js: store decoded calldata in pendingTxDetails.decoded
- txStatus.js: carry decoded through state.viewData, render in success view
- index.html: add success-tx-decoded container element
The decodeCalldata function in approval.js was embedding the token symbol
into the Amount value string (e.g. '2.0000 USDT'). This value was then
assigned to pendingTxDetails.amount, and txStatus.js would append the
symbol again, producing '2.0000 USDT ETH' (or '2.0000 USDT USDT' when
the token was in TOKEN_BY_ADDRESS).
Fix: decodeCalldata now provides a rawValue field (numeric only) on
Amount details. pendingTxDetails.amount uses rawValue when available,
so txStatus.js can append the correct symbol exactly once.
Affected paths:
- approve() decoded amount (approve calldata)
- transfer() decoded amount (transfer calldata)
- pendingTxDetails.amount assignment
Audited all other amount+symbol display sites:
- txStatus.js showWait/showSuccess/showError: correctly derive symbol
from txInfo.token, no duplication
- confirmTx.js show(): builds symbol independently, amount is raw — OK
- send.js: amount is raw user input — OK
- addressToken.js: uses balanceLine helper — OK
- transactions.js parseTx/parseTokenTransfer: separate value/symbol — OK
Fixes#59
Adds a test that constructs a Uniswap V4 USDT→USDC swap using
SETTLE/SWAP_EXACT_IN_SINGLE/TAKE sub-actions inside a V4_SWAP command.
Without decodeV4Swap(), the output token would be unresolvable and the
swap name would not show 'USDT → USDC'. This test fails on the old code
and passes with the decodeV4Swap() fix.
Refs: #59