Repository navigation
Conversation
Adds a small helper that saves the dApp request whose sheet is about to show, clears it once that request is answered or dismissed, and, at the next start, rejects the pending requests of a dApp whose request was still on screen when the app closed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… on one Saves the dApp request whose sheet is about to show, and waits for the save before showing it. If the app closes while that request is on screen (a crash, the system ending it for memory, or a force-quit), the next start finds it: before handling any request, the wallet rejects every pending request from that dApp, drops any replay already waiting, and shows a toast naming the dApp, instead of showing the request again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
Android Emulator preview APK is ready: https://github.com/stellar/freighter-mobile/releases/tag/untagged-684c2bcf5d39e7c948e5 |
Contributor
|
iOS Simulator preview build is ready: https://github.com/stellar/freighter-mobile/releases/tag/untagged-323f70b53b058b66ad69 |
This was referenced Nov 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TL;DR
Stacked on #1061. If the app closes while a dApp request is on screen (a crash, the system ending it for memory, or the user force-quitting a frozen app), the next start no longer brings that request back.
Before a request's sheet opens (or the Blockaid sheet shown in front of it), the wallet saves which request it is, and forgets it once the request is answered or dismissed. If it's still saved at the next start, the app closed while showing it: before handling any request, the wallet rejects every pending request from that dApp and shows a toast naming it. The dApp can send the request again.
There's no crash detection: the saved request is the whole signal, so a force-quit with a request open also rejects it. Connection proposals aren't covered, since one that fails is delivered only once.
Lines changed
Only this PR's own changes, not those of the PRs it's stacked on.
Screenshots and recordings (iPhone SE simulator on iOS 27.2, Pixel 10 Pro emulator)
A local test dApp sends a sign-message request; with its sheet open, the app is force-quit and reopened.
Implementation details (for agents)
What changed:
src/helpers/dappRequestReplayBreaker.ts(new):markDappRequestOnScreen({ id, topic, dappName })saves the request indataStorageunderSTORAGE_KEYS.DAPP_REQUEST_ON_SCREEN.clearDappRequestOnScreen(id)removes it, unless a later request has replaced it.rejectRequestsLeftOnScreen(message)reads and removes the saved request, then rejects everywalletKit.getPendingSessionRequests()entry with its session topic (code 5000). It removes the record first, so a failure can't repeat on every start, and a failed rejection is logged without stopping the others. It returns the dApp name and the ids it rejected, or null when nothing was saved or nothing from that dApp was pending.freighter-mobile/src/helpers/dappRequestReplayBreaker.ts
Lines 44 to 111 in 9172d28
src/providers/WalletKitProvider.tsx:presentRequestSheetsaves the request, waits for the write, then presents the sheet. A failed write is logged and the sheet shows anyway. The fourpresent()calls inprocessSessionRequestgo through it.handleClearDappRequest, forgets the request. It runs when a request is answered, cancelled or dismissed.rejectRequestsLeftOnScreenonce WalletKit is initialized, logs a warning with the count, and shows the toast. The dispatch effect handles no request until that check is done, and drops any request it rejected. WalletKit replays pending requests about a second after it starts, so a replay can already be waiting.freighter-mobile/src/providers/WalletKitProvider.tsx
Lines 785 to 812 in 9172d28
freighter-mobile/src/providers/WalletKitProvider.tsx
Lines 510 to 519 in 9172d28
freighter-mobile/src/providers/WalletKitProvider.tsx
Lines 1513 to 1589 in 9172d28
src/config/constants.ts:STORAGE_KEYS.DAPP_REQUEST_ON_SCREEN. It's cleared with the other non-sensitive keys when the wallet is wiped.i18n (en, pt):
walletKit.requestRejectedAtStartTitle,walletKit.requestRejectedAtStartandwalletKit.requestRejectedAtStartReason(what the dApp receives).Verification:
yarn test: 354 suites pass, 5,307 tests pass and 6 are skipped. New tests cover the helper (save, clear only its own request, reject only the dApp's pending requests, a corrupt record, a failed rejection) and the provider: the save happens before the sheet or the Blockaid sheet is presented, a failed save still shows the request and is logged, answering or cancelling forgets it, the start check rejects and toasts before any request is handled, a replay already waiting is dropped, and requests wait for the check.yarn lint:tspasses, and ESLint and Prettier pass on every changed file.Follow-ups / out of scope:
🤖 Generated with Claude Code