@@ -16,6 +16,7 @@ import com.getcode.opencode.controllers.TokenController
1616import com.getcode.opencode.exchange.Exchange
1717import com.getcode.opencode.model.financial.Fiat
1818import com.getcode.opencode.model.financial.LocalFiat
19+ import com.getcode.opencode.model.financial.Rate
1920import com.getcode.opencode.model.financial.TokenWithLocalizedBalance
2021import com.getcode.opencode.model.financial.sum
2122import com.getcode.opencode.model.financial.toFiat
@@ -50,13 +51,25 @@ class SelectTokenViewModel @Inject constructor(
5051
5152 data class State (
5253 val purpose : TokenPurpose ,
54+ val rate : Rate = Rate .oneToOne,
5355 val reservesEnabled : Boolean = false ,
5456 val preferredOnRampProvider : OnRampProvider ? = null ,
5557 val tokens : List <TokenWithLocalizedBalance >? = null ,
5658 val selectedToken : Mint ? = null ,
5759 ) {
5860 val totalBalance: LocalFiat
59- get() = tokens.orEmpty().map { it.balance }.sum()
61+ get() {
62+ val set = tokens.orEmpty()
63+ if (set.isEmpty()) {
64+ return LocalFiat .Zero
65+ .copy(
66+ nativeAmount = 0 .toFiat(currencyCode = rate.currency),
67+ rate = rate
68+ )
69+ }
70+
71+ return set.map { it.balance }.sum()
72+ }
6073
6174 val aggregateAppreciation: LocalFiat ?
6275 get() = tokens?.map { it.appreciation }?.sum()
@@ -66,6 +79,8 @@ class SelectTokenViewModel @Inject constructor(
6679 data class OnPreferredOnRampProviderChanged (val provider : OnRampProvider ? ) : Event
6780 data class OnReservesEnabled (val enabled : Boolean ) : Event
6881
82+ data class OnRateChanged (val rate : Rate ): Event
83+
6984 data class OnPurposeChanged (val purpose : TokenPurpose ) : Event
7085 data class OnTokensUpdated (val tokens : List <TokenWithLocalizedBalance >) : Event
7186
@@ -106,32 +121,37 @@ class SelectTokenViewModel @Inject constructor(
106121 TokenPurpose .Deposit -> exchange.observeEntryRate()
107122 }
108123 ) { state, balances, rate ->
124+ dispatchEvent(Event .OnRateChanged (rate))
109125 balances
110126 .map {
127+ val balance = LocalFiat (
128+ usdf = it.balance,
129+ nativeAmount = it.balance.convertingTo(rate),
130+ )
131+
132+ // USD reserves don't appreciate so we track that as MIN_VALUE internally to avoid confusion
133+ // with true zero's.
134+ val appreciation = if (it.appreciation == Fiat .MIN_VALUE ) {
135+ LocalFiat (
136+ usdf = 0 .toFiat(),
137+ nativeAmount = 0 .toFiat(rate.currency),
138+ )
139+ } else {
140+ LocalFiat (
141+ usdf = it.appreciation,
142+ nativeAmount = it.appreciation.convertingTo(rate),
143+ )
144+ }
145+
111146 TokenWithLocalizedBalance (
112147 token = it.token,
113148 displayName = if (it.token.address == Mint .usdf) {
114149 resources.getString(R .string.title_cashReserves)
115150 } else {
116151 it.token.name
117152 },
118- balance = LocalFiat (
119- usdf = it.balance,
120- nativeAmount = it.balance.convertingTo(rate),
121- ),
122- // USD reserves don't appreciate so we track that as MIN_VALUE internally to avoid confusion
123- // with true zero's.
124- appreciation = if (it.appreciation == Fiat .MIN_VALUE ) {
125- LocalFiat (
126- usdf = 0 .toFiat(),
127- nativeAmount = 0 .toFiat(rate.currency),
128- )
129- } else {
130- LocalFiat (
131- usdf = it.appreciation,
132- nativeAmount = it.appreciation.convertingTo(rate),
133- )
134- }
153+ balance = balance,
154+ appreciation = appreciation
135155 )
136156 }
137157 .sortedWith(compareByDescending { item ->
@@ -193,6 +213,10 @@ class SelectTokenViewModel @Inject constructor(
193213 state.copy(reservesEnabled = event.enabled)
194214 }
195215
216+ is Event .OnRateChanged -> { state ->
217+ state.copy(rate = event.rate)
218+ }
219+
196220 is Event .OnPurposeChanged -> { state -> state.copy(purpose = event.purpose) }
197221 is Event .OnTokensUpdated -> { state -> state.copy(tokens = event.tokens) }
198222 is Event .OnTokenSelected -> { state -> state.copy(selectedToken = event.mint) }
0 commit comments