Updated on 2026-08-14
This commit is contained in:
parent
2b5fcdf0f9
commit
db93629493
9 changed files with 79 additions and 54 deletions
|
|
@ -6,16 +6,18 @@ import java.math.BigDecimal
|
|||
* Represents fiat balance of [WalletStoreModel] list
|
||||
* @property amount Amount of the total balance
|
||||
* */
|
||||
sealed class TotalFiatBalance {
|
||||
open val amount: BigDecimal = BigDecimal.ZERO
|
||||
sealed interface TotalFiatBalance {
|
||||
val amount: BigDecimal?
|
||||
|
||||
object Loading : TotalFiatBalance()
|
||||
object Loading : TotalFiatBalance {
|
||||
override val amount: BigDecimal? = null
|
||||
}
|
||||
|
||||
data class Error(
|
||||
override val amount: BigDecimal,
|
||||
) : TotalFiatBalance()
|
||||
override val amount: BigDecimal?,
|
||||
) : TotalFiatBalance
|
||||
|
||||
data class Loaded(
|
||||
override val amount: BigDecimal,
|
||||
) : TotalFiatBalance()
|
||||
) : TotalFiatBalance
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ import java.math.BigDecimal
|
|||
* founds will be destroyed. Null if currency don't have existential deposit
|
||||
* @param fiatRate Wallet's fiat rate, used to calculate fiat balance. Null if not provided
|
||||
* @param isCardSingleToken shows that [Currency] is a card token
|
||||
* @param isCustom shows that currency is a custom
|
||||
* */
|
||||
data class WalletDataModel(
|
||||
val currency: Currency,
|
||||
|
|
@ -24,6 +25,7 @@ data class WalletDataModel(
|
|||
val existentialDeposit: BigDecimal?,
|
||||
val fiatRate: BigDecimal?,
|
||||
val isCardSingleToken: Boolean,
|
||||
val isCustom: Boolean,
|
||||
val historyTransactions: List<TransactionData>?,
|
||||
) {
|
||||
|
||||
|
|
@ -59,9 +61,7 @@ data class WalletDataModel(
|
|||
|
||||
data class NoAccount(
|
||||
val amountToCreateAccount: BigDecimal?,
|
||||
) : Status() {
|
||||
override val isErrorStatus: Boolean = true
|
||||
}
|
||||
) : Status()
|
||||
|
||||
data class Unreachable(
|
||||
override val errorMessage: String?,
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@ package com.tangem.tap.domain.model.builders
|
|||
|
||||
import com.tangem.blockchain.blockchains.polkadot.ExistentialDepositProvider
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.DerivationStyle
|
||||
import com.tangem.blockchain.common.Token
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.common.hdWallet.DerivationPath
|
||||
import com.tangem.domain.common.util.UserWalletId
|
||||
import com.tangem.domain.common.TapWorkarounds.derivationStyle
|
||||
import com.tangem.tap.common.extensions.getBlockchainTxHistory
|
||||
import com.tangem.tap.common.extensions.getTokenTxHistory
|
||||
import com.tangem.tap.domain.model.UserWallet
|
||||
import com.tangem.tap.domain.model.WalletDataModel
|
||||
import com.tangem.tap.domain.model.WalletStoreModel
|
||||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||
|
|
@ -26,23 +28,23 @@ interface WalletStoreBuilder {
|
|||
|
||||
companion object {
|
||||
operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
userWallet: UserWallet,
|
||||
blockchainNetwork: BlockchainNetwork,
|
||||
): BlockchainNetworkWalletStoreBuilder {
|
||||
return BlockchainNetworkWalletStoreBuilderImpl(userWalletId, blockchainNetwork)
|
||||
return BlockchainNetworkWalletStoreBuilderImpl(userWallet, blockchainNetwork)
|
||||
}
|
||||
|
||||
operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
userWallet: UserWallet,
|
||||
walletManager: WalletManager,
|
||||
): WalletMangerWalletStoreBuilder {
|
||||
return WalletMangerWalletStoreBuilderImpl(userWalletId, walletManager)
|
||||
return WalletMangerWalletStoreBuilderImpl(userWallet, walletManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class BlockchainNetworkWalletStoreBuilderImpl(
|
||||
private val userWalletId: UserWalletId,
|
||||
private val userWallet: UserWallet,
|
||||
private val blockchainNetwork: BlockchainNetwork,
|
||||
) : WalletStoreBuilder.BlockchainNetworkWalletStoreBuilder {
|
||||
private var walletManager: WalletManager? = null
|
||||
|
|
@ -52,11 +54,12 @@ private class BlockchainNetworkWalletStoreBuilderImpl(
|
|||
}
|
||||
|
||||
override fun build(): WalletStoreModel {
|
||||
val blockchainWalletData = blockchainNetwork.getBlockchainWalletData(walletManager)
|
||||
val tokensWalletsData = blockchainNetwork.getTokensWalletsData(walletManager)
|
||||
val cardDerivationStyle = userWallet.scanResponse.card.derivationStyle
|
||||
val blockchainWalletData = blockchainNetwork.getBlockchainWalletData(walletManager, cardDerivationStyle)
|
||||
val tokensWalletsData = blockchainNetwork.getTokensWalletsData(walletManager, cardDerivationStyle)
|
||||
|
||||
return WalletStoreModel(
|
||||
userWalletId = userWalletId,
|
||||
userWalletId = userWallet.walletId,
|
||||
blockchain = blockchainNetwork.blockchain,
|
||||
derivationPath = blockchainNetwork.derivationPath?.let { DerivationPath(it) },
|
||||
walletsData = listOf(blockchainWalletData) + tokensWalletsData,
|
||||
|
|
@ -68,7 +71,7 @@ private class BlockchainNetworkWalletStoreBuilderImpl(
|
|||
}
|
||||
|
||||
private class WalletMangerWalletStoreBuilderImpl(
|
||||
private val userWalletId: UserWalletId,
|
||||
private val userWallet: UserWallet,
|
||||
private val walletManager: WalletManager,
|
||||
) : WalletStoreBuilder.WalletMangerWalletStoreBuilder {
|
||||
|
||||
|
|
@ -78,7 +81,7 @@ private class WalletMangerWalletStoreBuilderImpl(
|
|||
val tokenWalletsData = wallet.getTokens().firstOrNull()?.toTokenWalletData(walletManager)
|
||||
|
||||
return WalletStoreModel(
|
||||
userWalletId = userWalletId,
|
||||
userWalletId = userWallet.walletId,
|
||||
blockchain = wallet.blockchain,
|
||||
derivationPath = wallet.publicKey.derivationPath,
|
||||
walletsData = listOf(blockchainWalletData) + listOfNotNull(tokenWalletsData),
|
||||
|
|
@ -89,35 +92,45 @@ private class WalletMangerWalletStoreBuilderImpl(
|
|||
}
|
||||
}
|
||||
|
||||
private fun BlockchainNetwork.getBlockchainWalletData(walletManager: WalletManager?): WalletDataModel {
|
||||
private fun BlockchainNetwork.getBlockchainWalletData(
|
||||
walletManager: WalletManager?,
|
||||
cardDerivationStyle: DerivationStyle?,
|
||||
): WalletDataModel {
|
||||
val currency = Currency.Blockchain(
|
||||
blockchain = blockchain,
|
||||
derivationPath = derivationPath,
|
||||
)
|
||||
return WalletDataModel(
|
||||
currency = Currency.Blockchain(
|
||||
blockchain = blockchain,
|
||||
derivationPath = derivationPath,
|
||||
),
|
||||
currency = currency,
|
||||
status = WalletDataModel.Loading,
|
||||
walletAddresses = walletManager?.wallet?.createAddressesData().orEmpty(),
|
||||
existentialDeposit = getExistentialDeposit(walletManager),
|
||||
fiatRate = null,
|
||||
isCardSingleToken = false,
|
||||
isCustom = currency.isCustomCurrency(cardDerivationStyle),
|
||||
historyTransactions = walletManager?.getBlockchainTxHistory(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun BlockchainNetwork.getTokensWalletsData(walletManager: WalletManager?): List<WalletDataModel> {
|
||||
private fun BlockchainNetwork.getTokensWalletsData(
|
||||
walletManager: WalletManager?,
|
||||
cardDerivationStyle: DerivationStyle?,
|
||||
): List<WalletDataModel> {
|
||||
return this.tokens
|
||||
.map { token ->
|
||||
val currency = Currency.Token(
|
||||
token = token,
|
||||
blockchain = blockchain,
|
||||
derivationPath = derivationPath,
|
||||
)
|
||||
WalletDataModel(
|
||||
currency = Currency.Token(
|
||||
token = token,
|
||||
blockchain = blockchain,
|
||||
derivationPath = derivationPath,
|
||||
),
|
||||
currency = currency,
|
||||
status = WalletDataModel.Loading,
|
||||
walletAddresses = walletManager?.wallet?.createAddressesData().orEmpty(),
|
||||
existentialDeposit = getExistentialDeposit(walletManager),
|
||||
fiatRate = null,
|
||||
isCardSingleToken = walletManager?.cardTokens?.contains(token) ?: false,
|
||||
isCustom = currency.isCustomCurrency(cardDerivationStyle),
|
||||
historyTransactions = walletManager?.getTokenTxHistory(token),
|
||||
)
|
||||
}
|
||||
|
|
@ -135,6 +148,7 @@ private fun Blockchain.toBlockchainWalletData(walletManager: WalletManager): Wal
|
|||
existentialDeposit = getExistentialDeposit(walletManager),
|
||||
fiatRate = null,
|
||||
isCardSingleToken = false,
|
||||
isCustom = false,
|
||||
historyTransactions = walletManager.getBlockchainTxHistory(),
|
||||
)
|
||||
}
|
||||
|
|
@ -152,6 +166,7 @@ private fun Token.toTokenWalletData(walletManager: WalletManager): WalletDataMod
|
|||
existentialDeposit = getExistentialDeposit(walletManager),
|
||||
fiatRate = null,
|
||||
isCardSingleToken = walletManager.cardTokens.contains(this),
|
||||
isCustom = false,
|
||||
historyTransactions = walletManager.getTokenTxHistory(this),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ internal class DefaultTotalFiatBalanceCalculator : TotalFiatBalanceCalculator {
|
|||
when (walletsData.findStatus()) {
|
||||
TotalFiatBalanceStatus.Loading -> TotalFiatBalance.Loading
|
||||
TotalFiatBalanceStatus.Error -> TotalFiatBalance.Error(calculateAmount())
|
||||
TotalFiatBalanceStatus.Loaded -> TotalFiatBalance.Loaded(calculateAmount())
|
||||
TotalFiatBalanceStatus.Loaded -> TotalFiatBalance.Loaded(
|
||||
amount = calculateAmount() ?: BigDecimal.ZERO,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +49,8 @@ internal class DefaultTotalFiatBalanceCalculator : TotalFiatBalanceCalculator {
|
|||
is WalletDataModel.VerifiedOnline,
|
||||
is WalletDataModel.SameCurrencyTransactionInProgress,
|
||||
is WalletDataModel.TransactionInProgress,
|
||||
is WalletDataModel.NoAccount -> if (walletData.fiatRate == null) {
|
||||
is WalletDataModel.NoAccount,
|
||||
-> if (walletData.isCustom || walletData.fiatRate == null) {
|
||||
TotalFiatBalanceStatus.Error
|
||||
} else {
|
||||
TotalFiatBalanceStatus.Loaded
|
||||
|
|
@ -60,14 +63,17 @@ internal class DefaultTotalFiatBalanceCalculator : TotalFiatBalanceCalculator {
|
|||
}
|
||||
}
|
||||
|
||||
private fun Sequence<WalletDataModel>.calculateTotalFiatAmount(): BigDecimal {
|
||||
private fun Sequence<WalletDataModel>.calculateTotalFiatAmount(): BigDecimal? {
|
||||
return this
|
||||
.filterNot { it.isCustom }
|
||||
.map { walletData ->
|
||||
walletData.fiatRate
|
||||
?.takeUnless { walletData.status.isErrorStatus }
|
||||
?.let { walletData.status.amount.toFiatValue(it) }
|
||||
?: BigDecimal.ZERO
|
||||
}
|
||||
.reduce(BigDecimal::plus)
|
||||
.reduce { acc, value ->
|
||||
value?.let { acc?.plus(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCurrentStatus(
|
||||
|
|
@ -88,8 +94,6 @@ internal class DefaultTotalFiatBalanceCalculator : TotalFiatBalanceCalculator {
|
|||
}
|
||||
|
||||
private enum class TotalFiatBalanceStatus {
|
||||
Loading,
|
||||
Error,
|
||||
Loaded,
|
||||
Loading, Error, Loaded,
|
||||
}
|
||||
}
|
||||
|
|
@ -175,7 +175,7 @@ internal class DefaultWalletCurrenciesManager(
|
|||
.flatMap { walletManager ->
|
||||
walletStoresRepository.storeOrUpdate(
|
||||
userWalletId = userWalletId,
|
||||
walletStore = WalletStoreBuilder(userWalletId, blockchainNetwork)
|
||||
walletStore = WalletStoreBuilder(userWallet, blockchainNetwork)
|
||||
.walletManager(walletManager)
|
||||
.build(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ internal class DefaultWalletStoresManager(
|
|||
{ walletManager ->
|
||||
walletStoresRepository.storeOrUpdate(
|
||||
userWalletId = userWalletId,
|
||||
walletStore = WalletStoreBuilder(userWalletId, blockchainNetwork)
|
||||
walletStore = WalletStoreBuilder(userWallet, blockchainNetwork)
|
||||
.walletManager(walletManager)
|
||||
.build(),
|
||||
)
|
||||
|
|
@ -171,7 +171,7 @@ internal class DefaultWalletStoresManager(
|
|||
val userWalletId = userWallet.walletId
|
||||
walletStoresRepository.storeOrUpdate(
|
||||
userWalletId = userWalletId,
|
||||
walletStore = WalletStoreBuilder(userWalletId, walletManager)
|
||||
walletStore = WalletStoreBuilder(userWallet, walletManager)
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ import java.math.BigDecimal
|
|||
|
||||
data class TotalBalance(
|
||||
val state: ProgressState,
|
||||
val fiatAmount: BigDecimal,
|
||||
val fiatAmount: BigDecimal?,
|
||||
val fiatCurrency: FiatCurrency,
|
||||
)
|
||||
|
|
@ -37,6 +37,7 @@ import com.tangem.tap.common.entities.FiatCurrency
|
|||
import com.tangem.tap.common.extensions.formatWithSpaces
|
||||
import com.tangem.tap.features.wallet.models.TotalBalance
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.wallet.R
|
||||
import com.valentinilk.shimmer.shimmer
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -91,7 +92,7 @@ internal class TotalBalanceCard @JvmOverloads constructor(
|
|||
ProgressState.Refreshing,
|
||||
ProgressState.Done,
|
||||
-> TotalBalanceCardState.Success(
|
||||
amount = status.fiatAmount,
|
||||
amount = status.fiatAmount ?: BigDecimal.ZERO,
|
||||
fiatCurrency = status.fiatCurrency,
|
||||
onChangeFiatCurrencyClick = onChangeCurrencyClick,
|
||||
)
|
||||
|
|
@ -232,9 +233,11 @@ private fun LoadedAmount(
|
|||
|
||||
@Composable
|
||||
private fun buildAmountString(
|
||||
amount: BigDecimal,
|
||||
amount: BigDecimal?,
|
||||
fiatCurrencySymbol: String,
|
||||
): AnnotatedString {
|
||||
if (amount == null) return AnnotatedString(text = UNKNOWN_AMOUNT_SIGN)
|
||||
|
||||
val format = DecimalFormat.getInstance(Locale.getDefault()) as DecimalFormat
|
||||
val scaledAmount = amount
|
||||
.setScale(2, RoundingMode.HALF_UP)
|
||||
|
|
@ -255,12 +258,12 @@ private fun buildAmountString(
|
|||
}
|
||||
|
||||
private sealed interface TotalBalanceCardState {
|
||||
val amount: BigDecimal
|
||||
val amount: BigDecimal?
|
||||
val onChangeFiatCurrencyClick: () -> Unit
|
||||
val fiatCurrency: FiatCurrency
|
||||
|
||||
object Empty : TotalBalanceCardState {
|
||||
override val amount: BigDecimal = BigDecimal.ZERO
|
||||
override val amount: BigDecimal? = null
|
||||
override val fiatCurrency: FiatCurrency = FiatCurrency.Default
|
||||
override val onChangeFiatCurrencyClick: () -> Unit = { /* no-op */ }
|
||||
}
|
||||
|
|
@ -273,7 +276,7 @@ private sealed interface TotalBalanceCardState {
|
|||
}
|
||||
|
||||
data class Failure(
|
||||
override val amount: BigDecimal,
|
||||
override val amount: BigDecimal?,
|
||||
override val fiatCurrency: FiatCurrency,
|
||||
override val onChangeFiatCurrencyClick: () -> Unit,
|
||||
) : TotalBalanceCardState
|
||||
|
|
|
|||
|
|
@ -3,23 +3,24 @@ package com.tangem.tap.features.walletSelector.ui
|
|||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.common.extensions.toFormattedFiatValue
|
||||
import com.tangem.tap.domain.model.TotalFiatBalance
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.features.walletSelector.redux.UserWalletModel
|
||||
import com.tangem.tap.features.walletSelector.ui.model.MultiCurrencyUserWalletItem
|
||||
import com.tangem.tap.features.walletSelector.ui.model.SingleCurrencyUserWalletItem
|
||||
import com.tangem.tap.features.walletSelector.ui.model.UserWalletItem
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal fun List<UserWalletModel>.toUiModels(
|
||||
appCurrency: FiatCurrency,
|
||||
): Sequence<UserWalletItem> {
|
||||
return this.asSequence().map { userWalletModel ->
|
||||
with(userWalletModel) {
|
||||
val formatAmount = { amount: BigDecimal ->
|
||||
amount.toFormattedFiatValue(appCurrency.symbol)
|
||||
}
|
||||
val balance = when (fiatBalance) {
|
||||
is TotalFiatBalance.Error -> UserWalletItem.Balance.Error(formatAmount(fiatBalance.amount))
|
||||
is TotalFiatBalance.Loaded -> UserWalletItem.Balance.Loaded(formatAmount(fiatBalance.amount))
|
||||
is TotalFiatBalance.Error -> UserWalletItem.Balance.Error(
|
||||
amount = fiatBalance.amount?.toFormattedFiatValue(appCurrency.symbol) ?: UNKNOWN_AMOUNT_SIGN,
|
||||
)
|
||||
is TotalFiatBalance.Loaded -> UserWalletItem.Balance.Loaded(
|
||||
amount = fiatBalance.amount.toFormattedFiatValue(appCurrency.symbol),
|
||||
)
|
||||
is TotalFiatBalance.Loading -> UserWalletItem.Balance.Loading
|
||||
}
|
||||
when (type) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue