feat(activity): lead activity rows with the viewer's own currency - #709
Merged
Conversation
An activity row showed `nativeAmount` alone — the currency the payment was denominated in — so a 7,500 peso tip read "-$7,500.00" to someone who reads money in dollars, with nothing saying it was $5. The row now leads with the amount in the viewer's currency and, only when the transferred currency differs, shows what actually moved beneath it with that currency's flag in the secondary style. Both lines carry the same sign; a payment already in the viewer's currency renders one line as before. `ExchangedFiat.forViewer(preferredRate:rates:)` is the conversion. A USDF payment converts from the USD it settled at (`onChainAmount`), so a $5 tip keeps reading $5 however far the peso moves afterwards. Any other mint has no such anchor — `onChainAmount` holds that mint's own quarks — so it crosses through today's rates instead and falls back to a single line when the source currency has no rate to cross with. Deliberately not `usdfValue`: an activity's rate is synthesized as `nativeAmount / onChainAmount` for a bonded mint, so dividing back through it returns the token count rather than dollars. The conversion runs at render time rather than where the feed is mapped. Reading `RatesController` in the row's body is what subscribes the rows to it, so a currency changed on a screen stacked over the list reaches them. Feed amounts are magnitudes with the direction carried alongside, which is why the row supplies the sign at all. `FiatAmount.formatted(signPrefix:)` leaves a value that already carries its own "-" alone rather than printing "--$5.00". Swap rows keep the second line for the swap fee, unchanged. Ports code-payments/code-android-app#1388. Android updated two row implementations and flagged both lines in the per-token history, which had always flagged the one amount it showed. iOS has a single `ActivityRow` across the Recent previews, the cross-token history and the per-token history, and none of them flag today, so only the transferred line gains a flag.
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.
An activity row showed
nativeAmountalone — the currency the payment was denominated in — so a 7,500 peso tip read "-$7,500.00" to someone who reads money in dollars, with nothing saying it was $5.The row now leads with the amount in the viewer's currency and, only when the transferred currency differs, shows what actually moved beneath it with that currency's flag in the secondary style. Both lines carry the same sign; a payment already in the viewer's currency renders one line as before.
The conversion
ExchangedFiat.forViewer(preferredRate:rates:)in FlipcashCore, with unit tests.A USDF payment converts from the USD it settled at (
onChainAmount), so a $5 tip keeps reading $5 however far the peso moves afterwards. Any other mint has no such anchor —onChainAmountholds that mint's own quarks — so it crosses through today's rates instead, and falls back to a single line when the source currency has no rate to cross with.Deliberately not
usdfValue: an activity's rate is synthesized asnativeAmount / onChainAmountfor a bonded mint, so dividing back through it returns the token count rather than dollars. This is the same trap as Android'sunderlyingTokenAmount.Where it runs
At render time, not in the feed mapping. Reading
RatesControllerin the row's body is what subscribes the rows to it, so a currency changed on a screen stacked over the list reaches them. Android needed the same placement for a different reason — its feed only re-maps when a profile or token cache lands.Signs
Feed amounts are magnitudes with the direction carried alongside, which is why the row supplies the sign at all.
FiatAmount.formatted(signPrefix:)leaves a value that already carries its own "-" alone rather than printing "--$5.00".Swap rows keep the second line for the swap fee, unchanged.
Difference from Android
Ports code-payments/code-android-app#1388. Android updated two row implementations and flagged both lines in the per-token history, which had always flagged the one amount it showed. iOS has a single
ActivityRowacross the Recent previews, the cross-token history and the per-token history, and none of them flag today, so only the transferred line gains a flag.One guard has no Android counterpart: a viewer rate of zero falls back to the transferred amount rather than rendering the row as zero. iOS rehydrates its rate table from SQLite at launch, so a bad row is reachable.