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
The Uniswap Universal Router calldata decoder listed V4_SWAP (0x10) in
command names but never decoded its inner actions to extract token
addresses. This caused all V4 swaps (e.g. USDT→USDC) to display as
'Swap ETH → ETH' because tokenIn/tokenOut defaulted to null, which
tokenInfo() resolved as native ETH.
Added decodeV4Swap() which parses the V4 inner action bytes:
- SETTLE (0x0b) → extracts input token currency address
- TAKE (0x0e) → extracts output token currency address
- SWAP_EXACT_IN/OUT and their SINGLE variants → extracts tokens from
pool keys and paths, plus amounts
These addresses are then resolved against the known token list
(TOKEN_BY_ADDRESS) to display correct symbols like USDT, USDC, etc.
Fixes#59
The etherscanLinkHtml helper had added border, px-1, hover:bg-fg,
hover:text-bg, and cursor-pointer classes that no other view uses.
All other views (addressDetail, addressToken, confirmTx, send, receive,
home, txStatus) use only 'inline-flex items-center' on etherscan links.
Removed the extra classes for consistency.
1. Protocol name now has Etherscan link (was appearing clickable but wasn't)
2. Token contract addresses: symbol shown separately, then color dot +
full address + Etherscan link (symbol no longer interposed)
3. Raw data section moved after transaction hash (no longer pushes
useful info off screen)
- Add clickable affordance (border + hover state) to all Etherscan external
links on addresses and transaction hash per clickable affordance policy
- Fix address display when ENS name is present: show color dot and Etherscan
link on the full address line (previously only shown on ENS name line)
- Extract etherscanLinkHtml helper for consistent link styling
Closes#59
Previously loadCalldata was only called from show(), meaning when the popup
was closed and reopened (triggering render() directly via restoreView), the
calldata decoding section was hidden and never re-fetched. Now render()
triggers loadCalldata for contract calls, so decoded data always appears.
Closes#60
Extends the fallback chain to: tb → state.trackedTokens → TOKEN_BY_ADDRESS → '?'
This ensures user-added custom tokens (not just hardcoded known tokens)
display correct symbol, name, and decimals even when Blockscout hasn't
returned balance data (e.g. zero-balance tracked tokens).
For swap transactions in the transaction history list views (home and
addressDetail), display the user's own labelled wallet address instead
of the contract/counterparty address. The contract address is not useful
in the list view — users need to see which of their addresses performed
the swap.
Closes#55
When a token's balance entry is missing or incomplete (e.g. not yet
fetched from Blockscout), the address-token view and send view now
fall back to the built-in known token list for symbol, name, and
decimals instead of showing '?'.
Also includes token name in the balance object returned by
fetchTokenBalances so the contract info well can display it.
Fixes#51
- send.js: show addressTitle() above ENS name and address in From field
- txStatus.js: show addressTitle() in To address when it's a local wallet
- home.js: show addressTitle() for counterparties in tx list when they
are local wallet addresses
Previously, ENS reverse lookups were only performed for the single
counterparty address (from or to depending on direction). This meant
contract interaction targets and the non-counterparty side of
transactions never got ENS names resolved.
Now both from and to addresses are collected for ENS resolution,
ensuring all displayed addresses show their ENS names when available.
Two issues that could cause ENS names to disappear:
1. refreshBalances: on ENS lookup error, addr.ensName was set to null,
wiping any previously resolved name. Now keeps the existing value
on error — only overwrites on successful lookup.
2. ens.js cache: failed lookups were cached as null for 12 hours,
preventing retries even after transient errors resolved. Now skips
caching on failure so subsequent lookups retry immediately.
Added debug logging to ENS reverse lookups in refreshBalances.
The approve-tx view was showing raw addresses for From/To even when they
belonged to the user's wallet. Now uses addressTitle() to display the
wallet name (e.g. 'My Wallet — Address 1') consistently with other views.
Replace the inline confirmation div at the bottom of Settings with a
proper full-screen view (view-delete-wallet-confirm). This fixes the
issue where the confirmation was offscreen on the 360x600 popup.
- New view with back button, title, warning text, password input,
and red-text Confirm Delete button
- Dedicated flash area for password errors
- New deleteWallet.js module with init/show pattern
- Added delete-wallet-confirm to VIEWS array in helpers.js
- Removed old inline confirmation HTML and logic from settings
- Restructured calldata section to use same well layout as approval view:
Action label + bold name + structured details
- Always show raw data section below decoded well
- Unknown contract calls show method name in well instead of inline
action.openPopup() is unreliable when called from the background script
during an async message handler — it requires a user gesture context.
tx and sign approvals are triggered programmatically by dApp RPC calls,
not by user clicking the toolbar icon, so openPopup() fails silently.
Use windows.create() directly for tx/sign approvals, matching the
standard extension pattern (used by MetaMask and others). Site-connection
approvals retain openPopup() since they can fall back to the user
clicking the toolbar icon.
Also updates popup window dimensions to 360x600 to match the standard
popup viewport specified in README.
Closes#4
- Delete buttons now use [x] with border, matching token and site
removal patterns in settings
- Wallet names are click-to-rename (inline input), matching the
home view rename UX
- Per-wallet [delete] links in settings wallet list
- Monochrome styling throughout, no red/danger colors
- Password confirmation modal with warning text
- Cleans up site permissions for deleted addresses
- Switches to first remaining wallet or shows welcome if none left
- Remove all red/danger styling, use standard monochrome colors
- Add wallet picker dropdown instead of relying on selectedWallet
- Fix encryptedSecret field name (was wallet.encrypted)
- Populate dropdown when settings view opens
- Confirmation modal uses standard border styling