Skip to content

Enable Stealth swap and send via param, deep link, and saved toggles - #6257

Open
j0ntz wants to merge 12 commits into
developfrom
jon/stealth-nav-param
Open

j0ntz wants to merge 12 commits into
developfrom
jon/stealth-nav-param

Conversation

@j0ntz

@j0ntz j0ntz commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Description

Asana task

Stealth Swap and Stealth Send can now be turned on from outside the scenes, and the app remembers each toggle per account.

  • Swap scene param. stealth: true opens the swap scene with Stealth Swap on, stealth: false opens it off, and an absent value starts from the saved choice. The scene consumes the param once, and the override ends when the user leaves the swap tab. The Stealth Swap toggle also shows as soon as the scene opens; it used to appear only after both assets were picked.
  • Send scene param. stealth: true arms Stealth Send on entry through the same handler as a tap, and only where a tap would succeed. A send that hides the toggle (locked tiles, a pre-filled address, a FIO request) or that cannot go private opens with Stealth off, and the card states the reason.
  • Send deep link. edge://send?stealth=true[&asset=<pluginId>[_<tokenId>]] opens the send wallet picker, then Send with Stealth Send on. A named asset filters the picker and auto-picks a lone matching wallet; an asset no wallet holds falls back to the full picker. Without stealth=true the link is a plain send entry.
  • Saved toggles. stealthSendEnabled and stealthSwapEnabled live in the synced account settings, default off, and are written only when the user taps a toggle. A param or link never writes them. Send re-seeds from the saved value on each wallet it opens with, so a wallet that cannot go private shows off with its reason while the next eligible wallet shows on again. A tap waits for the settings write, and the row stays locked until it lands; a failed write shows an error and leaves the toggle as it was.
  • Maestro flows. Because the toggles are remembered, the stealth flows set each toggle explicitly with a shared helper that takes STATE: on|off and taps only when the screen shows the other state.

Docs: src/docs/exchange-deep-links.md (the link) and src/docs/stealth-send-swap.md (the saved toggles).

CHANGELOG

Does this branch warrant an entry to the CHANGELOG?

  • Yes
  • No

Dependencies

none

Requirements

If you have made any visual changes to the GUI. Make sure you have:

  • Tested on iOS device
  • Tested on Android device
  • Tested on small-screen device (iPod Touch)
  • Tested on large-screen device (tablet)

Test evidence

652651e
2026-10-14
🪓 frames 21 and 22: a temporary uncommitted edit made the edge://swap link pass stealth: true, reverted before push, because no caller passes the swap param

7. link no asset opens full wallet picker

8. link no asset send opens with stealth on

9. link btc one wallet auto picks stealth on

10. link robinhood two wallets filtered picker

11. link robinhood send opens with stealth on

12. link unheld asset falls back to full picker

13. plain send after link stealth stays off

14. send toggle tapped on

15. after relaunch send remembers on

16. after relaunch swap stays off

17. ineligible wallet off with reason

18. next eligible wallet still on

19. after relaunch send remembers off

20. after relaunch swap remembers on

21. 🪓 swap param on over saved off

22. 🪓 swap param dropped after leaving tab
4f6bdae
fixup! Remember the Stealth toggle choices
2026-10-15
🪓 Send frames: develop's 4-line row-key fix (31b29ad) applied locally so its pre-existing LogBox error toast did not cover the Wallet Empty modal; not part of this PR

35. swap start off

36. swap stealth on

37. 🪓 send initial

38. 🪓 send stealth on

39. 🪓 send memo chain

Note

Medium Risk
Changes send/swap entry paths, deep-link picker concurrency, and synced account settings; mistakes could mis-route users or persist wrong privacy defaults, but taps are awaited before save and links cannot write settings.

Overview
Adds per-account remembered Stealth Send / Stealth Swap toggles (stealthSendEnabled, stealthSwapEnabled in synced settings), written only when the user taps the switch; navigation stealth and edge://send?stealth=true arm the toggle for one visit without persisting.

Send: edge://send (optional asset, stealth=true) resolves a wallet via pickSendWallet, joins the in-progress deep-link picker guard, and pushes send2 with stealth when requested. Send seeds the toggle on entry and after wallet/asset changes using the same eligibility rules as a tap; params override the saved choice.

Swap: Stealth Swap is shown before wallets are selected; stealth route param is consumed once and cleared on tab blur.

Maestro stealth flows now force explicit toggle on/off because state is remembered. Docs and tests cover parsing, link handling, settings round-trip, and scene behavior.

Reviewed by Cursor Bugbot for commit 4f6bdae. Bugbot is set up for automated code reviews on this repo. Configure here.

The toggle used to appear only once both swap assets were picked. It
now renders as soon as the swap scene opens, so the choice is visible
before any wallet is selected.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-13T23:47:29.826472Z 3f59f4f PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@j0ntz
j0ntz force-pushed the jon/stealth-nav-param branch from 3f59f4f to 652651e Compare October 14, 2026 18:34
@j0ntz j0ntz changed the title Enable Stealth swap and send via navigation param Enable Stealth swap and send via param, deep link, and saved toggles Oct 14, 2026

@peachbits peachbits 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.

Every path traced against the task behaves as specified, and tsc, the full jest run (1154 tests) and eslint are clean. The gaps that block approval are inline.

Suggestion: some notes for the merge with EdgeApp/edge-react-gui#6253, which reworks both scenes. It adds houdiniChains.size > 0 to swapSendAllowed, and this PR seeds only on mount and on a wallet switch, so a Houdini list that loads after Send mounts would drop the saved value or the link param for that visit; re-running the seed when swapSendAllowed turns true covers it. On the swap scene, the card should stay gated on stealthAvailable alone, because #6253 keeps the both-wallets gate this PR removes to show the toggle on entry. On a wallet switch, reseedStealthRef.current = true belongs inside #6253's reset !== 'none' block.

Comment thread src/__tests__/scenes/SendScene2.ui.test.tsx
Comment thread src/components/scenes/SwapCreateScene.tsx Outdated
Comment thread src/docs/exchange-deep-links.md Outdated
Comment thread src/actions/DeepLinkingActions.tsx
Comment thread src/__tests__/scenes/SwapCreateScene.test.tsx Outdated
Comment thread src/docs/exchange-deep-links.md Outdated
@j0ntz

j0ntz commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

The #6253 merge notes go to whichever PR rebases second, since none of them applies to code on this branch: houdiniChains.size > 0 is not in swapSendAllowed here, so there is no late-loading list to re-seed for yet. That rebase re-runs the seed when swapSendAllowed turns true (behind a previous-value ref, so a re-render does not overwrite a tap), keeps the swap card gated on stealthAvailable alone, and moves reseedStealthRef.current = true inside the reset !== 'none' block. The inline gaps are fixed in the threads above.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 09d70a5. Configure here.

Comment thread src/components/scenes/SendScene2.tsx Outdated
j0ntz added 11 commits October 15, 2026 16:38
Stamp the design doc with the fingerprint of the code tree it documents (80eb0504bf6c7f2445fe9d8de52017d04e5e435c)

Stamp the design doc with the fingerprint of the code tree it documents (67d7ec808229154879b36dd673014a9d71dcbbbf)

Fixup-for: auto
Callers can now open the swap scene with Stealth Swap already on or
off by passing `stealth` in the navigation params.

The scene keeps the toggle in local state and consumes the param once.
The swap tab stays mounted and its other callers navigate with params
that carry no stealth value, so a toggle read straight from the params
would switch off on every return from a failed quote.
Restore the setParams spy in the swap param test, so it no longer stays on the shared fake navigation for later tests (peachbits review).

Fixup-for: human
Callers can now open the send scene with Stealth Send already armed by
passing `stealth` in the navigation params.

The param arms through the same handler as a tap on the toggle, and
only where a tap would succeed. A send that hides the toggle (locked
tiles, a pre-filled address, a FIO request) or that cannot go private
opens with Stealth off.
Rename the address-prefilled stealth param test to what it checks: the toggle is not rendered there, so it never reaches a refusal (peachbits review).

Fixup-for: human
edge://send?stealth=true[&asset=<pluginId>[_<tokenId>]] lets the user
pick a wallet to send from and opens the Send scene with Stealth Send
on. A named asset narrows the picker, auto-picking a lone match, and
falls back to every wallet when none holds it. The picker never offers
wallet creation, since a new wallet has nothing to send.

The link waits for every wallet and joins the in-progress guard so a
second link cannot stack a second picker.
Drop a second send link while the first link's picker is open (test), mark both send params optional, split the unserved-chain behavior by coin and token, source the native payout from the quote, and correct the test counts

Fixup-for: human
Two synced account settings, stealthSendEnabled and stealthSwapEnabled,
default off, loaded on login, with writers the scenes call on a user
tap.
The Send and Swap scenes start their Stealth toggles from the saved
per-account choice and save each accepted tap. The stealth navigation
param still sets the toggle for one visit and never writes the saved
value; Send re-applies the visit choice after a wallet switch.
Cover the saved Stealth choice on wallets that cannot go private, a late swap param, and restore the getParent spy

Make the Stealth toggle maestro helper set an explicit on or off state, since the toggles are now remembered per account

Fixup-for: human
Document that a Stealth tap saves to synced settings and locks the row until the write lands, and add the third review round to the phase history.

Await the Stealth toggle save so the switch row stays locked until the write lands; a second tap could otherwise race it and persist a stale choice (Bugbot).

Fixup-for: auto

@peachbits peachbits 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.

Round 2 at 4f6bdae.

All six asks from the last round are in, and each new test fails with the guard it pins removed: the seed arming a blocked pair, a save after a refused tap, tokenId dropped from the reseed deps, send dropped from the picker guard, and the late swap param. The Bugbot fix holds too: SettingsRow's usePendingPress keeps the row locked until the returned write settles, and a failed save shows its error once. tsc, the full jest run (1161 tests) and eslint on the changed files are clean.

Sending the EdgeApp/edge-react-gui#6253 notes to whichever PR rebases second works, since none of that code is on this branch yet.

When this rebases onto develop, EdgeApp/edge-react-gui#6241's handleStealthTermsDeclined still calls setStealth(false), which this PR removes, so tsc flags it. It should become setStealthOverride(false) with no settings write, so a decline turns the toggle off for the visit and leaves the saved choice alone. Its 'asks for an ordinary swap after the Stealth terms are declined' test still passes if the decline also saves false, so asserting that mockSetStealthSwapEnabled ran only for the tap would pin that.

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