Skip to content

fix(visualsign): always emit Condensed/Expanded in preview_layout (PRS-548)#403

Open
pepe-anchor wants to merge 1 commit into
mainfrom
worktree-d7d61861
Open

fix(visualsign): always emit Condensed/Expanded in preview_layout (PRS-548)#403
pepe-anchor wants to merge 1 commit into
mainfrom
worktree-d7d61861

Conversation

@pepe-anchor

Copy link
Copy Markdown
Contributor

Why am I making this PR?

The iOS VSP decoder (anchor-ios VisualSigningPayload.swift) declares PreviewLayout.condensed and PreviewLayout.expanded as non-optional List fields. The Ethereum visualizers were emitting condensed: None / expanded: None, and skip_serializing_if was silently dropping those keys from the JSON. Swift's synthesized decoder threw keyNotFound on receipt, degrading every Ethereum preview_layout (Uniswap Universal Router swaps, Permit2, ERC-20 previews) to FallbackText.

This was tracked in Sentry as IOS-646 and is the root cause behind PRS-548. Solana, Sui, and Tron already emit both keys unconditionally, which is why the failure was Ethereum-only.

What am I changing?

  • src/visualsign/src/lib.rsSignablePayloadFieldPreviewLayout::serialize now always emits Condensed and Expanded, defaulting to {"Fields": []} when the builder left either as None. Removed the now-contradictory skip_serializing_if annotations on both fields. This is one central serialization-layer change that covers all chains without touching any chain-specific visualizer.
  • Added test_preview_layout_always_emits_condensed_and_expanded — a failing-first unit test asserting both keys are always present even when condensed and expanded are None.
  • Updated the existing test_preview_layout_fields_alphabetical_order — the expected key set now includes Expanded (was ["Condensed", "Title"], now ["Condensed", "Expanded", "Title"]).
  • Regenerated 5 visualsign-ethereum fixtures (1559, json-eip1559, json-uniswap-ur-v2_1_1, uniswap-v2swap, uniswap-v3swap) and 2 parser_cli display fixtures (ethereum-from-file, ethereum-json). All fixture diffs are purely additive: only Condensed and Expanded keys are added, no existing content removed or reordered.

What is the Linear ticket?

PRS-548 (https://linear.app/anchorlabs/issue/PRS-548)

What are the rollback steps?

Revert the single commit (fix(visualsign): always emit Condensed/Expanded in preview_layout). This reverts src/visualsign/src/lib.rs to emit condensed/expanded only when set, restoring the prior iOS-decode-failure behavior. No database migrations, no config changes, no deploy coordination required.

Is this change backwards compatible?

Yes. The signed digest is computed over the JSON string at request time (parser/app/routes/parse.rs) and re-signed fresh per request, so changing serialized JSON output breaks no stored hashes. The change is purely additive from a JSON perspective: consumers that already handle the keys see no behavior change; consumers that were failing on missing keys (iOS) now succeed.

Does this require cross-team/service coordination?

No. The iOS fix is on the parser side; no anchor-ios change is needed. The parser service is stateless and re-signs per request.

How do I know it works as designed? Which tests exercise this code?

  • test_preview_layout_always_emits_condensed_and_expanded — new unit test, written failing-first, asserts {"Fields": []} is emitted for both keys when the builder leaves them as None.
  • All 23 preview_layout nodes across the Ethereum fixture files were verified to carry Title + Condensed + Expanded after regeneration.
  • make -C src test — all tests green (pinned toolchain 1.88.0 from src/).
  • cargo fmt --check — clean.
  • cargo clippy --all-targets -- -D warnings — clean.

…S-548)

The iOS VSP decoder declares PreviewLayout.condensed and .expanded as
non-optional List. The Ethereum visualizers emitted condensed: None /
expanded: None, and skip_serializing_if dropped those keys from the JSON,
so Swift's synthesized decoder threw keyNotFound and silently degraded
every Ethereum preview_layout (Uniswap Universal Router swaps, Permit2,
ERC-20 previews) to FallbackText. Solana/Sui/Tron already emit both keys,
which is why this was Ethereum-only.

Fix at the serialization layer: SignablePayloadFieldPreviewLayout::serialize
now always emits Condensed and Expanded, defaulting to {"Fields": []} when
unset. One central change covers all chains and is regression-proof. No
content is synthesized (Title/Subtitle still carry the summary), so empty
lists render nothing. The signed digest is computed over the JSON string
and re-signed per request, so no stored hashes break.

Regenerates the affected visualsign-ethereum and parser_cli fixtures.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes an iOS decoding failure by ensuring PreviewLayout JSON always includes Condensed and Expanded, even when the builder leaves them unset, preventing Swift’s synthesized decoder from throwing keyNotFound and falling back to FallbackText.

Changes:

  • Updated SignablePayloadFieldPreviewLayout::serialize to always emit Condensed and Expanded, defaulting to {"Fields":[]} when unset.
  • Added/updated unit tests to assert key presence and preserve deterministic alphabetical ordering.
  • Regenerated Ethereum and parser CLI fixtures to include the newly always-present Condensed/Expanded keys.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/visualsign/src/lib.rs Forces PreviewLayout serialization to always include Condensed and Expanded; adds/updates tests for key presence and ordering.
src/parser/cli/tests/fixtures/ethereum-json.display.expected Updates expected CLI display output to include Condensed/Expanded in PreviewLayout.
src/parser/cli/tests/fixtures/ethereum-from-file.display.expected Updates expected CLI display output to include Condensed/Expanded in PreviewLayout.
src/chain_parsers/visualsign-ethereum/tests/fixtures/uniswap-v3swap.expected Updates expected Ethereum fixture output to include Condensed/Expanded in nested PreviewLayouts.
src/chain_parsers/visualsign-ethereum/tests/fixtures/uniswap-v2swap.expected Updates expected Ethereum fixture output to include Condensed/Expanded in nested PreviewLayouts.
src/chain_parsers/visualsign-ethereum/tests/fixtures/json-uniswap-ur-v2_1_1.expected Updates expected Ethereum JSON fixture output to include Condensed/Expanded.
src/chain_parsers/visualsign-ethereum/tests/fixtures/json-eip1559.expected Updates expected Ethereum JSON fixture output to include Condensed/Expanded.
src/chain_parsers/visualsign-ethereum/tests/fixtures/1559.expected Updates expected Ethereum fixture output to include Condensed/Expanded.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/visualsign/src/lib.rs
Comment thread src/parser/cli/tests/fixtures/ethereum-json.display.expected
Comment thread src/parser/cli/tests/fixtures/ethereum-from-file.display.expected

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

@pepe-anchor pepe-anchor marked this pull request as ready for review June 30, 2026 15:13
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.

2 participants