Refine Money Sweepstakes campaign UX - #34852
Draft
jasonculbertson wants to merge 14 commits into
Draft
Conversation
Wire series-aware details, stats, draw schedule, prize pool, opt-in CTA, and winning flow using backend-resolved localizedText. Co-authored-by: Cursor <cursoragent@cursor.com>
Assert Money Account binding before campaign opt-in, surface binding conflicts in CTA/details UI, and mock the new outcome toast hook in dashboard/campaigns tests. Co-authored-by: Cursor <cursoragent@cursor.com>
…etaMask#34024) ## Summary - Align Money Account Sweepstakes scorecard UI with the backend collapse of `lost_today` into `below_threshold`. - Warning icon / copy now only keys off `below_threshold`. - Test fixtures update `belowThresholdDescription` to point at **tomorrow's** entry. Companion backend PR: consensys-vertical-apps/va-mmcx-rewards (branch `fix/collapse-today-status-below-threshold`). ## Finding `lost_today` was misleading: the API only had today's minimum, so a flat `$50 → $50` day looked like a dip. Under the strict intra-day-minimum rule both cases are unrecoverable for today, so one status + tomorrow-facing copy is the honest UX. ## Test plan - [ ] `MoneyAccountSweepstakesStatsSummary` unit tests pass - [ ] Warning Danger icon shows for `below_threshold` - [ ] Info sheet for `below_threshold` uses the tomorrow's-entry description - [ ] No TypeScript references to `lost_today` remain Made with [Cursor](https://cursor.com) --------- Co-authored-by: Cursor <cursoragent@cursor.com>
Matches the API collapsing lost_today into below_threshold; mobile no longer reads this key. Co-authored-by: Cursor <cursoragent@cursor.com>
…n rule (MetaMask#34067) ## **Description** Client side of [va-mmcx-rewards#748](consensys-vertical-apps/va-mmcx-rewards#748), which changes what qualifies a sweepstakes day: **net new deposits since the participant joined**, rather than an intra-day balance minimum. Targets `feat/money-account-sweepstakes` (MetaMask#33887), so review that first. **Draft** — the backend PR and its spec ([va-mmcx-rewards#747](consensys-vertical-apps/va-mmcx-rewards#747)) are still awaiting product sign-off. If the rule changes, this changes with it. - `todayMinUsd` → `qualifyingDepositsUsd`, plus a new `qualifyingThresholdUsd` carrying the campaign's threshold so progress can be rendered. The threshold is per-campaign Contentful config, so it can't be hardcoded client-side — it did not previously reach the client at all, which is why the API now returns it. - `todayStatus` splits `below_threshold` back into `not_yet_qualified` and `lost_today`. These are **not** interchangeable: the first is still winnable today by depositing the shortfall, the second is forfeit. Only `lost_today` warns; `not_yet_qualified` gets a neutral add affordance. Reverses the collapse in MetaMask#34024. - The tile shows the qualifying figure **against the threshold** (`$50 / $100`) rather than a bare number. The qualifying figure counts only deposits, never accrued yield, so it is normally **lower** than the account balance — someone holding $100 who deposited $50 since joining is legitimately at $50, and a lone figure gave them no way to understand that. - The figure is clamped at zero for display. An outflow is valued when it happens and so carries the yield earned on the position, which can leave the total a few cents below zero after a full withdrawal. - Copy keys follow the API: `belowThresholdDescription` → `notYetQualifiedDescription` + `lostTodayDescription`, and `currentBalanceTitle` / `currentBalanceDescription` are gone. Those two described the account balance, which no longer decides a day and is rendered nowhere, so the DTO stops requiring strings the API no longer sends. - The localized-text fixtures now hold the strings the API actually returns, with the threshold already substituted. The backend resolves `{threshold}` from campaign config before responding, so a fixture carrying the raw token was asserting on copy no client can receive. **Known remaining gap, left for design:** "Current balance" is still absent from the tiles, so the total balance appears nowhere on screen. Showing it as context beside the qualifying figure is the piece that makes the two numbers coherent, and it needs a design call rather than a guess. ## **Changelog** CHANGELOG entry: null ## **Related issues** Refs: consensys-vertical-apps/va-mmcx-rewards#748 ## **Manual testing steps** Not performed — this is a draft against an unmerged base, and the API fields it consumes are not deployed to any environment yet. Verification so far is type-level and unit-level only: 1. `npx tsc --noEmit -p tsconfig.json` — clean. 2. `npx jest app/components/UI/Rewards/components/Campaigns/MoneyAccountSweepstakes app/components/UI/Rewards/hooks/useGetMoneyAccountSweepstakesStatsMe.test.ts app/components/UI/Rewards/Views/MoneyAccountSweepstakesCampaignDetailsView.test.tsx` — 7 suites, 54 tests passing. 3. `npx jest app/core/Engine/controllers/rewards-controller` — 9 suites, 888 tests passing. Once MetaMask#748 is on DEV: open the campaign, confirm the tile reads `qualifying / threshold`, that a participant below the threshold shows the neutral state rather than a warning, and that a participant who dipped after crossing shows the warning. ## **Screenshots/Recordings** ### **Before** N/A — not captured. Draft against an unmerged base with undeployed API fields, so the screen cannot render real data yet. ### **After** N/A — see above. To be added before this leaves draft. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes the rewards campaign stats contract and user-facing qualification messaging; scope is limited to MAS with unit tests, but behavior depends on an unmerged backend API. > > **Overview** > Aligns the Money Account Sweepstakes client with the backend rule that **net new deposits since join** (not intra-day balance minimum) determine daily entries. > > **Stats API & types:** Replaces `todayMinUsd` with `qualifyingDepositsUsd` and `qualifyingThresholdUsd`. Splits `todayStatus` from `below_threshold` into `not_yet_qualified` (still winnable today) and `lost_today` (forfeit). Drops unused `currentBalance*` localized strings and swaps `belowThresholdDescription` for `notYetQualifiedDescription` / `lostTodayDescription`. `RewardsController` disabled-feature defaults and cache mapping follow the new shape. > > **Stats tile (`MoneyAccountSweepstakesStatsSummary`):** Shows progress as **`$qualifying / $threshold`** with qualifying amount clamped at zero. Warning styling and danger icon apply only to `lost_today`; `not_yet_qualified` uses a neutral add icon. Info-sheet copy picks the status-specific description. > > **Tests:** MAS fixtures and expectations updated for the new copy and fields (including CTA “no balance” toast strings). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 16d79de. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: sophieqgu <sophieqgu@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Contributor
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
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.
Summary
Validation
Follow-up
qualifyingThresholdUsd: 100to match the PRD. The client intentionally renders the backend value.