fix: give every address a row of its own, so none wraps or is shortened (closes #380) #381

Merged
clawbot merged 1 commits from issue-380-address-layout into next 2026-08-30 05:25:00 +02:00
Collaborator

Closes #380.

An address in the wallet list shared one row with the [info] and [x] controls, which took about a third of the width off it, so all 42 characters folded onto a second line. A folded address turns one string the user is meant to compare against a known value into two shorter ones, which is the shape an address-poisoning attack wants.

What changed. The layout, not the CSS. renderAddressHtml() - the single renderer behind every common view that shows an address - now emits an identity strip (colour dot, wallet title, explorer link, ENS name below it) and then the address alone on a full-width row. The wallet list moves [info] and [x] up onto the "Address N" line, which was empty to its right. The transaction rows on Home, the address screen and the token screen carried a truncateMiddle()d counterparty squeezed in beside the amount; they now name it on the amount line where we know it, and carry the whole address on the row below. .am-address holds white-space: nowrap so it cannot fold again.

Things the diff does not show:

  • overflow-x: auto on .am-address is an escape hatch, not the mechanism. The row is wide enough at every nesting depth the popup uses; if that ever stops being true, the row scrolls and the user can still reach the last character, instead of #app's overflow-x-hidden clipping the tail away silently. The e2e suite asserts the scroll is never actually needed.
  • No caller passes maxLen any more, so the 32-character floor that lived in those call sites moved into renderAddressHtml(). truncateMiddle() and its 10-character cap are untouched - RULES.md requires both, and the guarantee has to outlive having no current callers.
  • The 66-character transaction hash still wraps. It is not an address and it cannot fit on one row at any font this popup uses.

Verification. make check green. The e2e suite (make test-e2e, 57/57) measures every rendered address in a real Chromium - whole, one line box, inside its row, inside the popup's content box, document not scrolling sideways - across Home with a two-address wallet, the address, token, receive, send and transaction detail screens, the confirmation screen and the dApp transaction prompt. I also ran it as a negative control with the old wallet-list row restored, and it reproduced the reported wrap, so the new assertions are not vacuous. Rendered screenshots of the four main views were eyeballed as well.

Disclosures:

  • The branch is cut from next, whose tree is byte-identical to current main (main is one merge commit ahead and has no content next lacks), so this satisfies both "off current main" and the repo's base-next rule.
  • .am-address is a custom CSS class, which README's Tailwind bullet says the repo does not use for styling. I judged this an invariant rather than styling - it has to hold identically in a dozen places, and repeated utilities are how one of them drifts - and amended that bullet to record it alongside the existing .copy-flash-* classes. Push back if that is the wrong call.
  • TODO.md: I added the completed entry but did not advance Next Step, because the item sitting there is the pre-1.0 security review, not this issue, and moving it would claim work I did not do.
Closes [#380](https://git.eeqj.de/sneak/AutistMask/issues/380). An address in the wallet list shared one row with the `[info]` and `[x]` controls, which took about a third of the width off it, so all 42 characters folded onto a second line. A folded address turns one string the user is meant to compare against a known value into two shorter ones, which is the shape an address-poisoning attack wants. **What changed.** The layout, not the CSS. `renderAddressHtml()` - the single renderer behind every common view that shows an address - now emits an identity strip (colour dot, wallet title, explorer link, ENS name below it) and then the address alone on a full-width row. The wallet list moves `[info]` and `[x]` up onto the "Address N" line, which was empty to its right. The transaction rows on Home, the address screen and the token screen carried a `truncateMiddle()`d counterparty squeezed in beside the amount; they now name it on the amount line where we know it, and carry the whole address on the row below. `.am-address` holds `white-space: nowrap` so it cannot fold again. **Things the diff does not show:** - `overflow-x: auto` on `.am-address` is an escape hatch, not the mechanism. The row is wide enough at every nesting depth the popup uses; if that ever stops being true, the row scrolls and the user can still reach the last character, instead of `#app`'s `overflow-x-hidden` clipping the tail away silently. The e2e suite asserts the scroll is never actually needed. - No caller passes `maxLen` any more, so the 32-character floor that lived in those call sites moved into `renderAddressHtml()`. `truncateMiddle()` and its 10-character cap are untouched - RULES.md requires both, and the guarantee has to outlive having no current callers. - The 66-character transaction hash still wraps. It is not an address and it cannot fit on one row at any font this popup uses. **Verification.** `make check` green. The e2e suite (`make test-e2e`, 57/57) measures every rendered address in a real Chromium - whole, one line box, inside its row, inside the popup's content box, document not scrolling sideways - across Home with a two-address wallet, the address, token, receive, send and transaction detail screens, the confirmation screen and the dApp transaction prompt. I also ran it as a negative control with the old wallet-list row restored, and it reproduced the reported wrap, so the new assertions are not vacuous. Rendered screenshots of the four main views were eyeballed as well. **Disclosures:** - The branch is cut from `next`, whose tree is byte-identical to current `main` (`main` is one merge commit ahead and has no content `next` lacks), so this satisfies both "off current main" and the repo's base-`next` rule. - `.am-address` is a custom CSS class, which README's Tailwind bullet says the repo does not use for styling. I judged this an invariant rather than styling - it has to hold identically in a dozen places, and repeated utilities are how one of them drifts - and amended that bullet to record it alongside the existing `.copy-flash-*` classes. Push back if that is the wrong call. - `TODO.md`: I added the completed entry but did not advance `Next Step`, because the item sitting there is the pre-1.0 security review, not this issue, and moving it would claim work I did not do.
clawbot added 1 commit 2026-08-30 04:52:17 +02:00
fix: give every address a row of its own, so none wraps or is shortened (closes #380)
All checks were successful
check / check (push) Successful in 1m52s
e2e / e2e-chrome (push) Successful in 2m33s
e2e / e2e-firefox (push) Successful in 56s
4b4d9e7a1d
The wallet list was the reported case. An address there shared one row with
the [info] and [x] controls, which took about a third of the width off it,
so all 42 characters folded onto a second line. A folded address is not a
cosmetic problem: it turns one string the user is meant to compare against
a known value into two shorter ones, which is the shape an address-poisoning
attack wants.

The fix is the layout, not the CSS. renderAddressHtml() -- the single
renderer behind every common view that shows an address -- now emits an
identity strip (colour dot, wallet title, explorer link, with the ENS name
below it) and then the address alone on a full-width row. The wallet list
moves [info] and [x] up onto the "Address N" line, which was empty to its
right. The transaction rows on Home, the address screen and the token screen
carried a truncateMiddle()d counterparty squeezed in beside the amount;
they now name it on the amount line where we know it, and carry the whole
address on the row below.

With the row to itself, an address fits at every nesting depth the popup
uses, including the transaction detail wells, which are the narrowest
containers it has. .am-address holds nowrap so it cannot fold again, and
overflow-x so that if it ever does not fit -- wider glyphs, a zoom -- the
user can still reach the last character rather than having it clipped away
by #app's overflow-x-hidden with nothing to say it happened.

No caller passes maxLen any more, so the 32-character floor that lived in
those call sites moved into renderAddressHtml(). truncateMiddle() and its
10-character cap are unchanged: the guarantee has to outlive having no
current callers.

tests/e2e measures it in a real Chromium rather than asserting on markup:
whether an address wrapped is a question about glyph advances and the width
of the box it landed in, and nothing in the HTML answers it. Every rendered
address is checked for being whole, occupying one line box, fitting its row
and ending inside the popup's content box, with the document itself not
scrolling sideways -- across Home with a two-address wallet, the address,
token, receive, send and transaction detail screens, the confirmation screen
and the dApp transaction prompt.
clawbot added the needs-review label 2026-08-30 04:52:18 +02:00
clawbot self-assigned this 2026-08-30 04:52:18 +02:00
Author
Collaborator

PASS: every common view renders the whole 42-character address on a line of its own with the layout intact, and it holds even with the never-wrap CSS removed, so the fix is the restructure and not the rule.

Disclosure: judgement call left to sneak, not written up as a defect - .am-address is a custom CSS class and the PR amends the README bullet that said the repo has none, where the Tailwind utilities whitespace-nowrap overflow-x-auto would have needed no amendment.
Disclosure: the second #380 test asserts over .am-address elements only, so it stays green against a view that drops the class entirely; the first one catches that for the wallet list by counting, and no other view has that guard.

PASS: every common view renders the whole 42-character address on a line of its own with the layout intact, and it holds even with the never-wrap CSS removed, so the fix is the restructure and not the rule. Disclosure: judgement call left to sneak, not written up as a defect - `.am-address` is a custom CSS class and the PR amends the README bullet that said the repo has none, where the Tailwind utilities `whitespace-nowrap overflow-x-auto` would have needed no amendment. Disclosure: the second `#380` test asserts over `.am-address` elements only, so it stays green against a view that drops the class entirely; the first one catches that for the wallet list by counting, and no other view has that guard.
clawbot added merge-ready and removed needs-review labels 2026-08-30 05:21:52 +02:00
clawbot merged commit 1197d2171b into next 2026-08-30 05:25:00 +02:00
clawbot deleted branch issue-380-address-layout 2026-08-30 05:25:00 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/AutistMask#381