fix(activity): show Convert transactions in the feed - #1281
Merged
Conversation
A swap spans two mints, so the backend leaves `payment_amount` unset and carries
both amounts in `additional_metadata` instead. `ActivityFeedMessageMapper` only
ever read `payment_amount`, so every Convert cached with a null amount, rate, and
mint — which meant it matched no token's activity query and rendered blank in the
global feed.
- Map multi-mint amounts from `additional_metadata` when `payment_amount` is absent.
- Attribute a Convert to *both* mints, so it appears on the source and destination
token screens (`MintInvolvement` + the metadata clause in `observeRecentForMint`).
- Render it the way iOS does: overlapping dual-token avatar, from-amount on top,
`-<fee> Fee` beneath.
- Title the row with the two token names ("Moony -> Jeffy") rather than the
server's bare "Converted", falling back to the server text until both tokens
resolve.
Rows cached before this can't be repaired in place (the amounts were never
persisted) and can't be re-fetched either, since sync only walks forward from the
newest cached id. DB 28 -> 29 clears `messages` so the next sync re-seeds from
scratch — the same approach as the existing 1->2, 6->7, 7->8 and 9->10 migrations.
Also fixes a silent data-loss path found alongside it: `MessageDataSource.upsert`
no-oped when the per-user DB wasn't open yet, discarding a whole fetched page
while the coordinator still reported `Synced`. Because every sync path pages
forward from the newest cached id, those notifications were never requested
again. It now fails loudly (matching `observe()`, which already errors on a
missing DB), the mediator turns that into a retryable error, and the coordinator
only reports `Synced` once the write has actually landed.
Folds in the standalone migration work from #1284, which duplicated the 28 -> 29 clear this branch already carries. Adds TransactionHistoryMigrationTest, following the hand-rolled pattern in UserProfileMigrationTest: asserts the feed is emptied, that a neighbouring table survives, and that it's a no-op on an already-empty feed. Also switches Migration28To29 to the onPostMigrate(SQLiteConnection) overload. Room's SupportSQLiteDatabase variant only fires when the database is built without a driver, so a future setDriver would turn the delete into a silent no-op.
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.
Problem
A swap spans two mints, so the backend leaves
payment_amountunset and carries both amounts inadditional_metadatainstead.ActivityFeedMessageMapperonly ever readpayment_amount, so every Convert was cached with a null amount, rate, and mint — which meant it matched no token's activity query and rendered blank in the global feed.Changes
additional_metadatawhenpayment_amountis absent.MintInvolvement, plus the metadata clause inobserveRecentForMint).-<fee> Feebeneath.Cache repair (DB 28 → 29)
Rows cached before this can't be repaired in place — the amounts were never persisted — and they can't be re-fetched either, since
fetchSinceLatestonly ever walks forward from the newest cached id. The migration clearsmessagesso the next sync falls into its descending re-seed and refetches from scratch; paging refills older history on demand. Same approach as the existing 1→2, 6→7, 7→8 and 9→10 migrations.TransactionHistoryMigrationTestcovers it, following the hand-rolled pattern inUserProfileMigrationTest: the feed is emptied, a neighbouring table survives, and it's a no-op on an already-empty feed.The spec overrides
onPostMigrate(SQLiteConnection)rather than theSupportSQLiteDatabasevariant used byMigration22To23— Room only calls the latter when the database is built without a driver, so a future.setDriver(...)would turn the delete into a silent no-op.Silent data loss, found alongside
MessageDataSource.upsertno-oped when the per-user DB wasn't open yet, discarding a whole fetched page whileActivityFeedCoordinatorstill reportedSynced. Because every sync path pages forward from the newest cached id, those notifications were never requested again.It now fails loudly — matching
observe(), which already errors on a missing DB.FeedRemoteMediatorturns that into a retryableMediatorResult.Error, and the coordinator moved its write fromonSuccessintomapCatchingsoSyncedis only reported once the page has actually landed.Note on missing history
Activity older than the backend's swap deploy is absent server-side — the widest query the client can issue (DESC, no paging token,
pageSize=100) returns only post-deploy notifications, and all of them are persisted. That's expected data loss from the migration, not a client bug.