Performance: fix - stop the persist transform mutating live wallet state - #2314
Open
JohnathanWhite wants to merge 4 commits into
Open
Performance: fix - stop the persist transform mutating live wallet state#2314JohnathanWhite wants to merge 4 commits into
JohnathanWhite wants to merge 4 commits into
Conversation
The bindWalletKeys inbound transform ran `delete wallet.transactionHistory` on wallet objects it does not own. redux-persist passes inbound transforms the live store slice by reference, so this mutated in-memory Redux state: the tx-history cache was wiped on every persist flush, moments after the reducer wrote it. The read-side cache check in GetTransactionHistory was therefore dead, and history was re-downloaded on every wallet or account view - one request per wallet on account views. Restoring that cache re-arms a safety gate that had been dead as a side effect of the same bug: send.ts blocks an ETH send when `hasConfirmingTxs` is set, to avoid a nonce collision with a pending transaction. Nothing recomputes that flag unless a details screen is mounted or the user pulls to refresh, so a cached value can be arbitrarily old. Trusting a stale value locks the user out of sending; discarding it disables the protection for exactly the case it exists for. So the flag now carries a fetchedAt stamp and, when stale, is re-verified against the network before the send is allowed or blocked. On a fetch failure it fails closed. For ERC20 sends the re-verification targets the linked native wallet, because the flag for a token wallet is derived from the linked wallet's history - nonces are account-level - and re-fetching the token wallet would recompute from the same stale cache. Load-more pages carry the previous flag and its age forward rather than reporting false, which would clobber a correct value after an ordinary scroll.
gabrielbazan7
force-pushed
the
fix/persist-transform-and-nonce-gate
branch
from
August 25, 2026 14:26
613c126 to
ba081c9
Compare
Collaborator
|
follow up: JohnathanWhite#10 |
…once-gate-followup persist transform and nonce gate followup
JohnathanWhite
marked this pull request as ready for review
August 25, 2026 14:38
Collaborator
|
Already implemented here: #2241. We can close this one. |
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.
The bindWalletKeys inbound transform ran
delete wallet.transactionHistoryon wallet objects it does not own. redux-persist passes inbound transforms the live store slice by reference, so this mutated in-memory Redux state: the tx-history cache was wiped on every persist flush, moments after the reducer wrote it. The read-side cache check in GetTransactionHistory was therefore dead, and history was re-downloaded on every wallet or account view - one request per wallet on account views.Restoring that cache re-arms a safety gate that had been dead as a side effect of the same bug: send.ts blocks an ETH send when
hasConfirmingTxsis set, to avoid a nonce collision with a pending transaction. Nothing recomputes that flag unless a details screen is mounted or the user pulls to refresh, so a cached value can be arbitrarily old. Trusting a stale value locks the user out of sending; discarding it disables the protection for exactly the case it exists for. So the flag now carries a fetchedAt stamp and, when stale, is re-verified against the network before the send is allowed or blocked. On a fetch failure it fails closed.For ERC20 sends the re-verification targets the linked native wallet, because the flag for a token wallet is derived from the linked wallet's history - nonces are account-level - and re-fetching the token wallet would recompute from the same stale cache. Load-more pages carry the previous flag and its age forward rather than reporting false, which would clobber a correct value after an ordinary scroll.