Skip to content

Show the destination the transaction encodes, not the one echoed back - #226

Merged
droplister merged 1 commit into
mainfrom
fix/review-screens-render-decoded
Aug 3, 2026
Merged

Show the destination the transaction encodes, not the one echoed back#226
droplister merged 1 commit into
mainfrom
fix/review-screens-render-decoded

Conversation

@droplister

Copy link
Copy Markdown
Member

PRIORITIES.md item 2.

The problem

ADR-019 layer 4 says the approval screen must be derived from the decoded transaction, never from result.params — the composer repeating what it was asked for cannot testify about the composer. In practice only compose/send/review.tsx did that; the other 27 rendered the echo.

Severity depends on whether byte equality covers the type. Where it does, the echo is sound: matching bytes prove the params describe the message. Where it doesn't — btcpay, dispenser, both pool screens, and the three UTXO screens — field comparison speaks only to fields it was taught about, and the screen showed the request's version of everything else.

The change

All seven of those screens render their recipient through the shared ReviewScreen, so preferring the decoded destination there fixes them at one point rather than rewriting seven UIs — and every other screen inherits it.

  • The composer context is read optionally (new useComposerOptional), because ReviewScreen is also rendered outside a compose flow.
  • The response remains the fallback when a transaction carries no decodable destination: an issuance has none, and a dispense names its dispenser rather than a payee, so that path is left alone explicitly.

Tests

Two new cases in review-screen.test.tsx covering the substitution directly: when the response echoes one recipient and the transaction encodes another, the screen shows the encoded one and not the echoed one; when the decoded message carries no destination, it falls back.

The context is mocked rather than wrapped in a real provider — the real module reaches for webext-bridge, and this stays a component test.

  • tsc --noEmit clean; 1205 tests across components/pages/contexts.
  • E2E locally: compose/utxo 9/9, compose/dispenser/index.spec.ts 7/7 (which includes "full flow: dispenser form → review → verify content").

Note

This closes the destination half of item 2, which is where value routing is visible. Per-type amount and asset fields on those screens still come from params; they are covered by the field verifier and by output accounting, and correcting them needs per-type field mapping — the enumeration problem ADR-019 warns about. Worth doing per screen if it proves necessary, but it is a different shape of work than this one-point fix.

https://claude.ai/code/session_01CcjnCrgosSeshymXLBxdGj

ADR-019 says the approval screen must be derived from the decoded
transaction rather than from result.params, because params is the
composer repeating what it was asked for and so cannot testify about
the composer. Only the send screen did that; the other twenty-seven
rendered the echo.

For the types with byte equality the echo is sound -- matching bytes
prove the params describe the message -- but the ones verified field by
field are exactly where an unenumerated difference could hide, and
btcpay, dispenser, both pool screens and the three UTXO screens all
render their recipient through the shared review screen. Preferring the
decoded destination there fixes all of them at one point instead of
rewriting seven UIs, and every other screen inherits it.

The context is read optionally, since the component is also rendered
outside a compose flow, and the response is still the fallback when a
transaction carries no decodable destination -- an issuance has none,
and a dispense names its dispenser rather than a payee.

Claude-Session: https://claude.ai/code/session_01CcjnCrgosSeshymXLBxdGj
@droplister
droplister merged commit a16da4a into main Aug 3, 2026
38 checks passed
@droplister
droplister deleted the fix/review-screens-render-decoded branch August 3, 2026 23:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant