Skip to content

feat(money): show every amount in the display currency - #1841

Merged
bmc08gt merged 15 commits into
code/cashfrom
feat/single-display-currency
Oct 24, 2026
Merged

bmc08gt merged 15 commits into
code/cashfrom
feat/single-display-currency

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

The currency picked on the Money tab is now the only currency the app shows. Every fiat amount is restated in it with no flag and no second line. The balance header and the region-picker rows keep their flags.

What changed

  • Fiat.forViewer sits beside LocalFiat.forViewer for amounts with no mint (chat quotes, reaction boosts, minimums). USD-priced amounts display as USD × display fx and stay USD on the wire.
  • USDF converts from its settled USD in both the received sheet and chat (bubble, quote panel, reply strip, chat list preview), so the two show the same number for the same payment.
  • A preferred rate that is only the Rate.oneToOne.copy(currency = code) stand-in converts nothing. With no rate, the native amount is shown bare.
  • The cash bill face stays in its native currency; BillAmount no longer takes a flag.
  • Transaction details drop the Currency and USDF rows; the header, fee and received lines use the display currency.
  • Amount-entry screens lose the currency button. FlagWithFiat and PriceWithFlag are deleted.
  • Discover's leaderboard and the Search tab's currency cards show market cap and weekly change as USD × display fx, keeping the K/M abbreviation. The ranking-info holder minimum is converted for display only.
  • The chat list, archive, requests, search, share picker and group invite previews now get the exchange rate, so their last-message amount converts like the bubble. The chat list also redraws when the display currency changes; before, a row kept the old currency's amount until the chat was opened.
  • Cash-link cards in a chat resolve again when the display currency changes. The resolver held the amount as a string formatted when the link resolved, so a card kept the old currency until the chat was reopened.
  • The Coinbase add-money entry is in the display currency with no flag, like every other entry screen. The "$5 Minimum Purchase" and "$1,000 per week" alerts show the amount converted to the display currency, with no currency code: the minimum rounded half-up to the cent, the weekly limit floored to it and shown without a zero fraction, as on iOS. The $5 check converts the floor before comparing; it used to compare the typed number against 5 USD by raw value. The order sent to Coinbase stays in USD.
  • Token Info, the funding token picker and the Cash Reserves subtitle go through forViewer, so the 1:1 stand-in rate no longer puts the dollar number under the display symbol.
  • Amounts use the currency's local symbol: a CAD viewer sees "$7.30", not "CA$7.30". The symbol lookup now checks every locale of the currency's region instead of only the US and closest locale, which for CAD, AUD, MXN, CNY and about 55 others had no single-character symbol on the JVM.
  • The menu's username progress card states its minimum in the display currency instead of "$100 USD".

Parity

viewer_amount.json is copied into core-ui/src/test/resources. ViewerAmountVectorsTest runs every case through forViewer and rounds half-even to the display currency's minor units before comparing; iOS checks the same file.

@bmc08gt bmc08gt self-assigned this Oct 23, 2026
@github-actions github-actions Bot added type: feature New functionality area: payments Payments, transfers, intents, billing area: ui Compose UI, theme, components, resources area: tokens Token accounts, balances, token info area: onboarding labels Oct 23, 2026
The currency picked on the Money tab is now the only currency the app
shows. Chat bubbles, quotes, reply strips, activity, transaction details,
the received sheet, token rows, account rows, reaction boosts and the
group and username minimums all restate their amount in that currency
with no flag. The balance header and region picker keep theirs.

LocalFiat.forViewer gains a plain-Fiat sibling for amounts with no mint.
USDF converts from its settled USD on both the bill and chat paths, so
the received sheet and the chat bubble agree for the same payment. A
preferred rate that is only the 1:1 stand-in converts nothing, and an
amount with no rate is shown in its native currency.

Amount-entry screens lose their currency button. FlagWithFiat and
PriceWithFlag are deleted.

ViewerAmountVectorsTest runs forViewer against the shared
viewer_amount.json fixture that iOS also checks.
Discover's leaderboard, its ranking-info dialog, the Search tab's currency
cards and the currency creator's purchase cost were still USD with a "$"
or "USD" suffix. They now read as USD x display fx, matching iOS
(code-ios-app#1126). The holder minimum still goes to Discover in USD.
The chat list, archive, requests, search, share picker and group invite
mapped last-message amounts without an Exchange, so previews kept the
native amount. Each view model now injects Exchange and passes it to the
conversation mapping.
The "$5 Minimum Purchase" and "$1,000 per week" alerts were hard-coded
in dollars. Both now take the amount as an argument, restated in the
display currency with a zero fraction dropped.

The $5 check compared the typed amount, which is in the display
currency, against 5 USD by raw value, so a JPY user passed at ¥5 and a
GBP user was blocked at £4.50. The floor is now converted first, and
the check runs only when both sides share a currency.

Token Info, the funding token picker and the Cash Reserves subtitle
converted through the preferred rate even when it is the 1:1 stand-in
used before rates load, which put the dollar number under the display
symbol. They now go through forViewer, which shows the native amount
when there is no real rate.
@bmc08gt
bmc08gt force-pushed the feat/single-display-currency branch from cd35538 to e410b2d Compare October 23, 2026 22:56
@github-actions github-actions Bot added the area: onramp Deposit, purchase, Coinbase, fiat on-ramp label Oct 23, 2026
Coinbase sets the guest weekly limit in USD and its error carries no
amount, so a converted figure would drift with the rate. The message
stays "$1,000" and adds "USD" when the display currency is anything
else, matching code-ios-app#1126.

The $5 minimum keeps its conversion but now shows the currency's full
fraction digits ("CA$6.85", "$5.00"), the format iOS uses.
Both Coinbase alerts now state the amount converted into the display
currency with two decimals and the currency code after it, e.g.
"$6.85 CAD Minimum Purchase" and "up to $1,370.00 CAD per week". A
viewer on USD sees "$5.00" and "$1,000.00" with no code. This replaces
the unconverted "$1,000 USD" from the previous commit.
The minimum-purchase alert now reads "$5.00 USD" for a non-USD viewer
and "$5.00" for a USD viewer, instead of the converted floor. The check
itself still compares the typed amount against the converted floor.
Both Coinbase alerts state the dollar figure with no currency code for
every viewer: "$5.00 Minimum Purchase" and "up to $1,000 per week". The
weekly limit is no longer converted. The $5 check still compares the
typed amount against the converted floor.
The Coinbase amount entry keeps its currency flag and picker, its bounds
are not restated, and the $5 minimum check and alerts are the production
ones. Every other amount-entry screen stays in the display currency.
The $5 minimum and the $1,000 weekly limit alerts now show the amount
converted to the display currency, with no currency code. The Coinbase
amount entry follows the other entry screens: display currency, no flag.
The order sent to Coinbase stays in USD.
The converted $5 minimum is rounded half-up to the currency's minor
unit before the check and the alert, and the weekly limit is floored to
it so it never states more than Coinbase allows. CAD at 1.416385 now
reads $7.08 and $1,416.38 on both platforms.
The single-character symbol only looked at the US locale and the currency's
closest locale. When the closest locale prefixes the country (CA$ under
csw_CA), CAD had no single-character symbol and amounts read "CA$7.30".
Collect the symbol from every locale of the currency's region and keep only
currency signs and the Latin letters some currencies use alone.

The menu's username progress card also stated its minimum as "$100 USD";
it now restates it in the display currency like the other minimums.
@github-actions github-actions Bot added the area: network gRPC, connectivity, API, exchange rates label Oct 24, 2026
A payment preview is converted at mapping time, but the list only re-mapped
on feed, token or profile changes. After switching ARS to CAD the XCTests row
kept reading "$10,662.00" while the bubble read "$9.80", until the chat was
opened. The preferred rate now joins the combine.
…hanges

LinkCardResolver keeps a cash card's amount as the string GiftCardLookup
formatted when the link resolved, so a card kept the old currency after a
Money tab switch until the chat was reopened. ChatViewModel now drops every
answer that carries an amount when the preferred currency changes, and the
cards resolve again.
@bmc08gt
bmc08gt merged commit 5d5c29d into code/cash Oct 24, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: network gRPC, connectivity, API, exchange rates area: onboarding area: onramp Deposit, purchase, Coinbase, fiat on-ramp area: payments Payments, transfers, intents, billing area: tokens Token accounts, balances, token info area: ui Compose UI, theme, components, resources type: feature New functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant