Skip to content

feat(tokens): cross-currency buy UI and receipt flow#1094

Merged
bmc08gt merged 6 commits into
code/cashfrom
feat/cross-currency-buy-ui
Jul 17, 2026
Merged

feat(tokens): cross-currency buy UI and receipt flow#1094
bmc08gt merged 6 commits into
code/cashfrom
feat/cross-currency-buy-ui

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Client (UI + ViewModel) layer for buying a launchpad currency with another launchpad currency. Stacked on the service-layer PR #1085base is the service branch, so this diff shows only the UI/VM changes.

What's here

  • Buy receipt screen (TokenBuyReceiptScreen) with a "You Pay" (grossed-up) / "You Receive" breakdown plus amount-to-buy and exchange-fee line items.
  • "Insufficient Balance After Fees" modal that auto-shows on landing the receipt when the pool fee pushes the pay total past the funding token's wallet balance, offering to cap the buy to the maximum affordable amount. Display-only correction — the buy already caps to the balance on-chain via VerifiedFiatCalculator.compute.
  • SwapViewModel: grosses up the entered amount by the funding pool's sell fee (guarding the 100% edge), and shows the amount received of the target token on the success screen.

bmc08gt and others added 6 commits July 16, 2026 16:30
Adds full_amount_exchange_data to the reserve swap client parameters and
treasury/treasury_purchase_amount to the reserve new currency server
parameters for treasury-funded cross-currency swaps.

Signed-off-by: Brandon McAnsh <brandon@bmcreations.dev>
…waps

Handle the reserve new currency flow when the initial buy is funded from a
source mint other than the core mint. The full swap + fee amount is collected
into a server-controlled treasury, sold for the core mint (proceeds routed to
the fee destination), and the new currency is bought using the treasury's own
core mint holdings for a pre-coordinated amount. Mirrors the server's
ReserveTreasuryFundedCreateAndBuySwapHandler; the treasury signs the sell/buy
instructions server-side while the client signs only as the swapper.

- Map treasury/treasuryPurchaseAmount into the NewCurrency server params and
  thread them through the extracted server parameters
- Add buildTreasuryFundedNewCurrencyBuyInstructions and dispatch to it from
  TransactionBuilder.buyNewCurrency when a treasury is present
- Add the fullAmountExchangeData request field and serialize it in the reserve
  client parameters when set
- Cover the new instruction builder with count/program/account tests

Signed-off-by: Brandon McAnsh <brandon@bmcreations.dev>
StatefulSwapRequest carried two sealed types that both drifted toward the
generic word 'kind' on different axes. Give each a name for its actual axis:

- SwapStartKind (Reserve | Stablecoin) -> SwapProgram; field kind -> program
  (which on-chain program the swap runs against)
- SwapDirection (Buy | Sell | WithdrawUsdc | Swap) -> SwapRoute; field
  direction -> route (the source -> destination route)

Also rename the cross-currency route SwapRoute.Swap -> SwapRoute.CrossCurrency
to say what distinguishes it from Buy/Sell (neither side is the core mint). The
cross-currency existing currency swap path is not built client-side yet and
throws NotImplementedError.

Signed-off-by: Brandon McAnsh <brandon@bmcreations.dev>
Implement the client instruction builder for swaps between two existing
launchpad currencies (neither side the core mint), mirroring the server's
ReserveBuySellSwapHandler: transfer the source out of the user's VM swap
account into a temporary account held by the swap authority, sell it for the
core mint, then buy and deposit the destination currency into the user's
destination VM. Dispatch to it from TransactionBuilder.swap for the
SwapRoute.CrossCurrency case (previously threw NotImplementedError), and cover
the builder with count/program/account tests.

Signed-off-by: Brandon McAnsh <brandon@bmcreations.dev>
Expose a crossCurrencySwap entry point through the controller, repository and
service that swaps one launchpad currency directly for another. It builds a
Reserve stateful swap with a SwapRoute.CrossCurrency route and branches on the
destination:

- existing destination -> one-time swap authority; server returns existing
  currency parameters (buy+sell handler)
- freshly-launched stub destination -> owner == swap authority and a
  fullAmountExchangeData valuation over the full swap + fee amount; server
  returns treasury-funded new currency parameters

The response builders for both paths already exist, so this closes the
request-side gap. The caller supplies fullAmountExchangeData (USD-valued,
keyed to the source mint) for the new-currency case.

Signed-off-by: Brandon McAnsh <brandon@bmcreations.dev>
Client layer for buying a launchpad currency with another launchpad
currency, on top of the opencode cross-currency swap service.

- Buy receipt screen with a "You Pay" (grossed-up) / "You Receive"
  breakdown plus the amount-to-buy and exchange-fee line items.
- "Insufficient Balance After Fees" modal that auto-shows on landing
  the receipt when the pool fee pushes the pay total past the funding
  token's wallet balance, offering to cap the buy to the maximum
  affordable amount (display-only correction; the buy already caps to
  the balance on-chain).
- SwapViewModel: gross up the entered amount by the funding pool's
  sell fee (guarding the 100% edge), and show the amount received of
  the target token on the success screen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added area: tokens Token accounts, balances, token info type: feature New functionality labels Jul 17, 2026
Base automatically changed from feat/opencode-treasury-cross-currency-swaps to code/cash July 17, 2026 17:29
@bmc08gt
bmc08gt merged commit 5fac252 into code/cash Jul 17, 2026
3 checks passed
@bmc08gt
bmc08gt deleted the feat/cross-currency-buy-ui branch July 17, 2026 22:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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