Qa - #2576
Merged
Merged
Qa#2576
Conversation
qa reverted the tier-upgrade feature in the 18 reverts merged with #2561. This branch builds on that feature, so a plain merge would delete the code it changes and leave it importing modules that no longer exist. This merge brings in everything else qa has gained since the branch point (the deposit rework, the 0.03% fee notice, issuer-based deposit routing) and keeps the feature: every path the reverts removed is back in its pre-revert state, with this branch's refinements on top. Built as qa, plus the exact inverse of the reverts (a1e3912..03c17c2), plus this branch. qa's post-revert changes apply unchanged over the restored feature. The only file both touch is constants/modals.ts, where TIER_UPGRADE_MODAL returns beside qa's removal of OPEN_DEPOSIT_CHAIN. store/useDepositStore.ts takes qa's changes and this branch's upgradeTopUp slice together. Merging this PR therefore brings the tier-upgrade feature back to qa. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E6iamcwoqjwq77x9kDCPzR
qa now opens "Select token" first from Crypto and has deleted the "Select chain" step (a1e3912, 6ee35e0), so DEPOSIT_MODAL.OPEN_DEPOSIT_CHAIN no longer exists. The chooser test asserted that an ordinary Crypto press opens it, which failed once qa was merged. The soFUSE top-up test's negative check against it passed vacuously, since it compared against undefined. Both now name the step Crypto opens on a phone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E6iamcwoqjwq77x9kDCPzR
…p-20260923 Refine rewards tier upgrade and top-up flows
The backend now reports `legacyFuseOnly` on the membership state: whether the user's tier rests on FUSE sitting in Savings and nothing else. That route is being retired, and when it is switched off everyone it was carrying drops to Core in the same instant. The type only, so the app can be given a migration prompt without another backend round trip. False for anyone who has also locked or subscribed — nothing about the change can reach them, so there is nothing to warn them about. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XGzkz4QFpEZVg6GpNH311x
Carry the legacy skip-the-line flag through to the app
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VhnDQhJoWUKneB9KFcZgfV
…ase-2xrzv5 Rewards v3 prod release: merge master into qa
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. Review scope:
🤖 Generated with Claude Code |
Each tier's page said "Unlocks at 5M points" and opened a "how to earn points" sheet whether or not points could still reach that tier. Once the ladder is retired, or for anyone the grandfather list leaves nothing to, that advertises a route the backend refuses. The page now follows the membership state's pointsUnlockEnabled. The backend reports it per user: can points still take this user higher? When that is false, the line reads "Unlocks with a membership" if a lock or an annual charge is on sale for the tier, and is hidden otherwise. The points sheet goes in both cases. While the state is loading, the page keeps v2's copy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VhnDQhJoWUKneB9KFcZgfV
…ase-2xrzv5 Drop the points copy from the benefits screen once points can't unlock
Adds a USD deposit rail paid from Cash App. Selecting USD under "Deposit with cash" now opens a chooser — "Wire transfer, ACH" (the virtual account) or "Cash App" — instead of going straight to the bank rail. Outside the US the chooser is skipped, because one option is a question with one answer. The flow is amount → invoice → status, with the invoice screen acting as the review step: it shows the sats, fee and delivery Orchestra actually quoted, and nothing is charged until it is paid. There is no live quote on the amount screen by design — /estimate prices in sats only, with no fiat parameter at any spelling, and the app has no spot source, so a dollar figure there could only be quoted against a rate Orchestra never agreed to. Everything goes through our own backend at /accounts/v1/orchestra, which holds the Orchestra server key. The app carries no Orchestra credential: the recipient is the Safe the server resolves from the session, and availability — region plus allowlist — is the server's verdict, which it enforces again on order creation rather than trusting a hidden row. Status is streamed over SSE where EventSource exists and polled at the documented three seconds everywhere else, which is every native build. The poll keeps running underneath a healthy stream: frames carry only the status, and a reconnect does not replay what was missed. Amounts are formatted from smallest units with BigInt and grouped by hand, because Hermes and the React Native Web Intl shim throw on a BigInt passed to Intl.NumberFormat — Node's does not, so the tests alone would not have caught it. There is now a test that makes Intl behave the way the app's runtime does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The modal header is a three-part row: a 50px back button, the title, and the close button. The title's container had no flex constraint and the title itself no line limit, so a long one took its natural width and shoved both controls out of the header. They were still mounted, just off-screen — which on the Cash App amount step left a modal with no visible way back. The no-title branch already used `flex-1`; the title branch never did. It now takes the space between the two controls and truncates to one line rather than growing past them. Also shortens that step's own title from "Deposit with Cash App" to "Cash App". It is reached by tapping a row already labelled Cash App, from a screen titled "Deposit US Dollars", so the longer version was repeating context to earn a truncation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The config query fired on mount with countryCode still undefined. The server correctly answers "not available" to a request that names no region — but the amount screen read that as a verdict on the user and bounced them to the error screen, a beat before the real answer arrived. The hook kept its detected country in local state rather than the country store, so every mount started at undefined and each screen re-ran the race independently. The cause was that "we don't know yet" and "we looked and couldn't tell" were the same value. They are different answers: the first must not be acted on, the second is final. The hook now reports isResolving separately from isResolved, and every /config call waits for it. This only ever hit users who are not on the allowlist — an allowlisted username short-circuits the region check server-side, which is why it survived testing on an allowlisted account. The invoice and status screens also now pass the country, so all four call sites share one cache entry instead of firing a second request under ['orchestraConfig', undefined]. Their amounts were never wrong — decimals come from /v2/routes and do not depend on the country — but that entry cached isAvailable: false, which was a trap for anyone adding a gate to those screens later. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Gating /config on the geo lookup fixed the false "not available" bounce, but left each screen restarting the lookup from scratch: the hook kept its result in component state, so arriving at the invoice screen held its config call off for a frame and flashed empty amounts. detectGeo already memoises the request; what was missing was the settled result. Holding it at module scope lets a later mount start with the answer in hand — its first render is already settled, which is what the new test asserts rather than whatever state the mount eventually reaches. Exports a reset for tests, because module state would otherwise leak between cases. Also replaces the reassign-an-outer-binding pattern in this spec with collection into an array: the react-compiler rule counts the former as a render side-effect, and the file had been failing that rule. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nramp Claude/orchestra cash app onramp
This branch was successfully deployed
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.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.