fix(balance): $0-balance fix for the mobile build (cherry-pick of #2482) - #2485
Closed
innolope-dev wants to merge 4 commits into
Closed
fix(balance): $0-balance fix for the mobile build (cherry-pick of #2482)#2485innolope-dev wants to merge 4 commits into
innolope-dev wants to merge 4 commits into
Conversation
The home screen's headline number is smart-account balance + Rain spendingPower + Rain inTransit. Both Rain terms come from a single /rain/cards call, and rainCentsToUsdcUnits(undefined) folds them to 0n — so a failed fetch was indistinguishable from 'this user has no collateral'. For a card user whose funds the auto-balancer swept into collateral, the smart account is legitimately 0, and the total cratered to a confident, wrong $0 with no error and no retry affordance. /rain/cards times out at 10s for 621 users (PEANUT-UI-QD5), on web and native alike; native compounds it because the Android WebView GET path is edge-blocked on some devices (PEANUT-UI-R5F). React Query retains the last good data across a failed refetch, so this only bit on a session's first load. Persist the last fully-settled total per user and seed the display from it, so a cold start paints the previous number immediately and corrects it in the background. The cached value is display-only and dimmed while stale — every affordability gate still runs on the live availableSpendableBalance, so a stale number can never green-light a spend into an orphan charge.
…r non-card users Follow-on to the last-known-spendable cache, pairing with the API's new `balanceUnavailable` flag. - treat a response that arrived but couldn't read Rain (flag set, no balance to fall back on) as not-ready, so the displayed total holds the last-known value instead of summing an absent spendingPower as 0. A null balance WITHOUT the flag stays a real zero — a user with no card must still see their plain smart-account total. - a served-but-stale balance is used as-is: it is fresher than the FE's own cache. - stop the 30s /rain/cards poll for users with no card application. It ran for every logged-in user and made this the most-called endpoint, and with it the top source of client-side 10s timeouts, for a payload that reads `hasApplication: false` every time. Card users keep the 30s cadence, and the user_rail_status_changed WebSocket invalidation resumes polling the moment someone applies. - guard on `!!rainOverview` rather than `!== undefined`: a null JSON body would pass the stricter check and then throw on property access.
…limits as $0
Two more instances of the same unknown-coerced-to-zero shape.
- extract isRainBalanceKnown into balance.utils so the display path
(useWallet) and the spend path (useSpendBundle) answer 'can this Rain
figure be trusted' identically. They were never allowed to disagree.
- spendPreflight: when the overview is missing, rainSpendingPower arrives
as 0n and a Rain outage lands in the insufficient branch. Blocking is
still the right call — we can't size a collateral withdrawal we can't
see, and the user already gets BALANCE_SETTLING_MESSAGE ('try again in
a few seconds'), not a false 'not enough funds'. But reporting it as
error_kind 'insufficient' hid the outage inside the card-withdraw
failure rate; it now reports 'rain-balance-unavailable'.
- limits: 'You can add up to $0' when remainingLimit is merely unknown.
Omit the sentence rather than invent a figure.
…s tree The cherry-picked useWalletSpendable.test.tsx carried `// eslint-disable-next-line import/first` directives (fine on the main-based #2482 tree). The mobile-release eslint config doesn't register import/first, so disabling an unknown rule is itself an error here — it was the only thing pushing eslint back above 0. Match the sibling tests' plain-comment convention.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Collaborator
Author
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.
Cherry-picks the three commits from #2482 onto the mobile-release sync branch, so the next build carries the $0-balance fix.
Targets
chore/mobile-release-sync(#2483), notmobile-releasedirectly — the balance commits expect main'sbalance.utils/rain.tscontext, which the sync branch has and rawmobile-releasedoes not. Merge order: #2483 → this. Once both land onmobile-release, the build has: main sync + localization (#2483) + this fix.What it does
Same as #2482 (targeting
main) — see there for the full write-up. In short: a failed/again-missing/rain/cardsread made a card user's spendable total collapse to a confident $0; this persists the last-known-good total, consumes the API'sbalanceUnavailableflag, stops polling/rain/cardsfor non-card users, and stops rendering unknown spend/limit figures as $0.Cherry-pick conflicts (2 files)
Both are files the localization branch in #2483 also touched:
features/limits/utils.ts— the sync branch has a newer structure (amountDisplay,perTransactionSuffix, richeritems.pushwith akinddiscriminator for translation). Re-applied the fix's intent onto that shape:formattedLimit/amountDisplaygo null when the remaining limit is unknown, and the amount item is omitted entirely rather than showing "$0".utils/__tests__/balance.utils.test.ts— pure additive overlap: the sync branch added acomputeExcessCollateralCentsdescribe block, fix(balance): keep last-known spendable total instead of rendering $0 #2482 added anisRainBalanceKnownone, both at the file tail. Kept both.One tree-specific adaptation (separate commit)
useWalletSpendable.test.tsxcarried// eslint-disable-next-line import/firstdirectives — fine on the main-based #2482 tree, but this tree's eslint config doesn't registerimport/first, so disabling an unknown rule is itself an error. Dropped them for the sibling tests' plain-comment convention. This keeps the branch at 0 eslint errors (#2483's headline).Testing
eslint .0 errors (62 warnings, baseline); prettier clean; typecheck cleanDepends on
FE degrades gracefully without the API change, but pairs with peanutprotocol/peanut-api-ts#1227 (
balanceUnavailable).