Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ final class AddMoneyProcessingViewModel {
case .processing:
return "This Will Take a Minute"
case .success:
return "\(input.amount.nativeAmount.formatted()) of USDF"
// No "of <currency>" here: adding money always lands in the reserve, so
// "$1.00 of Dollars" only restates what the amount already says.
return input.amount.nativeAmount.formatted()
case .failed:
return "Something Went Wrong"
}
Expand Down
29 changes: 5 additions & 24 deletions Flipcash/Core/Screens/Main/Buy/USDCDepositEducationScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import SwiftUI
import FlipcashCore
import FlipcashUI

/// Pre-flight for the USDC → USDF conversion: explains that incoming Solana
/// USDC is auto-converted 1:1 to USDF on receipt. Pass `onDepositOtherCurrencies`
/// Pre-flight for the USDC → Dollars conversion: explains that incoming Solana
/// USDC is auto-converted 1:1 to Dollars on receipt. Pass `onDepositOtherCurrencies`
/// to expose a subtle escape hatch below Next.
struct USDCDepositEducationScreen: View {

Expand All @@ -33,16 +33,16 @@ struct USDCDepositEducationScreen: View {
VStack(spacing: 24) {
Spacer()

ConversionGraphic()
ConversionGraphic(from: .usdcOnSolana, to: .dollars)
.accessibilityElement(children: .ignore)
.accessibilityLabel("Convert USDC to USDF")
.accessibilityLabel("Convert USDC to Dollars")

VStack(spacing: 8) {
Text("Deposit USDC")
.font(.appTextLarge)
.foregroundStyle(Color.textMain)

Text("Your Solana USDC will be converted 1:1 to USD on Flipcash (USDF)")
Text("Your USDC will be converted 1:1 to Dollars on Flipcash")
.font(.appTextMedium)
.foregroundStyle(Color.textSecondary)
.multilineTextAlignment(.center)
Expand All @@ -68,22 +68,3 @@ struct USDCDepositEducationScreen: View {
.toolbarTitleDisplayMode(.inline)
}
}

private struct ConversionGraphic: View {
var body: some View {
HStack(spacing: 16) {
BadgedIcon(
icon: Image.asset(.buyUSDC),
badge: Image.asset(.buySolana)
)

Image.system(.arrowRight)
.foregroundStyle(Color.textSecondary)

Image.asset(.buyFlipcash)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ class SwapProcessingViewModel {
case .success:
if let exchangedFiat {
switch swapType {
case .convert where targetMint == .usdf:
// Converting into the reserve would read "$1.00 of Dollars" —
// the amount alone already says it.
return exchangedFiat.nativeAmount.formatted()
case .buyWithReserves, .buyWithCurrency, .convert:
// Convert names its destination via `currencyName`, so the
// same "X of <currency>" reads correctly there too.
Expand Down Expand Up @@ -94,8 +98,9 @@ class SwapProcessingViewModel {

private let swapId: SwapId
private let swapType: SwapType
/// The token being bought — analytics-only; nil on the sell path, where
/// `amount.mint` already names the subject token.
/// The token being bought, or a convert's destination; nil on the sell path,
/// where `amount.mint` already names the subject token. Feeds analytics, and
/// the success title's check for a conversion landing in the reserve.
private let targetMint: PublicKey?
private let currencyName: String
private let amount: ExchangedFiat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct WithdrawIntroScreen: View {
VStack(spacing: 24) {
Spacer()

ConversionGraphic()
ConversionGraphic(from: .dollars, to: .usdcOnSolana)
.accessibilityElement(children: .ignore)
.accessibilityLabel("Convert Dollars to USDC")

Expand Down Expand Up @@ -44,22 +44,3 @@ struct WithdrawIntroScreen: View {
.toolbarTitleDisplayMode(.inline)
}
}

private struct ConversionGraphic: View {
var body: some View {
HStack(spacing: 16) {
Image.asset(.buyDollars)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)

Image.system(.arrowRight)
.foregroundStyle(Color.textSecondary)

BadgedIcon(
icon: Image.asset(.buyUSDC),
badge: Image.asset(.buySolana)
)
}
}
}
67 changes: 67 additions & 0 deletions FlipcashUI/Sources/FlipcashUI/Views/ConversionGraphic.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//
// ConversionGraphic.swift
// FlipcashUI
//

import SwiftUI

/// A coin face `ConversionGraphic` can show on either side of the arrow.
public enum ConversionCoin {
/// The gold "Dollars" coin — Flipcash's own reserve currency.
case dollars

/// The USDC coin with the Solana badge on its bottom-trailing corner.
case usdcOnSolana
}

/// The "converted 1:1" education art: two coins separated by an arrow.
///
/// Composed here rather than shipped as one flattened asset so the same art serves both
/// directions — Dollars → USDC when withdrawing, and the inverse when adding money from
/// another wallet.
public struct ConversionGraphic: View {

private let from: ConversionCoin
private let to: ConversionCoin

public init(from: ConversionCoin, to: ConversionCoin) {
self.from = from
self.to = to
}

public var body: some View {
HStack(spacing: 16) {
coin(from)

Image.system(.arrowRight)
.foregroundStyle(Color.textSecondary)

coin(to)
}
}

@ViewBuilder
private func coin(_ coin: ConversionCoin) -> some View {
switch coin {
case .dollars:
Image.asset(.buyDollars)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)

case .usdcOnSolana:
// Badge is an overlay, so the coin still lays out as a flat 100pt square.
BadgedIcon(
icon: Image.asset(.buyUSDC),
badge: Image.asset(.buySolana)
)
}
}
}

#Preview {
VStack(spacing: 40) {
ConversionGraphic(from: .dollars, to: .usdcOnSolana)
ConversionGraphic(from: .usdcOnSolana, to: .dollars)
}
}