Skip to content
This repository was archived by the owner on Mar 26, 2026. It is now read-only.
Merged
3 changes: 3 additions & 0 deletions Features/FiatConnect/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ let package = Package(
.package(name: "Localization", path: "../../Packages/Localization"),
.package(name: "Store", path: "../../Packages/Store"),
.package(name: "PrimitivesComponents", path: "../../Packages/PrimitivesComponents"),
.package(name: "FeatureServices", path: "../../Packages/FeatureServices"),
],
targets: [
.target(
Expand All @@ -36,6 +37,7 @@ let package = Package(
"Localization",
"Store",
"PrimitivesComponents",
.product(name: "FiatService", package: "FeatureServices"),
],
path: "Sources"
),
Expand All @@ -44,6 +46,7 @@ let package = Package(
dependencies: [
"FiatConnect",
.product(name: "PrimitivesTestKit", package: "Primitives"),
.product(name: "FiatServiceTestKit", package: "FeatureServices"),
],
path: "Tests"
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Primitives
import Store
import Components
import Localization
import Style

public struct FiatConnectNavigationView: View {
@State private var model: FiatSceneViewModel
Expand All @@ -29,6 +30,21 @@ public struct FiatConnectNavigationView: View {
$0.navigationTitle(model.title)
}
)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
NavigationLink(value: Scenes.FiatTransactions()) {
Images.Tabs.activity
}
}
}
.navigationDestination(for: Scenes.FiatTransactions.self) { _ in
FiatTransactionsScene(
model: FiatTransactionsViewModel(
walletId: model.walletId,
service: model.fiatService
)
)
}
.sheet(isPresented: $model.isPresentingFiatProvider) {
SelectableListNavigationStack(
model: model.fiatProviderViewModel,
Expand Down
53 changes: 53 additions & 0 deletions Features/FiatConnect/Sources/Scenes/FiatTransactionsScene.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c). Gem Wallet. All rights reserved.

import SwiftUI
import Components
import Primitives
import Store
import Style
import PrimitivesComponents

public struct FiatTransactionsScene: View {
@State private var model: FiatTransactionsViewModel

public init(model: FiatTransactionsViewModel) {
_model = State(initialValue: model)
}

public var body: some View {
List {
ForEach(model.sections) { section in
Section {
ForEach(section.values) {
let viewModel = FiatTransactionViewModel(info: $0)
if let url = viewModel.detailsUrl {
SafariNavigationLink(url: url) {
ListItemView(model: viewModel.listItemModel)
}
} else {
NavigationCustomLink(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There will be chevron with no action, maybe instead just use ListItemView?

with: ListItemView(model: viewModel.listItemModel),
action: {}
)
}
}
} header: {
section.title.map { Text($0) }
}
}
.listRowInsets(.assetListRowInsets)
}
.overlay {
if model.transactions.isEmpty {
EmptyContentView(model: model.emptyContentModel)
.padding(.horizontal, .medium)
}
}
.contentMargins(.top, .scene.top, for: .scrollContent)
.listSectionSpacing(.compact)
.bindQuery(model.query)
.refreshable { await model.fetch() }
.navigationTitle(model.title)
.task { await model.fetch() }
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import Foundation
import Primitives
import SwiftUI
import GemAPI
import Components
import Style
import Localization
Expand All @@ -12,6 +11,7 @@ import PrimitivesComponents
import Formatters
import Validators
import BigInt
import FiatService

@MainActor
@Observable
Expand All @@ -22,11 +22,11 @@ public final class FiatSceneViewModel {
static let suggestedAmounts: [Int] = [100, 250]
}

private let fiatService: any GemAPIFiatService
let walletId: WalletId
let fiatService: FiatService
private let assetAddress: AssetAddress
private let currencyFormatter: CurrencyFormatter
private let valueFormatter = ValueFormatter(locale: .US, style: .medium)
private let walletId: WalletId

public let assetQuery: ObservableQuery<AssetRequest>
var assetData: AssetData { assetQuery.value }
Expand All @@ -40,7 +40,7 @@ public final class FiatSceneViewModel {
let sellViewModel: FiatOperationViewModel

public init(
fiatService: any GemAPIFiatService,
fiatService: FiatService,
currencyFormatter: CurrencyFormatter = CurrencyFormatter(currencyCode: Currency.usd.rawValue),
assetAddress: AssetAddress,
walletId: WalletId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c). Gem Wallet. All rights reserved.

import Components
import Foundation
import FiatService
import Localization
import Primitives
import PrimitivesComponents
import Store

@Observable
@MainActor
public final class FiatTransactionsViewModel {
private let service: FiatService
let walletId: WalletId

public let query: ObservableQuery<FiatTransactionsRequest>
var transactions: [FiatTransactionInfo] { query.value }

var sections: [ListSection<FiatTransactionInfo>] {
DateSectionBuilder(items: transactions, dateKeyPath: \.transaction.createdAt).build()
}

public init(walletId: WalletId, service: FiatService) {
self.walletId = walletId
self.service = service
self.query = ObservableQuery(FiatTransactionsRequest(walletId: walletId), initialValue: [])
}

var title: String { Localized.Activity.title }

var emptyContentModel: EmptyContentTypeViewModel {
EmptyContentTypeViewModel(type: .activity(isViewOnly: false))
}

func fetch() async {
do {
try await service.updateTransactions(walletId: walletId)
} catch {
debugLog("FiatTransactionsViewModel fetch error: \(error)")
}
Comment thread
DRadmir marked this conversation as resolved.
}
}
7 changes: 4 additions & 3 deletions Features/FiatConnect/Tests/FiatSceneViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,25 @@

import Foundation
import Testing
import GemAPI
import Primitives
import PrimitivesTestKit
import Formatters
import FiatService
import FiatServiceTestKit
import BigInt

@testable import FiatConnect

@MainActor
final class FiatSceneViewModelTests {
private static func mock(
service: any GemAPIFiatService = GemAPIService(),
fiatService: FiatService = .mock(),
currencyFormatter: CurrencyFormatter = .init(locale: Locale.US, currencyCode: Currency.usd.rawValue),
assetAddress: AssetAddress = .mock(),
walletId: WalletId = .mock()
) -> FiatSceneViewModel {
FiatSceneViewModel(
fiatService: service,
fiatService: fiatService,
currencyFormatter: currencyFormatter,
assetAddress: assetAddress,
walletId: walletId
Expand Down
4 changes: 3 additions & 1 deletion Features/Transfer/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ let package = Package(
.product(name: "ExplorerService", package: "ChainServices"),
.product(name: "NameService", package: "ChainServices"),
.product(name: "AddressNameService", package: "FeatureServices"),
.product(name: "ActivityService", package: "FeatureServices")
.product(name: "ActivityService", package: "FeatureServices"),
.product(name: "FiatService", package: "FeatureServices")
],
path: "Sources"
),
Expand Down Expand Up @@ -120,6 +121,7 @@ let package = Package(
.product(name: "NFTServiceTestKit", package: "FeatureServices"),
.product(name: "SignerTestKit", package: "Signer"),
.product(name: "EarnServiceTestKit", package: "FeatureServices"),
.product(name: "FiatServiceTestKit", package: "FeatureServices"),
.product(name: "EventPresenterServiceTestKit", package: "EventPresenterService"),
],
path: "Tests"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import Perpetuals
import Preferences

public struct AmountNavigationView: View {
@Environment(\.fiatService) private var fiatService
@State private var model: AmountSceneViewModel

public init(model: AmountSceneViewModel) {
Expand All @@ -30,7 +29,7 @@ public struct AmountNavigationView: View {
case let .fiatConnect(assetAddress, walletId):
NavigationStack {
FiatConnectNavigationView(
model: FiatSceneViewModel(fiatService: fiatService, assetAddress: assetAddress, walletId: walletId)
model: FiatSceneViewModel(fiatService: model.fiatService, assetAddress: assetAddress, walletId: walletId)
)
.navigationBarTitleDisplayMode(.inline)
.toolbar { ToolbarDismissItem(type: .close, placement: .topBarLeading) }
Expand Down
3 changes: 1 addition & 2 deletions Features/Transfer/Sources/Scenes/ConfirmTransferScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import Preferences
import Primitives

public struct ConfirmTransferScene: View {
@Environment(\.fiatService) private var fiatService
@State private var model: ConfirmTransferSceneViewModel

public init(model: ConfirmTransferSceneViewModel) {
Expand Down Expand Up @@ -63,7 +62,7 @@ public struct ConfirmTransferScene: View {
NavigationStack {
FiatConnectNavigationView(
model: FiatSceneViewModel(
fiatService: fiatService,
fiatService: model.fiatService,
assetAddress: assetAddress,
walletId: walletId
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import BigInt
import Components
import FiatService
import Formatters
import Foundation
import InfoSheet
Expand All @@ -19,6 +20,7 @@ import Validators
public final class AmountSceneViewModel {
private let wallet: Wallet
private let onTransferAction: TransferDataAction
let fiatService: FiatService

private let formatter = ValueFormatter(style: .full)
private let valueConverter = ValueConverter()
Expand All @@ -40,11 +42,13 @@ public final class AmountSceneViewModel {
input: AmountInput,
wallet: Wallet,
service: AmountService,
fiatService: FiatService,
preferences: Preferences = .standard,
onTransferAction: TransferDataAction
) {
self.wallet = wallet
self.onTransferAction = onTransferAction
self.fiatService = fiatService
self.currencyFormatter = CurrencyFormatter(type: .currency, currencyCode: preferences.currency)
self.provider = .make(from: input, wallet: wallet, service: service)
self.assetQuery = ObservableQuery(AssetRequest(walletId: wallet.walletId, assetId: input.asset.id), initialValue: .with(asset: input.asset))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import WalletConnector
import InfoSheet
import Validators
import SwiftUI
import FiatService
import Swap

@Observable
@MainActor
public final class ConfirmTransferSceneViewModel {
let fiatService: FiatService
var feeModel: NetworkFeeSceneViewModel
var state: StateViewType<TransactionInputViewModel> = .loading {
didSet {
Expand Down Expand Up @@ -56,6 +58,7 @@ public final class ConfirmTransferSceneViewModel {
data: TransferData,
confirmService: ConfirmService,
simulationService: ConfirmSimulationService,
fiatService: FiatService,
confirmTransferDelegate: TransferDataCallback.ConfirmTransferDelegate? = .none,
simulation: SimulationResult? = nil,
onComplete: VoidAction
Expand All @@ -64,6 +67,7 @@ public final class ConfirmTransferSceneViewModel {
self.transferData = data
self.confirmService = confirmService
self.simulationService = simulationService
self.fiatService = fiatService
self.confirmTransferDelegate = confirmTransferDelegate
self.simulation = simulation
self.onComplete = onComplete
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Testing
import PrimitivesTestKit
import Primitives
import EarnServiceTestKit
import FiatServiceTestKit

@testable import Transfer
@testable import Store
Expand Down Expand Up @@ -160,6 +161,7 @@ extension AmountSceneViewModel {
input: AmountInput(type: type, asset: assetData.asset),
wallet: .mock(),
service: AmountService(earnDataProvider: MockEarnService()),
fiatService: .mock(),
onTransferAction: { _ in }
)
model.assetQuery.value = assetData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import AddressNameServiceTestKit
import ActivityServiceTestKit
import EventPresenterService
import EventPresenterServiceTestKit
import FiatServiceTestKit
import Store
import BigInt
import Components
Expand Down Expand Up @@ -472,6 +473,7 @@ private extension ConfirmTransferSceneViewModel {
addressNameService: addressNameService,
assetsService: .mock()
),
fiatService: .mock(),
simulation: simulation,
onComplete: {}
)
Expand Down
Loading
Loading