Skip to content

feat(signing): render W addresses and survive undecodable dApp XDR - #3045

Merged
JiahuiWho merged 2 commits into
masterfrom
feature/105-signing-w-addresses
Oct 30, 2026
Merged

JiahuiWho merged 2 commits into
masterfrom
feature/105-signing-w-addresses

Conversation

@JiahuiWho

Copy link
Copy Markdown
Contributor

What

Signing screens and muxed contract (W…) addresses (CAP-84).

  • W rendering: a dApp SAC transfer to a W address now renders the W… strkey in the operation parameters and the auth entry parameters. No display code changes for this.
  • Undecodable XDR: SignTransaction called TransactionBuilder.fromXdr during render, before the loading and error checks. XDR that failed to decode threw on every render and fell through to the generic "Unexpected Error" page. The view now catches the error and shows "Unable to read this transaction". Closing that warning rejects the request, so the dApp gets a response.

Why

Protocol 30 support. Closes stellar/wallet-eng-monorepo#105.

Screenshots / video

Screenshot 2026-10-27 at 3 29 19 PM

Checklist

  • I have read CONTRIBUTING.md and this PR meets its requirements.
  • This PR has narrow scope and does not mix refactoring with feature changes.
  • This PR adds tests for the new functionality or fixes.
  • These changes have been tested in both Chrome and Firefox.
  • This PR includes relevant before and after screenshots for UI changes.
  • I took the time to review my own PR.

@JiahuiWho
JiahuiWho marked this pull request as ready for review October 27, 2026 19:48
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

PR Preview build is ready: https://github.com/stellar/freighter/releases/tag/untagged-baab57f4e30ba22855b7
Backend: V1 prod + V2 beta (no sandbox configured for @JiahuiWho). SDF collaborators only — install instructions in the release description.

@JiahuiWho
JiahuiWho force-pushed the feature/105-signing-w-addresses branch from f5263a7 to cae8cdb Compare October 27, 2026 22:25
@JiahuiWho
JiahuiWho added this pull request to stack #3053 October 29, 2026 13:45
@JiahuiWho
JiahuiWho force-pushed the feature/105-signing-w-addresses branch from 5c3aa2c to ecf0e6f Compare October 30, 2026 14:34
@piyalbasu

Copy link
Copy Markdown
Contributor

The "Unable to read this transaction" path can't be reached from a dApp

Medium — the new branch, strings, and tests describe a failure the background already intercepts. Not a merge blocker, but it changes what this PR should ship.

TL;DR: The background message listener parses the dApp's XDR with the same SDK before it ever opens the popup. If that parse throws, the dApp gets an API error and no popup appears. So the popup never receives XDR it can't decode, and the "threw on every render and fell through to Unexpected Error" repro in the description has no path I can find. How was the screenshot reproduced? If it came from a dev-only edit or a deliberately broken fixture, I'd drop the undecodable-XDR half and ship the W-address tests alone. If the real worry is background and popup disagreeing on which SDK to use, the fix belongs in picking the SDK by passphrase in the popup, not in a UI state only the unit test reaches.


Detailed explanation (for agents)

Root cause: submitTransaction in the background decodes the envelope inside its try/catch before any popup is opened:

const Sdk = getSdk(currentNetworkPassphrase);
const { tab, url: tabUrl = "" } = sender;
const transaction = Sdk.TransactionBuilder.fromXdr(
transactionXdr,
networkPassphrase || Sdk.Networks[network as keyof typeof Sdk.Networks],
);

A throw there returns FreighterApiInternalError to the dApp. The popup only mounts after this succeeds and then re-parses the identical transactionXdr with transaction.networkPassphrase:

// rebuild transaction to get Transaction prototypes. The XDR comes from a
// dApp, so a failed parse renders an error below rather than throwing
// mid-render and taking down the whole popup.
let transaction: ReturnType<typeof TransactionBuilder.fromXdr> | null = null;
try {
transaction = TransactionBuilder.fromXdr(
transactionXdr,
_networkPassphrase as string,
);
} catch (error) {
console.error(error);
}

Both sides use stellar-sdk 17.4.0 (stellar-sdk and stellar-sdk-next are pinned to the same version on this branch), and getSdk only switches for an empty passphrase, so there is no decode that succeeds in the background and fails in the popup. Passphrase choice does not affect envelope decoding either; it only sets the network for hashing.

Consequences of keeping the branch as-is: the null-transaction state leaks into the rest of the view. _memo is undefined, so isMemoRequired goes true whenever flaggedKeys carries memoRequired, and the metric effect emits signingTransactionBlocked with reason_code: memo_required for a request the user sees as "unable to read". The guard also sits below the Loading gate and onboarding reroute, so the full fetch (account switch, balances, Blockaid scanTx) still runs first. These only matter if the branch is reachable.

Suggested fixes (in increasing order of depth):

  1. Drop it: remove the try/catch, the translation strings, and the new SignTransaction test; keep the W-address tests, which are the Protocol 30 work.
  2. If SDK skew is the concern: parse in the popup with the SDK selected by _networkPassphrase so background and popup use the same decoder, and memoize it on [transactionXdr, _networkPassphrase] the way ReviewTransaction does.

@JiahuiWho
JiahuiWho force-pushed the feature/105-signing-w-addresses branch from ecf0e6f to 211047d Compare October 30, 2026 18:25
Base automatically changed from chore/99-protocol-30-sdk-bump to master October 30, 2026 18:56
@JiahuiWho
JiahuiWho force-pushed the feature/105-signing-w-addresses branch from 80b90e3 to 09b6444 Compare October 30, 2026 18:56
@JiahuiWho
JiahuiWho merged commit b237323 into master Oct 30, 2026
11 checks passed
@JiahuiWho
JiahuiWho deleted the feature/105-signing-w-addresses branch October 30, 2026 19:14
JiahuiWho added a commit that referenced this pull request Oct 30, 2026
* feat(signing): render W addresses and survive undecodable dApp XDR (#3045)

* feat(signing): render W addresses and survive undecodable dApp XDR

* fix(signing): drop the unreachable undecodable-XDR branch

* feat(send): support muxed contract (W) destinations

* fix(send): address review on muxed contract destinations
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