feat(tokens): cross-currency buy UI and receipt flow#1094
Merged
Conversation
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>
Base automatically changed from
feat/opencode-treasury-cross-currency-swaps
to
code/cash
July 17, 2026 17:29
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.
Client (UI + ViewModel) layer for buying a launchpad currency with another launchpad currency. Stacked on the service-layer PR #1085 — base is the service branch, so this diff shows only the UI/VM changes.
What's here
TokenBuyReceiptScreen) with a "You Pay" (grossed-up) / "You Receive" breakdown plus amount-to-buy and exchange-fee line items.VerifiedFiatCalculator.compute.