Uh oh!
There was an error while loading. Please reload this page.
fix(wallet): wait for the token set before drawing recent activity - #1285
Merged
Conversation
On a fresh login `hydrateFromPersistence` flips `_hydrated` true immediately when Room is empty, so the wallet's `tokens` went from null to an empty list before any network fetch. The tab's loading gate only checked for null, so the feed and the token set raced — and the feed regularly won. `convertTitle` needs both mints resolved out of the cache-only token map, so convert rows fell back to the server's bare "Converted" and re-titled themselves once tokens landed. Mirror the pattern the feed already uses for this exact ambiguity (`FeedSyncState`): add `TokenSyncState` to `TokenCoordinator`, set from `updateTokens()`, and derive `State.isAwaitingTokens` from it — an empty token set only counts as "settled" once a fetch has actually completed. A non-empty set short-circuits the wait, so a returning user with cached tokens never blocks, and a failed fetch flips to Unavailable rather than spinning forever. Gated on "a fetch completed" rather than "these mints resolved" because `getTokenMetadata` only caches metadata for mints the user holds an account for, so a per-row wait could hang on a convert whose destination never lands.
Uh oh!
There was an error while loading. Please reload this page.
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 freeto 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.
Post-login, the wallet's Recent Activity preview drew convert rows as "Converted" for a beat before re-titling them to "USDF → Dad Cash".
Cause
A race, not a mapping bug.
TokenCoordinator.hydrateFromPersistence()sets_hydrated = trueimmediately when Room is empty, so on a fresh logintokensgoes fromnulltoemptyList()before any network fetch. The wallet tab's single loading gate only checkedtokens == null, so it released, and the feed and the token set then raced independently — the feed regularly won.TransactionItemMapper.convertTitleneeds both mints resolved out of the cache-only token map. With the map still empty it returns null, and the row falls back to the server's bare verb.Fix
Mirror the pattern the activity feed already uses for exactly this ambiguity (
FeedSyncState):TokenCoordinator— newTokenSyncState(Unknown/Synced/Unavailable) exposed assyncState, maintained byupdateTokens():Syncedon a successfulfetchTokenAccounts,Unavailableon failure, never downgrading an already-successful sync. Reset toUnknownon login and onreset().SelectTokenViewModel.State.isAwaitingTokens— true whiletokens == null, or while the set is empty and nothing has fetched yet. A non-empty set short-circuits, so a returning user with cached tokens never waits.WalletScreenContent— the gate becomestokenState.isAwaitingTokens || balanceState.isAwaitingActivity, so the existing single spinner covers both sources.Notes
The wait is bounded: a failed token fetch flips to
Unavailableand releases the gate rather than spinning forever.Gated on "a fetch completed" rather than "these specific mints resolved" on purpose —
getTokenMetadataonly caches metadata for mints the user holds an account for, so a per-row wait could hang indefinitely on a convert whose destination never lands.The token-info screen's copy of
recentActivitySectionis untouched: you only reach it by tapping a card in the stack, so tokens are already resolved there.