Updated on 2026-08-14
This commit is contained in:
parent
6a5a8300cf
commit
3269095c97
15 changed files with 148 additions and 96 deletions
|
|
@ -12,6 +12,7 @@ import com.tangem.core.ui.format.bigdecimal.fiat
|
|||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.format.bigdecimal.percent
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.utils.StringsSigns.DASH_SIGN
|
||||
|
|
@ -40,7 +41,7 @@ class TokenItemStateConverter(
|
|||
createSubtitleState(it, appCurrency)
|
||||
},
|
||||
private val subtitle2StateProvider: (CryptoCurrencyStatus) -> TokenItemState.Subtitle2State? = {
|
||||
createSubtitle2State(currencyStatus = it)
|
||||
createSubtitle2State(status = it)
|
||||
},
|
||||
private val fiatAmountStateProvider: (CryptoCurrencyStatus) -> TokenItemState.FiatAmountState? = {
|
||||
createFiatAmountState(status = it, appCurrency = appCurrency)
|
||||
|
|
@ -147,7 +148,7 @@ class TokenItemStateConverter(
|
|||
return totalAmount.format { crypto(currency) }
|
||||
}
|
||||
|
||||
fun CryptoCurrencyStatus.getStakedBalance() =
|
||||
private fun CryptoCurrencyStatus.getStakedBalance() =
|
||||
(value.yieldBalance as? YieldBalance.Data)?.getTotalWithRewardsStakingBalance().orZero()
|
||||
|
||||
private fun createTitleState(currencyStatus: CryptoCurrencyStatus): TokenItemState.TitleState {
|
||||
|
|
@ -190,15 +191,16 @@ class TokenItemStateConverter(
|
|||
}
|
||||
}
|
||||
|
||||
private fun createSubtitle2State(currencyStatus: CryptoCurrencyStatus): TokenItemState.Subtitle2State? {
|
||||
return when (currencyStatus.value) {
|
||||
private fun createSubtitle2State(status: CryptoCurrencyStatus): TokenItemState.Subtitle2State? {
|
||||
return when (status.value) {
|
||||
is CryptoCurrencyStatus.Loaded,
|
||||
is CryptoCurrencyStatus.Custom,
|
||||
is CryptoCurrencyStatus.NoQuote,
|
||||
is CryptoCurrencyStatus.NoAccount,
|
||||
-> {
|
||||
TokenItemState.Subtitle2State.TextContent(
|
||||
text = currencyStatus.getFormattedCryptoAmount(includeStaking = true),
|
||||
text = status.getFormattedCryptoAmount(includeStaking = true),
|
||||
isFlickering = status.value.isFlickering(),
|
||||
)
|
||||
}
|
||||
is CryptoCurrencyStatus.Loading,
|
||||
|
|
@ -221,6 +223,7 @@ class TokenItemStateConverter(
|
|||
-> {
|
||||
TokenItemState.FiatAmountState.Content(
|
||||
text = status.getFormattedFiatAmount(appCurrency = appCurrency, includeStaking = true),
|
||||
isFlickering = status.value.isFlickering(),
|
||||
icons = buildList {
|
||||
if (!status.getStakedBalance().isZero()) {
|
||||
TokenItemState.FiatAmountState.Content.IconUM(
|
||||
|
|
@ -228,6 +231,12 @@ class TokenItemStateConverter(
|
|||
useAccentColor = true,
|
||||
).let(::add)
|
||||
}
|
||||
if (status.value.getStatusSource() == StatusSource.ONLY_CACHE) {
|
||||
TokenItemState.FiatAmountState.Content.IconUM(
|
||||
iconRes = R.drawable.ic_error_sync_24,
|
||||
useAccentColor = false,
|
||||
).let(::add)
|
||||
}
|
||||
}.toImmutableList(),
|
||||
)
|
||||
}
|
||||
|
|
@ -248,6 +257,7 @@ class TokenItemStateConverter(
|
|||
price = fiatRate.getFormattedCryptoPrice(appCurrency),
|
||||
priceChangePercent = priceChange.format { percent() },
|
||||
type = priceChange.getPriceChangeType(),
|
||||
isFlickering = value.isFlickering(),
|
||||
)
|
||||
} else {
|
||||
TokenItemState.SubtitleState.Unknown
|
||||
|
|
@ -263,5 +273,15 @@ class TokenItemStateConverter(
|
|||
private fun BigDecimal.getPriceChangeType(): PriceChangeType {
|
||||
return PriceChangeConverter.fromBigDecimal(value = this)
|
||||
}
|
||||
|
||||
private fun CryptoCurrencyStatus.Value.isFlickering(): Boolean = getStatusSource() == StatusSource.CACHE
|
||||
|
||||
private fun CryptoCurrencyStatus.Value.getStatusSource(): StatusSource? {
|
||||
return when (this) {
|
||||
is CryptoCurrencyStatus.Loaded -> source
|
||||
is CryptoCurrencyStatus.NoAccount -> source
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,10 +10,9 @@ import com.tangem.domain.tokens.model.Network
|
|||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.extensions.addOrReplace
|
||||
import com.tangem.utils.extensions.replaceBy
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
private typealias NetworkStatusesByWalletId = Map<String, Set<NetworkStatusDM>>
|
||||
|
||||
|
|
@ -22,8 +21,6 @@ internal class DefaultNetworksStatusesStore(
|
|||
private val persistenceDataStore: DataStore<NetworkStatusesByWalletId>,
|
||||
) : NetworksStatusesStore {
|
||||
|
||||
private val mutex = Mutex()
|
||||
|
||||
override fun get(key: UserWalletId): Flow<Set<NetworkStatus>> {
|
||||
return runtimeDataStore.get(provideStringKey(key))
|
||||
}
|
||||
|
|
@ -42,11 +39,20 @@ internal class DefaultNetworksStatusesStore(
|
|||
|
||||
if (cachedStatuses.isNotEmpty()) {
|
||||
send(cachedStatuses)
|
||||
|
||||
/**
|
||||
* Required for storing cache data.
|
||||
* This will help to recognize networks that are still uploaded.
|
||||
*
|
||||
* @see mergeStatuses
|
||||
*/
|
||||
storeAll(key = key, values = cachedStatuses)
|
||||
}
|
||||
|
||||
runtimeDataStore.get(provideStringKey(key))
|
||||
.onEach { runtimeStatuses ->
|
||||
val mergedStatuses = mergeStatuses(
|
||||
networks = networks,
|
||||
cachedStatuses = cachedStatuses,
|
||||
runtimeStatuses = runtimeStatuses,
|
||||
)
|
||||
|
|
@ -57,36 +63,20 @@ internal class DefaultNetworksStatusesStore(
|
|||
}
|
||||
|
||||
override suspend fun getSyncOrNull(key: UserWalletId): Set<NetworkStatus>? {
|
||||
return runtimeDataStore.getSyncOrNull(provideStringKey(key))
|
||||
return runtimeDataStore.getSyncOrNull(key = provideStringKey(key))
|
||||
}
|
||||
|
||||
override suspend fun store(key: UserWalletId, value: NetworkStatus) {
|
||||
mutex.withLock {
|
||||
val newValues = getSyncOrNull(key)
|
||||
?.addOrReplace(value) { it.network == value.network }
|
||||
?: setOf(value)
|
||||
|
||||
runtimeDataStore.store(provideStringKey(key), newValues)
|
||||
storeNetworkStatusInPersistence(key, value)
|
||||
}
|
||||
storeAll(key = key, values = setOf(value))
|
||||
}
|
||||
|
||||
override suspend fun storeAll(key: UserWalletId, values: Collection<NetworkStatus>) {
|
||||
mutex.withLock {
|
||||
val currentValues = getSyncOrNull(key) ?: emptySet()
|
||||
val updatedValues = currentValues.toMutableSet()
|
||||
override suspend fun storeAll(key: UserWalletId, values: Set<NetworkStatus>) {
|
||||
coroutineScope {
|
||||
val updatedValues = getSyncOrNull(key).orEmpty()
|
||||
.addOrReplace(items = values) { prev, new -> prev.network == new.network }
|
||||
|
||||
values.forEach { newValue ->
|
||||
val isReplaced = updatedValues.replaceBy(newValue) {
|
||||
it.network == newValue.network
|
||||
}
|
||||
|
||||
if (!isReplaced) {
|
||||
updatedValues.add(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
runtimeDataStore.store(provideStringKey(key), updatedValues)
|
||||
launch { runtimeDataStore.store(key = provideStringKey(key), value = updatedValues) }
|
||||
launch { storeNetworkStatusInPersistence(userWalletId = key, statuses = updatedValues) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,19 +86,24 @@ internal class DefaultNetworksStatusesStore(
|
|||
* If a status with the same network is in both sets, the status from [runtimeStatuses] is used.
|
||||
*/
|
||||
private fun mergeStatuses(
|
||||
networks: Set<Network>,
|
||||
cachedStatuses: Set<NetworkStatus>,
|
||||
runtimeStatuses: Set<NetworkStatus>,
|
||||
): Set<NetworkStatus> {
|
||||
return runtimeStatuses
|
||||
.map { runtime ->
|
||||
runtime.takeIf { it.value !is NetworkStatus.Unreachable }
|
||||
?: getCachedStatusIfPossible(cachedStatuses = cachedStatuses, runtime = runtime)
|
||||
return networks.mapNotNullTo(hashSetOf()) { network ->
|
||||
val runtimeStatus = runtimeStatuses.firstOrNull { it.network == network }
|
||||
|
||||
if (runtimeStatus == null || runtimeStatus.value is NetworkStatus.Unreachable) {
|
||||
getCachedStatusIfPossible(cachedStatuses = cachedStatuses, network = network)
|
||||
?: runtimeStatus
|
||||
} else {
|
||||
runtimeStatus
|
||||
}
|
||||
.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCachedStatusIfPossible(cachedStatuses: Set<NetworkStatus>, runtime: NetworkStatus): NetworkStatus {
|
||||
val cached = cachedStatuses.firstOrNull { it.network == runtime.network } ?: return runtime
|
||||
private fun getCachedStatusIfPossible(cachedStatuses: Set<NetworkStatus>, network: Network): NetworkStatus? {
|
||||
val cached = cachedStatuses.firstOrNull { it.network == network } ?: return null
|
||||
|
||||
val updatedCachedStatus = when (val status = cached.value) {
|
||||
is NetworkStatus.NoAccount -> status.copy(source = StatusSource.ONLY_CACHE)
|
||||
|
|
@ -122,22 +117,17 @@ internal class DefaultNetworksStatusesStore(
|
|||
return if (updatedCachedStatus != null) {
|
||||
cached.copy(value = updatedCachedStatus)
|
||||
} else {
|
||||
runtime
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun storeNetworkStatusInPersistence(userWalletId: UserWalletId, networkStatus: NetworkStatus) {
|
||||
val network = networkStatus.network
|
||||
|
||||
private suspend fun storeNetworkStatusInPersistence(userWalletId: UserWalletId, statuses: Set<NetworkStatus>) {
|
||||
// Converter will return null if the network status is not supported
|
||||
val newStatus = NetworkStatusDataModelConverter.convert(value = networkStatus) ?: return
|
||||
val newStatuses = NetworkStatusDataModelConverter.convertSet(input = statuses).filterNotNull().toSet()
|
||||
|
||||
persistenceDataStore.updateData { storedStatuses ->
|
||||
val userWalletStatuses = storedStatuses[userWalletId.stringValue].orEmpty()
|
||||
val updatedStatuses = userWalletStatuses.addOrReplace(item = newStatus) { it.networkId == network.id }
|
||||
|
||||
storedStatuses.toMutableMap().apply {
|
||||
this[userWalletId.stringValue] = updatedStatuses
|
||||
this[userWalletId.stringValue] = newStatuses
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,5 +15,5 @@ interface NetworksStatusesStore {
|
|||
|
||||
suspend fun store(key: UserWalletId, value: NetworkStatus)
|
||||
|
||||
suspend fun storeAll(key: UserWalletId, values: Collection<NetworkStatus>)
|
||||
suspend fun storeAll(key: UserWalletId, values: Set<NetworkStatus>)
|
||||
}
|
||||
|
|
@ -36,4 +36,16 @@ inline fun <T> Set<T>.addOrReplace(item: T, predicate: (T) -> Boolean): Set<T> {
|
|||
}
|
||||
|
||||
return mutableList
|
||||
}
|
||||
|
||||
inline fun <T> Set<T>.addOrReplace(items: Set<T>, predicate: (T, T) -> Boolean): Set<T> {
|
||||
val updatedValues = this.toMutableSet()
|
||||
|
||||
items.forEach { newValue ->
|
||||
val isReplaced = updatedValues.replaceBy(item = newValue, predicate = { predicate(it, newValue) })
|
||||
|
||||
if (!isReplaced) updatedValues.add(newValue)
|
||||
}
|
||||
|
||||
return updatedValues
|
||||
}
|
||||
|
|
@ -129,7 +129,7 @@ internal class DefaultNetworksRepository(
|
|||
}
|
||||
|
||||
if (statusesToRefresh != null) {
|
||||
networksStatusesStore.storeAll(key = userWalletId, values = statusesToRefresh)
|
||||
networksStatusesStore.storeAll(key = userWalletId, values = statusesToRefresh.toSet())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.*
|
|||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
|
||||
internal class DefaultQuotesRepository(
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
|
|
@ -115,25 +116,26 @@ internal class DefaultQuotesRepository(
|
|||
val replacementIdsResult = quotesUnsupportedCurrenciesAdapter.replaceUnsupportedCurrencies(
|
||||
rawCurrenciesIds.map { it.value }.toSet(),
|
||||
)
|
||||
val response = safeApiCallWithTimeout(
|
||||
|
||||
safeApiCallWithTimeout(
|
||||
call = {
|
||||
val coinIds = replacementIdsResult.idsForRequest.joinToString(separator = ",")
|
||||
tangemTechApi.getQuotes(appCurrencyId, coinIds).bind()
|
||||
val response = tangemTechApi.getQuotes(appCurrencyId, coinIds).bind()
|
||||
|
||||
val updatedResponse = quotesUnsupportedCurrenciesAdapter.getResponseWithUnsupportedCurrencies(
|
||||
response = response,
|
||||
filteredIds = replacementIdsResult.idsFiltered,
|
||||
)
|
||||
|
||||
quotesStore.store(updatedResponse)
|
||||
},
|
||||
onError = { error ->
|
||||
Timber.e(error)
|
||||
|
||||
cacheRegistry.invalidate(rawCurrenciesIds.map { getQuoteCacheKey(it) })
|
||||
quotesStore.storeEmptyQuotes(currenciesIds = rawCurrenciesIds)
|
||||
|
||||
throw error
|
||||
},
|
||||
)
|
||||
|
||||
val updatedResponse = quotesUnsupportedCurrenciesAdapter.getResponseWithUnsupportedCurrencies(
|
||||
response,
|
||||
replacementIdsResult.idsFiltered,
|
||||
)
|
||||
|
||||
quotesStore.store(updatedResponse)
|
||||
}
|
||||
|
||||
private suspend fun filterExpiredCurrenciesIds(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.domain.tokens.model
|
||||
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -27,5 +28,6 @@ sealed class TotalFiatBalance {
|
|||
data class Loaded(
|
||||
val amount: BigDecimal,
|
||||
val isAllAmountsSummarized: Boolean,
|
||||
val source: StatusSource,
|
||||
) : TotalFiatBalance()
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.domain.tokens.model
|
||||
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
|
|
@ -47,6 +48,7 @@ sealed class TokenList {
|
|||
override val totalFiatBalance: TotalFiatBalance = TotalFiatBalance.Loaded(
|
||||
amount = BigDecimal.ZERO,
|
||||
isAllAmountsSummarized = true,
|
||||
source = StatusSource.ACTUAL,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.domain.tokens.operations
|
||||
|
||||
import arrow.core.NonEmptyList
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.TotalFiatBalance
|
||||
|
|
@ -34,14 +35,14 @@ internal class TokenListFiatBalanceOperations(
|
|||
is CryptoCurrencyStatus.NoAmount,
|
||||
-> {
|
||||
if (BlockchainUtils.isIncludeToBalanceOnError(token.currency.network.id.value)) {
|
||||
fiatBalance = recalculateNoAccountBalance(fiatBalance)
|
||||
fiatBalance = recalculateNoAccountBalance(status, fiatBalance)
|
||||
} else {
|
||||
fiatBalance = TotalFiatBalance.Failed
|
||||
break
|
||||
}
|
||||
}
|
||||
is CryptoCurrencyStatus.NoAccount -> {
|
||||
fiatBalance = recalculateNoAccountBalance(fiatBalance)
|
||||
fiatBalance = recalculateNoAccountBalance(status, fiatBalance)
|
||||
}
|
||||
is CryptoCurrencyStatus.Loaded -> {
|
||||
fiatBalance = recalculateBalance(status, fiatBalance)
|
||||
|
|
@ -55,11 +56,15 @@ internal class TokenListFiatBalanceOperations(
|
|||
return fiatBalance
|
||||
}
|
||||
|
||||
private fun recalculateNoAccountBalance(currentBalance: TotalFiatBalance): TotalFiatBalance {
|
||||
private fun recalculateNoAccountBalance(
|
||||
status: CryptoCurrencyStatus.Value,
|
||||
currentBalance: TotalFiatBalance,
|
||||
): TotalFiatBalance {
|
||||
return (currentBalance as? TotalFiatBalance.Loaded)?.copy(isAllAmountsSummarized = false)
|
||||
?: TotalFiatBalance.Loaded(
|
||||
amount = BigDecimal.ZERO,
|
||||
isAllAmountsSummarized = false,
|
||||
source = (status as? CryptoCurrencyStatus.NoAccount)?.source ?: StatusSource.ACTUAL,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +82,7 @@ internal class TokenListFiatBalanceOperations(
|
|||
) ?: TotalFiatBalance.Loaded(
|
||||
amount = status.fiatAmount + fiatStakingBalance,
|
||||
isAllAmountsSummarized = true,
|
||||
source = status.source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -95,6 +101,7 @@ internal class TokenListFiatBalanceOperations(
|
|||
) ?: TotalFiatBalance.Loaded(
|
||||
amount = status.fiatAmount.orZero() + fiatYieldBalance,
|
||||
isAllAmountsSummarized = isTokenAmountCanBeSummarized,
|
||||
source = StatusSource.ACTUAL,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.domain.tokens.mock
|
|||
|
||||
import arrow.core.NonEmptyList
|
||||
import arrow.core.toNonEmptyListOrNull
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.tokens.mock.MockNetworksGroups.failedNetworksGroups
|
||||
import com.tangem.domain.tokens.mock.MockNetworksGroups.loadedNetworksGroups
|
||||
import com.tangem.domain.tokens.mock.MockNetworksGroups.sortedNetworksGroups
|
||||
|
|
@ -79,6 +80,7 @@ internal object MockTokenLists {
|
|||
totalFiatBalance = TotalFiatBalance.Loaded(
|
||||
amount = tokens.sumOf { it.value.fiatAmount ?: BigDecimal.ZERO },
|
||||
isAllAmountsSummarized = true,
|
||||
source = StatusSource.ACTUAL,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -95,6 +97,7 @@ internal object MockTokenLists {
|
|||
.flatMap { it.currencies as NonEmptyList<CryptoCurrencyStatus> }
|
||||
.sumOf { it.value.fiatAmount ?: BigDecimal.ZERO },
|
||||
isAllAmountsSummarized = true,
|
||||
source = StatusSource.ACTUAL,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.core.ui.extensions.stringReference
|
|||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.format.bigdecimal.*
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.staking.model.StakingAvailability
|
||||
import com.tangem.domain.staking.model.StakingEntryInfo
|
||||
import com.tangem.domain.staking.model.stakekit.RewardBlockType
|
||||
|
|
@ -121,7 +122,7 @@ internal class TokenDetailsLoadedBalanceConverter(
|
|||
onBalanceSelect = clickIntents::onBalanceSelect,
|
||||
selectedBalanceType = currentState.selectedBalanceType,
|
||||
isBalanceSelectorEnabled = isBalanceSelectorEnabled,
|
||||
isBalanceFlickering = false, // TODO: Implement in [REDACTED_JIRA]
|
||||
isBalanceFlickering = status.value.isFlickering(),
|
||||
)
|
||||
is CryptoCurrencyStatus.Loading -> TokenDetailsBalanceBlockState.Loading(
|
||||
actionButtons = currentState.actionButtons,
|
||||
|
|
@ -344,4 +345,14 @@ internal class TokenDetailsLoadedBalanceConverter(
|
|||
RewardBlockType.RewardUnavailable -> TextReference.EMPTY
|
||||
}
|
||||
}
|
||||
|
||||
private fun CryptoCurrencyStatus.Value.isFlickering(): Boolean = getStatusSource() == StatusSource.CACHE
|
||||
|
||||
private fun CryptoCurrencyStatus.Value.getStatusSource(): StatusSource? {
|
||||
return when (this) {
|
||||
is CryptoCurrencyStatus.Loaded -> source
|
||||
is CryptoCurrencyStatus.NoAccount -> source
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,8 +4,8 @@ import arrow.core.Either
|
|||
import arrow.core.getOrElse
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.domain.common.util.getCardsCount
|
||||
import com.tangem.domain.visa.model.VisaCurrency
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -78,17 +78,20 @@ internal class SetBalancesAndLimitsTransformer(
|
|||
},
|
||||
cardCount = userWallet.getCardsCount(),
|
||||
isZeroBalance = visaCurrency.balances.available.isZero(),
|
||||
isBalanceFlickering = false, // TODO: Implement in [REDACTED_JIRA]
|
||||
isBalanceFlickering = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createAdditionalInfo(visaCurrency: VisaCurrency): WalletAdditionalInfo {
|
||||
val fiatAmount = BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = visaCurrency.fiatRate?.let { visaCurrency.balances.available.multiply(it) },
|
||||
fiatCurrencyCode = visaCurrency.fiatCurrency.code,
|
||||
fiatCurrencySymbol = visaCurrency.fiatCurrency.symbol,
|
||||
)
|
||||
val fiatAmount = visaCurrency.fiatRate?.let { visaCurrency.balances.available.multiply(it) }
|
||||
.format {
|
||||
fiat(
|
||||
fiatCurrencyCode = visaCurrency.fiatCurrency.code,
|
||||
fiatCurrencySymbol = visaCurrency.fiatCurrency.symbol,
|
||||
)
|
||||
}
|
||||
|
||||
val infoContent = stringReference(
|
||||
value = buildString {
|
||||
append(fiatAmount)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
||||
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.common.util.getCardsCount
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
|
|
@ -62,14 +63,12 @@ internal class SetTokenListErrorTransformer(
|
|||
imageResId = imageResId,
|
||||
onRenameClick = onRenameClick,
|
||||
onDeleteClick = onDeleteClick,
|
||||
balance = BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = BigDecimal.ZERO,
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
),
|
||||
balance = BigDecimal.ZERO.format {
|
||||
fiat(fiatCurrencyCode = appCurrency.code, fiatCurrencySymbol = appCurrency.symbol)
|
||||
},
|
||||
cardCount = selectedWallet.getCardsCount(),
|
||||
isZeroBalance = true,
|
||||
isBalanceFlickering = false, // TODO: Implement in [REDACTED_JIRA]
|
||||
isBalanceFlickering = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers.converter
|
||||
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.common.util.getCardsCount
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.tokens.model.TotalFiatBalance
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
|
|
@ -54,14 +56,12 @@ internal class MultiWalletCardStateConverter(
|
|||
imageResId = imageResId,
|
||||
onRenameClick = onRenameClick,
|
||||
onDeleteClick = onDeleteClick,
|
||||
balance = BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = fiatBalance.amount,
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
),
|
||||
balance = fiatBalance.amount.format {
|
||||
fiat(fiatCurrencyCode = appCurrency.code, fiatCurrencySymbol = appCurrency.symbol)
|
||||
},
|
||||
isZeroBalance = fiatBalance.amount.isZero(),
|
||||
cardCount = selectedWallet.getCardsCount(),
|
||||
isBalanceFlickering = false, // TODO: Implement in [REDACTED_JIRA]
|
||||
isBalanceFlickering = fiatBalance.source == StatusSource.CACHE,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,15 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers.converter
|
||||
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.common.util.getCardsCount
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.utils.StringsSigns.DASH_SIGN
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.extensions.isZero
|
||||
|
||||
|
|
@ -65,17 +68,15 @@ internal class SingleWalletCardStateConverter(
|
|||
balance = formatFiatAmount(status = status, appCurrency = appCurrency),
|
||||
cardCount = selectedWallet.getCardsCount(),
|
||||
isZeroBalance = status.fiatAmount?.isZero(),
|
||||
isBalanceFlickering = false, // TODO: Implement in [REDACTED_JIRA]
|
||||
isBalanceFlickering = (status as? CryptoCurrencyStatus.Loaded)?.source == StatusSource.CACHE,
|
||||
)
|
||||
}
|
||||
|
||||
private fun formatFiatAmount(status: CryptoCurrencyStatus.Value, appCurrency: AppCurrency): String {
|
||||
val fiatAmount = status.fiatAmount ?: return BigDecimalFormatter.EMPTY_BALANCE_SIGN
|
||||
val fiatAmount = status.fiatAmount ?: return DASH_SIGN
|
||||
|
||||
return BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = fiatAmount,
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
)
|
||||
return fiatAmount.format {
|
||||
fiat(fiatCurrencyCode = appCurrency.code, fiatCurrencySymbol = appCurrency.symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue