Skip to content

Commit 8d0cd69

Browse files
authored
feat(deposit): invert the conversion graphic for USDC deposits (#620)
* feat(deposit): show a USDC to Dollars conversion graphic The USDC deposit education screen, reached from Add Money -> Other Wallet, pointed its arrow the wrong way for a deposit and spelled the reserve as "USDF". Both this screen and WithdrawIntroScreen carried their own private copy of the same two-coins-and-an-arrow art, so promote it to FlipcashUI as ConversionGraphic, parameterised by which coin sits on each side, and have both call it. Mirrors the Android component of the same name. Copy drops the USDF branding. The "Deposit USDC" title stays as-is; the UI-test page object asserts on it. * fix(swap): drop the "of X" suffix when a swap lands in Dollars The processing success title reads "<amount> of <currency>", which names what the user received. That only helps when the destination is a community currency: adding money and converting into the reserve both rendered "$1.00 of Dollars", where the amount alone already said it. Suppress the suffix for those two, keeping it everywhere it still reads correctly. A convert already carries its destination as targetMint, so the check costs nothing to thread through.
1 parent 1fd371d commit 8d0cd69

5 files changed

Lines changed: 83 additions & 47 deletions

File tree

‎Flipcash/Core/Screens/Main/AddMoney/AddMoneyProcessingViewModel.swift‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ final class AddMoneyProcessingViewModel {
3333
case .processing:
3434
return "This Will Take a Minute"
3535
case .success:
36-
return "\(input.amount.nativeAmount.formatted()) of USDF"
36+
// No "of <currency>" here: adding money always lands in the reserve, so
37+
// "$1.00 of Dollars" only restates what the amount already says.
38+
return input.amount.nativeAmount.formatted()
3739
case .failed:
3840
return "Something Went Wrong"
3941
}

‎Flipcash/Core/Screens/Main/Buy/USDCDepositEducationScreen.swift‎

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import SwiftUI
99
import FlipcashCore
1010
import FlipcashUI
1111

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

@@ -33,16 +33,16 @@ struct USDCDepositEducationScreen: View {
3333
VStack(spacing: 24) {
3434
Spacer()
3535

36-
ConversionGraphic()
36+
ConversionGraphic(from: .usdcOnSolana, to: .dollars)
3737
.accessibilityElement(children: .ignore)
38-
.accessibilityLabel("Convert USDC to USDF")
38+
.accessibilityLabel("Convert USDC to Dollars")
3939

4040
VStack(spacing: 8) {
4141
Text("Deposit USDC")
4242
.font(.appTextLarge)
4343
.foregroundStyle(Color.textMain)
4444

45-
Text("Your Solana USDC will be converted 1:1 to USD on Flipcash (USDF)")
45+
Text("Your USDC will be converted 1:1 to Dollars on Flipcash")
4646
.font(.appTextMedium)
4747
.foregroundStyle(Color.textSecondary)
4848
.multilineTextAlignment(.center)
@@ -68,22 +68,3 @@ struct USDCDepositEducationScreen: View {
6868
.toolbarTitleDisplayMode(.inline)
6969
}
7070
}
71-
72-
private struct ConversionGraphic: View {
73-
var body: some View {
74-
HStack(spacing: 16) {
75-
BadgedIcon(
76-
icon: Image.asset(.buyUSDC),
77-
badge: Image.asset(.buySolana)
78-
)
79-
80-
Image.system(.arrowRight)
81-
.foregroundStyle(Color.textSecondary)
82-
83-
Image.asset(.buyFlipcash)
84-
.resizable()
85-
.aspectRatio(contentMode: .fit)
86-
.frame(width: 100, height: 100)
87-
}
88-
}
89-
}

‎Flipcash/Core/Screens/Main/Currency Swap/SwapProcessingViewModel.swift‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ class SwapProcessingViewModel {
2525
case .success:
2626
if let exchangedFiat {
2727
switch swapType {
28+
case .convert where targetMint == .usdf:
29+
// Converting into the reserve would read "$1.00 of Dollars" —
30+
// the amount alone already says it.
31+
return exchangedFiat.nativeAmount.formatted()
2832
case .buyWithReserves, .buyWithCurrency, .convert:
2933
// Convert names its destination via `currencyName`, so the
3034
// same "X of <currency>" reads correctly there too.
@@ -94,8 +98,9 @@ class SwapProcessingViewModel {
9498

9599
private let swapId: SwapId
96100
private let swapType: SwapType
97-
/// The token being bought — analytics-only; nil on the sell path, where
98-
/// `amount.mint` already names the subject token.
101+
/// The token being bought, or a convert's destination; nil on the sell path,
102+
/// where `amount.mint` already names the subject token. Feeds analytics, and
103+
/// the success title's check for a conversion landing in the reserve.
99104
private let targetMint: PublicKey?
100105
private let currencyName: String
101106
private let amount: ExchangedFiat

‎Flipcash/Core/Screens/Settings/Withdraw/WithdrawIntroScreen.swift‎

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct WithdrawIntroScreen: View {
1616
VStack(spacing: 24) {
1717
Spacer()
1818

19-
ConversionGraphic()
19+
ConversionGraphic(from: .dollars, to: .usdcOnSolana)
2020
.accessibilityElement(children: .ignore)
2121
.accessibilityLabel("Convert Dollars to USDC")
2222

@@ -44,22 +44,3 @@ struct WithdrawIntroScreen: View {
4444
.toolbarTitleDisplayMode(.inline)
4545
}
4646
}
47-
48-
private struct ConversionGraphic: View {
49-
var body: some View {
50-
HStack(spacing: 16) {
51-
Image.asset(.buyDollars)
52-
.resizable()
53-
.aspectRatio(contentMode: .fit)
54-
.frame(width: 100, height: 100)
55-
56-
Image.system(.arrowRight)
57-
.foregroundStyle(Color.textSecondary)
58-
59-
BadgedIcon(
60-
icon: Image.asset(.buyUSDC),
61-
badge: Image.asset(.buySolana)
62-
)
63-
}
64-
}
65-
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//
2+
// ConversionGraphic.swift
3+
// FlipcashUI
4+
//
5+
6+
import SwiftUI
7+
8+
/// A coin face `ConversionGraphic` can show on either side of the arrow.
9+
public enum ConversionCoin {
10+
/// The gold "Dollars" coin — Flipcash's own reserve currency.
11+
case dollars
12+
13+
/// The USDC coin with the Solana badge on its bottom-trailing corner.
14+
case usdcOnSolana
15+
}
16+
17+
/// The "converted 1:1" education art: two coins separated by an arrow.
18+
///
19+
/// Composed here rather than shipped as one flattened asset so the same art serves both
20+
/// directions — Dollars → USDC when withdrawing, and the inverse when adding money from
21+
/// another wallet.
22+
public struct ConversionGraphic: View {
23+
24+
private let from: ConversionCoin
25+
private let to: ConversionCoin
26+
27+
public init(from: ConversionCoin, to: ConversionCoin) {
28+
self.from = from
29+
self.to = to
30+
}
31+
32+
public var body: some View {
33+
HStack(spacing: 16) {
34+
coin(from)
35+
36+
Image.system(.arrowRight)
37+
.foregroundStyle(Color.textSecondary)
38+
39+
coin(to)
40+
}
41+
}
42+
43+
@ViewBuilder
44+
private func coin(_ coin: ConversionCoin) -> some View {
45+
switch coin {
46+
case .dollars:
47+
Image.asset(.buyDollars)
48+
.resizable()
49+
.aspectRatio(contentMode: .fit)
50+
.frame(width: 100, height: 100)
51+
52+
case .usdcOnSolana:
53+
// Badge is an overlay, so the coin still lays out as a flat 100pt square.
54+
BadgedIcon(
55+
icon: Image.asset(.buyUSDC),
56+
badge: Image.asset(.buySolana)
57+
)
58+
}
59+
}
60+
}
61+
62+
#Preview {
63+
VStack(spacing: 40) {
64+
ConversionGraphic(from: .dollars, to: .usdcOnSolana)
65+
ConversionGraphic(from: .usdcOnSolana, to: .dollars)
66+
}
67+
}

0 commit comments

Comments
 (0)