feat(tokens): add How Market Cap Works explainer - #1649
Merged
Merged
Conversation
30sp Bold, mirroring iOS appDisplayCompact. Nothing sat between the 24sp and 40sp display styles.
Opens from the Market Cap header on token info and from a new row under the range chips (spec section 10776:1757). A slider over reserve shows what the balance would be worth, springing back to Today on release. Readouts roll the way SwiftUI's numericText does.
bmc08gt
force-pushed
the
feat/market-cap-explainer
branch
from
October 2, 2026 00:25
2366890 to
4d4298f
Compare
Replace ExplainerGreen with CodeTheme.colors.success (the token the existing price chart uses) and successText for positive appreciation. The icon disc and slider inactive track use surfaceVariant, and the slider's glass thumb tint uses toggleUncheckedTrackColor. The curve icon drawable is tinted from code.
AnimatedNumberText now uses the market cap explainer's roll, and the explainer calls it directly. ExplainerNumberText is removed. Slots are keyed by role (prefix, integer digit from the point, point, fraction digit, suffix), so a digit keeps its slot when the string grows or shrinks. Each digit is a spring that is retargeted mid-roll with its current offset and velocity, travels at most 0.3 of the glyph height, and blurs up to 11dp on API 31+. Below 31 it fades only. Digits take the widest digit's width; AutoSize sizes the string with every digit set to that width so fixed-width digits do not overflow. The roller still mounts only after the first change, seeded with the value on screen. The outgoing glyph leaves the tree once it has faded, and an emptied slot leaves it once its width reaches zero, so a settled number is one node per character. The pure motion helpers move to NumberRollMotion with their tests.
…ngCurveProjection MarketCapExplainerCalculator moves to com.flipcash.app.tokens.bondingcurve as BondingCurveProjection, and the view model's state field becomes projection. The view model stays in shared. ExplainerCurrency, ExplainerFormat, ExplainerLabelBox and layoutExplainerLabels are only used by the explainer UI, so they move to the feature's internal/explainer package as ExplainerFormatting. Their tests move with them to ExplainerFormattingTest; the formatted assertions that ran on calculator output now use the same literal values, and the projection test keeps the raw-number checks.
ExplainerCurrency only held a Rate. Its convert duplicated Fiat.convertingTo, and its compact reserve label duplicated core's Fiat.abbreviated. The labels that do not move with the slider (tick labels, tokens held, price per token and both supply shares) are now formatted in MarketCapExplainerViewModel, and they are recomputed when the projection loads or the preferred rate changes. The reserve readout, scrub label and worth follow the finger, so Content derives them from the snapshot with convertingTo(rate) and abbreviated(). Reserve labels now use abbreviated()'s three significant digits instead of one decimal: $1.86M rather than $1.9M, and $1.23K rather than $1.2K. The ticks and Today read the same. ExplainerFormatting.kt only holds the label layout now, so it becomes ExplainerLabelLayout.kt. The price and percent tests move to MarketCapExplainerViewModelTest.
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.
Adds a "How Market Cap Works" screen to token info, built from the v0.1 spec (section 10776:1757, screens 10761:2077 and 10761:1773). It shows what the holder's balance would be worth if the coin's reserve grew to a chosen size.
The math is in
BondingCurveProjection(com.flipcash.app.tokens.bondingcurve), on top of new reserve and supply conversions onDiscreteBondingCurve(exposed throughEstimator). The slider axis is reserve in USD, positioned by log(reserve). Supply at a stop comes from the curve's supply-from-value, and "would be worth" is the fee-free sell value of the held quarks at that supply. Display goes through the preferred currency rate withFiat.convertingTo; the math stays in USD. The acceptance vectors (1.25M supply, 12,400 held) match iOS:Stops are $5K, $100K, $1M and $10M. While the top stop is at most twice today's reserve, a stop 10× higher is added, capped at the reserve where all 21M tokens are sold, so Today always has room to slide up.
The screen
Sliderwith a custom thumb: a white capsule that grows and turns translucent while pressed, to match the iOS 26 thumb. The track runs continuously under it. Haptic tick at each stop, and it springs back to Today on release.successfor the curve, slider fill, row icon and a gain;errorTextfor a loss;surfaceVariantfor the icon disc and inactive track.Fiat.abbreviated(), so they show three significant digits ($1.86M, not $1.9M).AnimatedNumberTextnow rolls digits the way SwiftUI's.numericText()does, and the explainer uses it. This changes every caller, not just the explainer:Other callers:
TokenCard,TokenBalanceRow,CurrencyAppreciationLabel,DescriptionSelectionScreen,ReportDetailsScreen,MarketCapSection,LinkCardView,AmountArea.Adds
CodeTypography.displayCompact(30sp Bold) to mirror iOS'sappDisplayCompact, for the amount readout. The Market Cap header loses its chevron.Tests cover the projection math and stops, the label layout, the roll motion (
NumberRollMotionTest), the existingAnimatedNumberTextTest, and the view model (currency conversion, appreciation sign, preformatted labels).iOS counterpart: code-payments/code-ios-app#946.