This repository was archived by the owner on Mar 26, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 59
Expand file tree
/
Copy pathEarnSceneViewModel.swift
More file actions
127 lines (107 loc) · 3.57 KB
/
Copy pathEarnSceneViewModel.swift
File metadata and controls
127 lines (107 loc) · 3.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright (c). Gem Wallet. All rights reserved.
import BigInt
import Components
import Foundation
import Localization
import Primitives
import Store
import EarnService
import PrimitivesComponents
@MainActor
@Observable
public final class EarnSceneViewModel {
private let earnService: EarnService
private var viewState: StateViewType<Bool> = .loading
public let wallet: Wallet
public let asset: Asset
private let currencyCode: String
public let assetQuery: ObservableQuery<AssetRequest>
public let positionsQuery: ObservableQuery<DelegationsRequest>
public let providersQuery: ObservableQuery<ValidatorsRequest>
public var assetData: AssetData { assetQuery.value }
public var positions: [Delegation] { positionsQuery.value }
public var providers: [DelegationValidator] { providersQuery.value }
public init(
wallet: Wallet,
asset: Asset,
currencyCode: String,
earnService: EarnService
) {
self.wallet = wallet
self.asset = asset
self.currencyCode = currencyCode
self.earnService = earnService
self.assetQuery = ObservableQuery(AssetRequest(walletId: wallet.walletId, assetId: asset.id), initialValue: .with(asset: asset))
self.positionsQuery = ObservableQuery(
DelegationsRequest(walletId: wallet.walletId, assetId: asset.id, providerType: .earn),
initialValue: []
)
self.providersQuery = ObservableQuery(
ValidatorsRequest(chain: asset.id.chain, providerType: .earn),
initialValue: []
)
}
var title: String { Localized.Common.earn }
var assetModel: AssetViewModel {
AssetViewModel(asset: asset)
}
private var apr: Double? {
providers.first.map(\.apr).flatMap { $0 > 0 ? $0 : nil }
?? assetData.metadata.earnApr
}
var aprModel: AprViewModel {
AprViewModel(apr: apr ?? .zero)
}
var showDeposit: Bool {
wallet.canSign && providers.isNotEmpty
}
var depositDestination: AmountInput? {
guard let provider = providers.first else { return nil }
return AmountInput(
type: .earn(.deposit(provider)),
asset: asset
)
}
var emptyContentModel: EmptyContentTypeViewModel {
EmptyContentTypeViewModel(type: .earn(symbol: asset.symbol))
}
var positionModels: [DelegationViewModel] {
positions
.filter { (BigInt($0.base.balance) ?? .zero) > 0 }
.map { DelegationViewModel(delegation: $0, asset: asset, currencyCode: currencyCode) }
}
var hasPositions: Bool {
positionModels.isNotEmpty
}
var showEmptyState: Bool {
!hasPositions && !viewState.isLoading
}
var positionsSectionTitle: String {
hasPositions ? Localized.Perpetual.positions : .empty
}
var providersState: StateViewType<Bool> {
switch viewState {
case .noData: .noData
case .loading: providers.isEmpty ? .loading : .data(true)
case .data: providers.isEmpty ? .noData : .data(true)
case .error(let error): .error(error)
}
}
}
// MARK: - Actions
extension EarnSceneViewModel {
func fetch() async {
viewState = .loading
do {
let address = try wallet.account(for: asset.id.chain).address
try await earnService.update(
walletId: wallet.walletId,
assetId: asset.id,
address: address
)
viewState = .data(true)
} catch {
viewState = .error(error)
}
}
}