Skip to content

feat: deposit-first "Add Money" UX#1045

Open
bmc08gt wants to merge 13 commits into
code/cashfrom
feat/add-money-ux
Open

feat: deposit-first "Add Money" UX#1045
bmc08gt wants to merge 13 commits into
code/cashfrom
feat/add-money-ux

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

Reworks buying and funding into a deposit-first "Add Money" flow: instead of sending users straight into a token purchase, we gate on USDF reserves and route them to add money first (Phantom, Coinbase, or external USDC), then complete the action. Adds the Coinbase and Phantom rails to make that deposit real, plus supporting UX (menu labels, profile contact states) and a handful of related fixes.

Gated behind the existing AddMoneyUX (deposit_first_ux_enabled) flag; the pre-flag paths are preserved.

What's included

Add Money-first core

  • Gate token buys on USDF reserves; over-reserve buys route to "Add Money" instead of a direct purchase.
  • Deposit-options navigation events and a reserves check wired through the swap and currency-creator flows.
  • Currency-creator: gate the intro on USDF reserves and surface insufficient-balance prompts.

Payment rails

  • Phantom: deposit-first flow connects the wallet, then routes to amount entry; confirming the amount triggers the Phantom transaction.
  • Coinbase: default add-money purchases to USDC delivered to the owner's ATA, converted to USDF by UsdcDepositSweep (deposit path). purchaseCurrency is parameterized and the region buy-options cache strategy is removed.
  • Coinbase email verification is now optional: email entry is always required, but the requireCoinbaseEmailVerification flag controls only verification. When off, the entered email skips the server round-trip and is persisted locally on the profile as unverified; when on, the existing verification flow runs. The synthetic <phone>@flipcash.com fallback is removed.

Supporting UX & fixes

  • Menu tiles show "Add Money" / "Withdraw Money" when AddMoneyUX is on.
  • hasGiveableBalance excludes USDF unless the GiveUsdf flag is on (and re-evaluates on flag toggle).
  • Profile contacts modeled as VerifiableContactMethod (value + verified), with verifiedPhoneNumber/verifiedEmailAddress kept as derived accessors. The user-profile screen now shows unverified phone/email with a verified/unverified status badge and an icon-only linked-for-payments indicator.
  • Return-to-origin fixes for deposits launched from token info and currency creator (no longer dismiss the whole sheet).

Feature flags

  • AddMoneyUX (deposit_first_ux_enabled) — deposit-first behavior.
  • GiveUsdf (give_usdf_enabled) — USDF counts as giveable.
  • requireCoinbaseEmailVerification — Coinbase email verification (server) vs. local-only entry.

Testing

  • Unit/Robolectric suites updated and passing across services:flipcash, shared:profile, shared:persistence:{db,sources}, shared:onramp:coinbase, shared:tokens, and features:myaccount; app compiles.
  • Added coverage for resolveEmail (flag on/off), local-unverified profile writes, the profile-refresh merge, and the profile-screen badges.

Notes

  • Assumes the backend honors requireCoinbaseEmailVerification when issuing the Coinbase JWT (confirmed): with the flag off it accepts an unverified email.
  • PhoneRegion / CoinbaseApi.getBuyOptions remain in the tree but are now unused by production.

bmc08gt added 12 commits July 7, 2026 15:07
…icon

Adds a Plain payment action variant rendering a plain Google Pay icon on the
purchase-method sheet, used by the deposit ("Add Money") flow.

Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
… type

Replaces AmountEntryStyle.actionLabel: String with a sealed AmountEntryLabel
(Plain text, or Annotated for a composable label with inline content such as a
wallet icon). Threads it through AmountEntryAction/Screen and updates all
callers (cash, withdrawal, chat, swap). The swap buy-via-Phantom label uses the
Annotated variant to render the Phantom icon.

Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
Renames the DepositFirstUX flag to AddMoneyUX and reframes getting funds into
the app around "Add Money" (deposit into USDF reserves). Adds per-context
"No Balance Yet" messaging, an "Adding Money" processing title, Phantom add-money
copy, and routes Phantom deposits straight to the connect step. Threads the flag
through balance/menu/chat/session/token-info and adds the swap-side add-money
label + (still-empty) mustAddMoney branch.

Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
Adds !isAddingMoney guards so pinned Coinbase/Phantom "add money" purposes
(mint = USDF) always take the pinned-method path instead of "buy directly" or
the add-money re-route, which only apply to token buys funded from USDF reserves.

Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
Adds Event.PresentDepositOptions (presents the add-money/deposit sheet via
purchaseMethodController.presentDepositOptions, or the USDC deposit flow when
AddMoneyUX is off) and Event.OpenScreen, which SwapEntryScreen observes to
navigate. Nothing dispatches PresentDepositOptions from the buy path yet.

Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
When a token buy exceeds available USDF reserves and deposit-first UX is on, the
mustAddMoney branch now dispatches PresentDepositOptions to send the user to the
add-money/deposit flow instead of doing nothing.

Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
… to VM

Injects FeatureFlagController and adds OnIntroContinue (checks AddMoneyUX +
USDF reserves; shows the "No Balance Yet" dialog routing to add-money, else
emits AdvanceFromInfo), PresentDepositOptions, and OpenScreen events. Adds the
featureflags module dependency. Screen wiring follows in a separate commit.

Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
Routes the intro "Get Started" button through the ViewModel: it dispatches
OnIntroContinue, which shows the "No Balance Yet" add-money dialog when reserves
are missing (deposit-first UX) or advances to name selection otherwise. The
screen observes AdvanceFromInfo/OpenScreen to drive navigation.

Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
In the deposit-first "Add Money" via Phantom flow, navigate to the amount
entry screen after connecting the wallet instead of the transaction
confirmation gate. Confirming the entered amount now triggers the Phantom
transaction request directly.

Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
Show "Add Money"/"Withdraw Money" tile labels when the AddMoneyUX flag is
enabled, falling back to "Deposit"/"Withdraw" otherwise. Tighten the
Phantom purchase-option button icon padding.

Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
hasGiveableBalance() now filters out USDF unless the GiveUsdf flag is
enabled, so a USDF-only balance no longer counts as giveable. Re-evaluate
the session's giveable state on GiveUsdf toggles, not just balance changes.

Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
Default Coinbase add-money purchases to USDC delivered to the owner's ATA, where UsdcDepositSweep converts it to USDF via the DepositSubmitted path. Parameterize purchaseCurrency on the order request and drop the region-based buy-options cache strategy.

Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
@bmc08gt bmc08gt self-assigned this Jul 7, 2026
@github-actions github-actions Bot added type: feature New functionality area: payments Payments, transfers, intents, billing area: network gRPC, connectivity, API, exchange rates area: onramp Deposit, purchase, Coinbase, fiat on-ramp area: tokens Token accounts, balances, token info area: session area: onboarding and removed type: feature New functionality labels Jul 7, 2026
Email entry is always required for the Coinbase add-money flow, but the requireCoinbaseEmailVerification flag now only controls verification. When it is off, the entered email skips the server round-trip and is persisted locally on the profile as unverified, then used for the Coinbase order; when on, the existing server verification flow runs. The synthetic phone@flipcash.com fallback is removed.

To support this, profile phone/email are modeled as VerifiableContactMethod (value + verified) with verifiedPhoneNumber/verifiedEmailAddress kept as derived accessors; ProfileController preserves locally-entered unverified contacts across refreshes; and the user profile screen surfaces unverified contacts with a verified/unverified status badge.

Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
@bmc08gt bmc08gt force-pushed the feat/add-money-ux branch from 3abc328 to 61b4789 Compare July 8, 2026 02:45
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: session area: tokens Token accounts, balances, token info type: feature New functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant