Updated on 2026-08-14
This commit is contained in:
parent
03428178ff
commit
bd3ab3e125
8 changed files with 204 additions and 21 deletions
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.tap.features.wallet.models
|
||||
|
||||
import com.tangem.tap.common.redux.global.FiatCurrencyName
|
||||
import java.math.BigDecimal
|
||||
|
||||
data class TotalBalance(
|
||||
val state: State,
|
||||
val fiatAmount: BigDecimal,
|
||||
val fiatCurrencyName: FiatCurrencyName,
|
||||
) {
|
||||
enum class State {
|
||||
Loading,
|
||||
Failed,
|
||||
Success
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ import com.tangem.tap.domain.tokens.BlockchainNetwork
|
|||
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
|
||||
import com.tangem.tap.features.tokens.redux.TokenWithBlockchain
|
||||
import com.tangem.tap.features.wallet.models.PendingTransaction
|
||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
||||
import com.tangem.tap.features.wallet.models.toPendingTransactions
|
||||
import com.tangem.tap.features.wallet.models.toPendingTransactionsForToken
|
||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
||||
|
|
@ -44,6 +45,7 @@ data class WalletState(
|
|||
val primaryBlockchain: Blockchain? = null,
|
||||
val primaryToken: Token? = null,
|
||||
val isTestnet: Boolean = false,
|
||||
val totalBalance: TotalBalance? = null,
|
||||
) : StateType {
|
||||
|
||||
// if you do not delegate - the application crashes on startup,
|
||||
|
|
@ -196,18 +198,20 @@ data class WalletState(
|
|||
return copy(wallets = replaceWalletInWallets(walletStore))
|
||||
}
|
||||
|
||||
fun updateWalletStores(walletStores: List<WalletStore>): WalletState {
|
||||
val walletStores = walletStores.toMutableList()
|
||||
private fun updateWalletStores(walletStores: List<WalletStore>): WalletState {
|
||||
val walletStoresMutable = walletStores.toMutableList()
|
||||
val updatedWallets = wallets.map { oldWalletStore ->
|
||||
val walletStore = walletStores.find { it.blockchainNetwork == oldWalletStore.blockchainNetwork }
|
||||
val walletStore = walletStoresMutable.find {
|
||||
it.blockchainNetwork == oldWalletStore.blockchainNetwork
|
||||
}
|
||||
if (walletStore != null) {
|
||||
walletStores.remove(walletStore)
|
||||
walletStoresMutable.remove(walletStore)
|
||||
walletStore
|
||||
} else {
|
||||
oldWalletStore
|
||||
}
|
||||
}
|
||||
return copy(wallets = updatedWallets + walletStores)
|
||||
return copy(wallets = updatedWallets + walletStoresMutable)
|
||||
}
|
||||
|
||||
fun removeWallet(walletData: WalletData?): WalletState {
|
||||
|
|
@ -268,6 +272,14 @@ data class WalletState(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateTotalBalance(
|
||||
totalBalance: TotalBalance
|
||||
): WalletState {
|
||||
return this.copy(
|
||||
totalBalance = totalBalance
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
sealed class WalletDialog : StateDialog {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.tangem.tap.common.extensions.toFormattedCurrencyString
|
|||
import com.tangem.tap.common.extensions.toFormattedFiatValue
|
||||
import com.tangem.tap.domain.getFirstToken
|
||||
import com.tangem.tap.domain.tokens.BlockchainNetwork
|
||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
||||
import com.tangem.tap.features.wallet.models.removeUnknownTransactions
|
||||
import com.tangem.tap.features.wallet.models.toPendingTransactions
|
||||
import com.tangem.tap.features.wallet.redux.*
|
||||
|
|
@ -16,6 +17,7 @@ import com.tangem.tap.features.wallet.ui.BalanceStatus
|
|||
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
|
||||
import com.tangem.tap.features.wallet.ui.TokenData
|
||||
import com.tangem.tap.store
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
||||
class OnWalletLoadedReducer {
|
||||
|
|
@ -33,13 +35,12 @@ class OnWalletLoadedReducer {
|
|||
blockchainNetwork: BlockchainNetwork,
|
||||
walletState: WalletState
|
||||
): WalletState {
|
||||
val walletData = walletState.getWalletData(blockchainNetwork) ?: return walletState
|
||||
|
||||
val fiatCurrencySymbol = store.state.globalState.appCurrency
|
||||
val exchangeManager = store.state.globalState.currencyExchangeManager
|
||||
|
||||
val coinAmountValue = wallet.amounts[AmountType.Coin]?.value
|
||||
if (walletState.getWalletData(blockchainNetwork) == null) {
|
||||
return walletState
|
||||
}
|
||||
val formattedAmount = coinAmountValue?.toFormattedCurrencyString(
|
||||
wallet.blockchain.decimals(),
|
||||
wallet.blockchain.currency
|
||||
|
|
@ -54,10 +55,9 @@ class OnWalletLoadedReducer {
|
|||
} else {
|
||||
BalanceStatus.VerifiedOnline
|
||||
}
|
||||
val walletData = walletState.getWalletData(blockchainNetwork)
|
||||
|
||||
val fiatAmount = walletData?.fiatRate?.let { coinAmountValue?.toFiatValue(it) }
|
||||
val newWalletData = walletData?.copy(
|
||||
val fiatAmount = walletData.fiatRate?.let { coinAmountValue?.toFiatValue(it) }
|
||||
val newWalletData = walletData.copy(
|
||||
currencyData = walletData.currencyData.copy(
|
||||
status = balanceStatus, currency = wallet.blockchain.fullName,
|
||||
currencySymbol = wallet.blockchain.currency,
|
||||
|
|
@ -87,7 +87,7 @@ class OnWalletLoadedReducer {
|
|||
val tokenFiatAmount =
|
||||
tokenWalletData?.fiatRate?.let { rate -> tokenAmountValue?.toFiatValue(rate) }
|
||||
|
||||
val tokenSendButton = newWalletData?.shouldEnableTokenSendButton() == true
|
||||
val tokenSendButton = newWalletData.shouldEnableTokenSendButton()
|
||||
&& tokenPendingTransactions.isEmpty()
|
||||
tokenWalletData?.copy(
|
||||
currencyData = tokenWalletData.currencyData.copy(
|
||||
|
|
@ -106,18 +106,27 @@ class OnWalletLoadedReducer {
|
|||
tradeCryptoState = TradeCryptoState.from(exchangeManager, tokenWalletData),
|
||||
)
|
||||
}
|
||||
val newWallets = (tokens + newWalletData).mapNotNull { it }
|
||||
val newWallets = tokens + newWalletData
|
||||
val wallets = walletState.replaceSomeWallets((newWallets))
|
||||
|
||||
val totalBalance = TotalBalance(
|
||||
state = wallets.findTotalBalanceState(),
|
||||
fiatAmount = wallets.calculateTotalFiatAmount(),
|
||||
fiatCurrencyName = fiatCurrencySymbol,
|
||||
)
|
||||
|
||||
val state = if (wallets.any { it.currencyData.status == BalanceStatus.Loading }) {
|
||||
ProgressState.Loading
|
||||
} else {
|
||||
ProgressState.Done
|
||||
}
|
||||
val newState = walletState.updateWalletsData(wallets)
|
||||
return newState.copy(
|
||||
state = state, error = null
|
||||
)
|
||||
return walletState
|
||||
.updateWalletsData(wallets)
|
||||
.updateTotalBalance(totalBalance)
|
||||
.copy(
|
||||
state = state,
|
||||
error = null
|
||||
)
|
||||
}
|
||||
|
||||
private fun onSingleWalletLoaded(wallet: Wallet, walletState: WalletState): WalletState {
|
||||
|
|
@ -183,4 +192,48 @@ class OnWalletLoadedReducer {
|
|||
state = ProgressState.Done, error = null
|
||||
)
|
||||
}
|
||||
|
||||
private fun List<WalletData>.findTotalBalanceState(): TotalBalance.State {
|
||||
return this.mapToTotalBalanceState()
|
||||
.fold(initial = TotalBalance.State.Loading) { accState, newState ->
|
||||
accState or newState
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<WalletData>.calculateTotalFiatAmount(): BigDecimal {
|
||||
return this.map { it.currencyData.fiatAmount ?: BigDecimal.ZERO }
|
||||
.reduce(BigDecimal::plus)
|
||||
}
|
||||
|
||||
private fun List<WalletData>.mapToTotalBalanceState(): List<TotalBalance.State> {
|
||||
return this.map {
|
||||
when (it.currencyData.status) {
|
||||
BalanceStatus.VerifiedOnline,
|
||||
BalanceStatus.SameCurrencyTransactionInProgress,
|
||||
BalanceStatus.TransactionInProgress -> TotalBalance.State.Success
|
||||
BalanceStatus.Unreachable,
|
||||
BalanceStatus.NoAccount,
|
||||
BalanceStatus.EmptyCard,
|
||||
BalanceStatus.UnknownBlockchain -> TotalBalance.State.Failed
|
||||
BalanceStatus.Loading,
|
||||
null -> TotalBalance.State.Loading
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
infix fun TotalBalance.State.or(newState: TotalBalance.State): TotalBalance.State {
|
||||
return when (this) {
|
||||
TotalBalance.State.Loading -> when (newState) {
|
||||
TotalBalance.State.Loading -> this
|
||||
TotalBalance.State.Failed,
|
||||
TotalBalance.State.Success -> newState
|
||||
}
|
||||
TotalBalance.State.Success,
|
||||
TotalBalance.State.Failed -> when (newState) {
|
||||
TotalBalance.State.Loading,
|
||||
TotalBalance.State.Failed -> newState
|
||||
TotalBalance.State.Success -> this
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import com.tangem.tap.common.redux.navigation.AppScreen
|
|||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.currenciesRepository
|
||||
import com.tangem.tap.features.tokens.redux.TokensAction
|
||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.WalletDialog
|
||||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
|
|
@ -51,6 +52,7 @@ class MultiWalletView : WalletView {
|
|||
btnScanMultiwallet.show()
|
||||
rvMultiwallet.show()
|
||||
btnAddToken.show()
|
||||
lCardTotalBalance.root.show()
|
||||
setupWalletCardNumber(binding)
|
||||
}
|
||||
|
||||
|
|
@ -97,6 +99,7 @@ class MultiWalletView : WalletView {
|
|||
val fragment = fragment ?: return
|
||||
val binding = binding ?: return
|
||||
|
||||
state.totalBalance?.let { handleTotalBalance(binding, it) }
|
||||
walletsAdapter.submitList(state.walletsData, state.primaryBlockchain, state.primaryToken)
|
||||
|
||||
binding.btnAddToken.setOnClickListener {
|
||||
|
|
@ -127,6 +130,20 @@ class MultiWalletView : WalletView {
|
|||
handleDialogs(state.walletDialog)
|
||||
}
|
||||
|
||||
private fun handleTotalBalance(
|
||||
binding: FragmentWalletBinding,
|
||||
totalBalance: TotalBalance,
|
||||
) = with(binding.lCardTotalBalance) {
|
||||
val fiatAmountFormatted = with(totalBalance) {
|
||||
"${fiatAmount.stripTrailingZeros()} $fiatCurrencyName"
|
||||
}
|
||||
tvBalance.text = fiatAmountFormatted
|
||||
tvCurrencyName.text = totalBalance.fiatCurrencyName
|
||||
tvCurrencyName.setOnClickListener {
|
||||
// TODO: Open app currency selector
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleErrorStates(
|
||||
state: WalletState,
|
||||
binding: FragmentWalletBinding,
|
||||
|
|
@ -148,6 +165,8 @@ class MultiWalletView : WalletView {
|
|||
fragment.getString(R.string.wallet_error_unsupported_blockchain_subtitle)
|
||||
)
|
||||
}
|
||||
else -> { /* no-op */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue