Updated on 2026-08-14

This commit is contained in:
Tangem 2023-07-13 09:50:38 +03:00
parent bde99e272b
commit d8348e54df
14 changed files with 448 additions and 27 deletions

View file

@ -0,0 +1,71 @@
package com.tangem.core.ui.utils
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.NumberFormat
import java.util.Currency
import java.util.Locale
object BigDecimalFormatter {
private const val TEMP_CURRENCY_CODE = "USD"
fun formatCryptoAmount(
cryptoAmount: BigDecimal,
cryptoCurrency: String,
decimals: Int,
locale: Locale = Locale.getDefault(),
): String {
val formatterCurrency = getCurrency(cryptoCurrency)
val formatter = NumberFormat.getCurrencyInstance(locale).apply {
currency = formatterCurrency
maximumFractionDigits = decimals.coerceAtMost(maximumValue = 8)
minimumFractionDigits = 2
roundingMode = RoundingMode.DOWN
}
return formatter.format(cryptoAmount)
.replace(formatterCurrency.getSymbol(locale), cryptoCurrency)
}
fun formatFiatAmount(
fiatAmount: BigDecimal,
fiatCurrencyCode: String,
fiatCurrencySymbol: String,
locale: Locale = Locale.getDefault(),
): String {
val formatterCurrency = getCurrency(fiatCurrencyCode)
val formatter = NumberFormat.getCurrencyInstance(locale).apply {
currency = formatterCurrency
maximumFractionDigits = 2
minimumFractionDigits = 2
roundingMode = RoundingMode.HALF_UP
}
return formatter.format(fiatAmount)
.replace(formatterCurrency.getSymbol(locale), fiatCurrencySymbol)
}
fun formatPercent(percent: BigDecimal, useAbsoluteValue: Boolean, locale: Locale = Locale.getDefault()): String {
val formatter = NumberFormat.getPercentInstance(locale).apply {
maximumFractionDigits = 2
minimumFractionDigits = 2
roundingMode = RoundingMode.HALF_UP
}
val value = if (useAbsoluteValue) percent.abs() else percent
return formatter.format(value)
}
private fun getCurrency(code: String): Currency {
return runCatching { Currency.getInstance(code) }
.getOrElse { e ->
// Currency code is not valid ISO 4217 code
if (e is IllegalArgumentException) {
Currency.getInstance(TEMP_CURRENCY_CODE)
} else {
throw e
}
}
}
}

View file

@ -1,9 +1,7 @@
package com.tangem.domain.tokens.model package com.tangem.domain.tokens.model
import arrow.core.NonEmptySet
data class NetworkGroup( data class NetworkGroup(
val networkId: Network.ID, val networkId: Network.ID,
val name: String, val name: String,
val tokens: NonEmptySet<TokenStatus>, val tokens: Set<TokenStatus>,
) )

View file

@ -1,6 +1,5 @@
package com.tangem.domain.tokens.model package com.tangem.domain.tokens.model
import arrow.core.NonEmptySet
import java.math.BigDecimal import java.math.BigDecimal
sealed class TokenList { sealed class TokenList {
@ -8,13 +7,13 @@ sealed class TokenList {
open val sortedBy: SortType = SortType.NONE open val sortedBy: SortType = SortType.NONE
data class GroupedByNetwork( data class GroupedByNetwork(
val groups: NonEmptySet<NetworkGroup>, val groups: Set<NetworkGroup>,
override val totalFiatBalance: FiatBalance, override val totalFiatBalance: FiatBalance,
override val sortedBy: SortType, override val sortedBy: SortType,
) : TokenList() ) : TokenList()
data class Ungrouped( data class Ungrouped(
val tokens: NonEmptySet<TokenStatus>, val tokens: Set<TokenStatus>,
override val totalFiatBalance: FiatBalance, override val totalFiatBalance: FiatBalance,
override val sortedBy: SortType, override val sortedBy: SortType,
) : TokenList() ) : TokenList()

View file

@ -84,7 +84,7 @@ internal class TokenListOperations(
): NonEmptySet<NetworkGroup> { ): NonEmptySet<NetworkGroup> {
val groupsWithSortedTokens = groupTokens(tokens, networks) val groupsWithSortedTokens = groupTokens(tokens, networks)
.map { group -> .map { group ->
group.copy(tokens = sortTokensByBalance(group.tokens)) group.copy(tokens = sortTokensByBalance(group.tokens as NonEmptySet<TokenStatus>))
} }
.toNonEmptySet() .toNonEmptySet()
val sortedGroups = if (isAnyTokenLoading) { val sortedGroups = if (isAnyTokenLoading) {

View file

@ -68,7 +68,7 @@ internal object MockTokenLists {
val loadingUngroupedTokenList = with(ungroupedTokenList) { val loadingUngroupedTokenList = with(ungroupedTokenList) {
copy( copy(
tokens = tokens.map { it.copy(value = TokenStatus.Loading) }.toNonEmptySet(), tokens = tokens.map { it.copy(value = TokenStatus.Loading) }.toSet(),
totalFiatBalance = TokenList.FiatBalance.Loading, totalFiatBalance = TokenList.FiatBalance.Loading,
) )
} }
@ -91,7 +91,7 @@ internal object MockTokenLists {
val sortedGroupedTokenList: TokenList.GroupedByNetwork val sortedGroupedTokenList: TokenList.GroupedByNetwork
get() { get() {
val groups = sortedNetworksGroups val groups = sortedNetworksGroups.toSet()
return groupedTokenList.copy( return groupedTokenList.copy(
groups = groups, groups = groups,

View file

@ -29,6 +29,7 @@ dependencies {
implementation(deps.kotlin.immutable.collections) implementation(deps.kotlin.immutable.collections)
implementation(deps.tangem.card.core) implementation(deps.tangem.card.core)
implementation(deps.tangem.blockchain) implementation(deps.tangem.blockchain)
implementation(deps.arrow.core)
/** DI */ /** DI */
implementation(deps.hilt.android) implementation(deps.hilt.android)

View file

@ -4,6 +4,7 @@ import com.tangem.core.ui.R
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
import com.tangem.core.ui.components.marketprice.PriceChangeConfig import com.tangem.core.ui.components.marketprice.PriceChangeConfig
import com.tangem.core.ui.components.transactions.TransactionState import com.tangem.core.ui.components.transactions.TransactionState
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.feature.wallet.presentation.common.state.TokenItemState import com.tangem.feature.wallet.presentation.common.state.TokenItemState
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.TokenOptionsState import com.tangem.feature.wallet.presentation.common.state.TokenItemState.TokenOptionsState
import com.tangem.feature.wallet.presentation.organizetokens.DraggableItem import com.tangem.feature.wallet.presentation.organizetokens.DraggableItem
@ -51,14 +52,16 @@ internal object WalletPreviewData {
onClick = null, onClick = null,
) )
val wallets = mapOf(
UserWalletId(stringValue = "123") to walletCardContentState,
UserWalletId(stringValue = "321") to walletCardLoadingState,
UserWalletId(stringValue = "42") to walletCardHiddenContentState,
UserWalletId(stringValue = "24") to walletCardErrorState,
)
val walletListConfig = WalletsListConfig( val walletListConfig = WalletsListConfig(
selectedWalletIndex = 0, selectedWalletIndex = 0,
wallets = persistentListOf( wallets = wallets.values.toPersistentList(),
walletCardContentState,
walletCardLoadingState,
walletCardHiddenContentState,
walletCardErrorState,
),
onWalletChange = {}, onWalletChange = {},
) )

View file

@ -0,0 +1,40 @@
package com.tangem.feature.wallet.presentation.wallet.utils
import com.tangem.core.ui.utils.BigDecimalFormatter.formatFiatAmount
import com.tangem.domain.tokens.model.TokenList
import com.tangem.feature.wallet.presentation.wallet.state.WalletCardState
import com.tangem.utils.converter.Converter
internal class FiatBalanceToWalletCardConverter(
private val currentState: WalletCardState,
private val isWalletContentHidden: Boolean,
private val fiatCurrencyCode: String,
private val fiatCurrencySymbol: String,
) : Converter<TokenList.FiatBalance, WalletCardState> {
override fun convert(value: TokenList.FiatBalance): WalletCardState {
// TODO: [REDACTED_JIRA]
return when (value) {
is TokenList.FiatBalance.Loading -> with(currentState) {
WalletCardState.Loading(id, title, additionalInfo, imageResId, onClick)
}
is TokenList.FiatBalance.Failed -> with(currentState) {
WalletCardState.Error(id, title, additionalInfo, imageResId, onClick)
}
is TokenList.FiatBalance.Loaded -> with(currentState) {
if (isWalletContentHidden) {
WalletCardState.HiddenContent(id, title, additionalInfo, imageResId, onClick)
} else {
WalletCardState.Content(
id = id,
title = title,
additionalInfo = additionalInfo,
imageResId = imageResId,
onClick = onClick,
balance = formatFiatAmount(value.amount, fiatCurrencyCode, fiatCurrencySymbol),
)
}
}
}
}
}

View file

@ -0,0 +1,15 @@
package com.tangem.feature.wallet.presentation.wallet.utils
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemState.MultiCurrencyItem
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.toPersistentList
internal object LoadingItemsProvider {
fun getLoadingMultiCurrencyTokens(): PersistentList<MultiCurrencyItem> {
return List(size = 5) { TokenItemState.Loading }
.map { MultiCurrencyItem.Token(it) }
.toPersistentList()
}
}

View file

@ -0,0 +1,15 @@
package com.tangem.feature.wallet.presentation.wallet.utils
import com.tangem.domain.tokens.error.TokensError
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
import com.tangem.utils.converter.Converter
internal class TokenErrorToWalletStateConverter(
private val currentState: WalletStateHolder,
) : Converter<TokensError, WalletStateHolder> {
// TODO: [REDACTED_JIRA]
override fun convert(value: TokensError): WalletStateHolder {
return currentState
}
}

View file

@ -0,0 +1,63 @@
package com.tangem.feature.wallet.presentation.wallet.utils
import com.tangem.domain.tokens.model.NetworkGroup
import com.tangem.domain.tokens.model.TokenList
import com.tangem.domain.tokens.model.TokenStatus
import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemState.MultiCurrencyItem
import com.tangem.feature.wallet.presentation.wallet.utils.LoadingItemsProvider.getLoadingMultiCurrencyTokens
import com.tangem.utils.converter.Converter
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.mutate
import kotlinx.collections.immutable.persistentListOf
internal class TokenListToContentItemsConverter(
isWalletContentHidden: Boolean,
fiatCurrencyCode: String,
fiatCurrencySymbol: String,
) : Converter<TokenList, ImmutableList<MultiCurrencyItem>> {
private val tokenStatusConverter = TokenStatusToTokenItemConverter(
isWalletContentHidden,
fiatCurrencyCode,
fiatCurrencySymbol,
)
override fun convert(value: TokenList): ImmutableList<MultiCurrencyItem> {
return when (value) {
is TokenList.GroupedByNetwork -> value.mapToMultiCurrencyItems()
is TokenList.Ungrouped -> value.mapToMultiCurrencyItems()
is TokenList.NotInitialized -> getLoadingMultiCurrencyTokens()
}
}
private fun TokenList.GroupedByNetwork.mapToMultiCurrencyItems(): PersistentList<MultiCurrencyItem> {
return groups.fold(initial = persistentListOf()) { acc, group ->
acc.mutate { it.addGroup(group) }
}
}
private fun TokenList.Ungrouped.mapToMultiCurrencyItems(): PersistentList<MultiCurrencyItem> {
return tokens.fold(initial = persistentListOf()) { acc, token ->
acc.mutate { it.addToken(token) }
}
}
private fun MutableList<MultiCurrencyItem>.addGroup(group: NetworkGroup): List<MultiCurrencyItem> {
this.add(MultiCurrencyItem.NetworkGroupTitle(group.name))
group.tokens.forEach { token ->
this.addToken(token)
}
return this
}
private fun MutableList<MultiCurrencyItem>.addToken(token: TokenStatus): List<MultiCurrencyItem> {
val tokenItemState = tokenStatusConverter.convert(token)
this.add(MultiCurrencyItem.Token(tokenItemState))
return this
}
}

View file

@ -0,0 +1,56 @@
package com.tangem.feature.wallet.presentation.wallet.utils
import com.tangem.domain.tokens.model.TokenList
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder.MultiCurrencyContent
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder.SingleCurrencyContent
import com.tangem.feature.wallet.presentation.wallet.state.WalletsListConfig
import com.tangem.utils.converter.Converter
import kotlinx.collections.immutable.toPersistentList
internal class TokenListToWalletStateConverter(
private val currentState: WalletStateHolder,
private val isWalletContentHidden: Boolean,
private val fiatCurrencyCode: String,
private val fiatCurrencySymbol: String,
) : Converter<TokenList, WalletStateHolder> {
override fun convert(value: TokenList): WalletStateHolder {
return when (currentState) {
is MultiCurrencyContent -> currentState.updateWithTokenList(value)
is SingleCurrencyContent -> currentState.updateWithTokenList(value)
}
}
private fun MultiCurrencyContent.updateWithTokenList(tokenList: TokenList): MultiCurrencyContent {
val converter = TokenListToContentItemsConverter(isWalletContentHidden, fiatCurrencyCode, fiatCurrencySymbol)
return this.copy(
walletsListConfig = updateSelectedWallet(tokenList.totalFiatBalance),
contentItems = converter.convert(tokenList),
)
}
private fun SingleCurrencyContent.updateWithTokenList(tokenList: TokenList): SingleCurrencyContent {
return this.copy(
walletsListConfig = updateSelectedWallet(tokenList.totalFiatBalance),
)
}
private fun WalletStateHolder.updateSelectedWallet(fiatBalance: TokenList.FiatBalance): WalletsListConfig {
val selectedWalletIndex = walletsListConfig.selectedWalletIndex
val selectedWalletCard = walletsListConfig.wallets[selectedWalletIndex]
val converter = FiatBalanceToWalletCardConverter(
selectedWalletCard,
isWalletContentHidden,
fiatCurrencyCode,
fiatCurrencySymbol,
)
return walletsListConfig.copy(
wallets = walletsListConfig.wallets
.toPersistentList()
.set(selectedWalletIndex, converter.convert(fiatBalance)),
)
}
}

View file

@ -0,0 +1,105 @@
package com.tangem.feature.wallet.presentation.wallet.utils
import androidx.annotation.DrawableRes
import com.tangem.core.ui.components.marketprice.PriceChangeConfig
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.domain.tokens.model.TokenStatus
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
import com.tangem.utils.converter.Converter
import java.math.BigDecimal
internal class TokenStatusToTokenItemConverter(
private val isWalletContentHidden: Boolean,
private val fiatCurrencyCode: String,
private val fiatCurrencySymbol: String,
) : Converter<TokenStatus, TokenItemState> {
private val TokenStatus.networkIconResId: Int?
@DrawableRes get() {
// TODO: [REDACTED_JIRA]
return if (isCoin) null else R.drawable.img_eth_22
}
private val TokenStatus.tokenIconResId: Int
@DrawableRes get() {
// TODO: [REDACTED_JIRA]
return R.drawable.img_eth_22
}
override fun convert(value: TokenStatus): TokenItemState {
return when (value.value) {
is TokenStatus.Loading -> TokenItemState.Loading
is TokenStatus.Loaded,
is TokenStatus.Custom,
-> value.mapToTokenItemState()
// TODO: Add other token item states, currently not designed
is TokenStatus.MissedDerivation,
is TokenStatus.NoAccount,
is TokenStatus.Unreachable,
-> value.mapToUnreachableTokenItemState()
}
}
private fun TokenStatus.mapToTokenItemState(): TokenItemState.Content {
return TokenItemState.Content(
id = this.id.value,
name = this.name,
tokenIconUrl = this.iconUrl,
tokenIconResId = this.tokenIconResId,
networkIconResId = this.networkIconResId,
amount = getFormattedAmount(),
hasPending = value.hasTransactionsInProgress,
tokenOptions = if (isWalletContentHidden) {
TokenItemState.TokenOptionsState.Hidden(getPriceChangeConfig())
} else {
TokenItemState.TokenOptionsState.Visible(
fiatAmount = getFormattedFiatAmount(),
priceChange = getPriceChangeConfig(),
)
},
)
}
private fun TokenStatus.getFormattedAmount(): String {
val amount = value.amount ?: return UNKNOWN_AMOUNT_SIGN
return BigDecimalFormatter.formatCryptoAmount(amount, symbol, decimals)
}
private fun TokenStatus.getFormattedFiatAmount(): String {
val fiatAmount = value.fiatAmount ?: return UNKNOWN_AMOUNT_SIGN
return BigDecimalFormatter.formatFiatAmount(fiatAmount, fiatCurrencyCode, fiatCurrencySymbol)
}
private fun TokenStatus.mapToUnreachableTokenItemState() = TokenItemState.Unreachable(
id = this.id.value,
name = this.name,
tokenIconUrl = this.iconUrl,
tokenIconResId = this.tokenIconResId,
networkIconResId = this.networkIconResId,
)
private fun TokenStatus.getPriceChangeConfig(): PriceChangeConfig {
val priceChange = value.priceChange
?: return PriceChangeConfig(UNKNOWN_AMOUNT_SIGN, PriceChangeConfig.Type.DOWN)
return PriceChangeConfig(
valueInPercent = BigDecimalFormatter.formatPercent(priceChange, useAbsoluteValue = true),
type = priceChange.getPriceChangeType(),
)
}
private fun BigDecimal?.getPriceChangeType(): PriceChangeConfig.Type {
return when {
this == null -> PriceChangeConfig.Type.DOWN
this < BigDecimal.ZERO -> PriceChangeConfig.Type.DOWN
else -> PriceChangeConfig.Type.UP
}
}
private companion object {
const val UNKNOWN_AMOUNT_SIGN = ""
}
}

View file

@ -6,16 +6,26 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import arrow.core.Either
import com.tangem.common.doOnFailure import com.tangem.common.doOnFailure
import com.tangem.common.doOnSuccess import com.tangem.common.doOnSuccess
import com.tangem.domain.card.ScanCardProcessor import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.tokens.GetTokenListUseCase import com.tangem.domain.tokens.GetTokenListUseCase
import com.tangem.domain.tokens.error.TokensError
import com.tangem.domain.tokens.model.TokenList
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.feature.wallet.presentation.common.WalletPreviewData import com.tangem.feature.wallet.presentation.common.WalletPreviewData
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
import com.tangem.feature.wallet.presentation.wallet.state.WalletTopBarConfig import com.tangem.feature.wallet.presentation.wallet.state.WalletTopBarConfig
import com.tangem.feature.wallet.presentation.wallet.utils.LoadingItemsProvider.getLoadingMultiCurrencyTokens
import com.tangem.feature.wallet.presentation.wallet.utils.TokenErrorToWalletStateConverter
import com.tangem.feature.wallet.presentation.wallet.utils.TokenListToWalletStateConverter
import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
import kotlin.properties.Delegates import kotlin.properties.Delegates
@ -27,7 +37,6 @@ import kotlin.properties.Delegates
*/ */
@HiltViewModel @HiltViewModel
internal class WalletViewModel @Inject constructor( internal class WalletViewModel @Inject constructor(
@Suppress("unused") // TODO: [REDACTED_JIRA]
private val getTokenListUseCase: GetTokenListUseCase, private val getTokenListUseCase: GetTokenListUseCase,
private val scanCardProcessor: ScanCardProcessor, private val scanCardProcessor: ScanCardProcessor,
private val dispatchers: CoroutineDispatcherProvider, private val dispatchers: CoroutineDispatcherProvider,
@ -40,14 +49,29 @@ internal class WalletViewModel @Inject constructor(
var uiState by mutableStateOf(getInitialState()) var uiState by mutableStateOf(getInitialState())
private set private set
private var getTokenListJob: Job? = null
set(value) {
field?.cancel()
field = value
}
// TODO: [REDACTED_TASK_KEY] Use production data instead of WalletPreviewData // TODO: [REDACTED_TASK_KEY] Use production data instead of WalletPreviewData
private fun getInitialState(): WalletStateHolder = WalletPreviewData.multicurrencyWalletScreenState.copy( private fun getInitialState(): WalletStateHolder {
onBackClick = ::onBackClick, val state = WalletPreviewData.multicurrencyWalletScreenState.copy(
topBarConfig = createTopBarConfig(), onBackClick = ::onBackClick,
walletsListConfig = WalletPreviewData.multicurrencyWalletScreenState.walletsListConfig.copy( topBarConfig = createTopBarConfig(),
onWalletChange = ::selectWallet, walletsListConfig = WalletPreviewData.multicurrencyWalletScreenState.walletsListConfig.copy(
), onWalletChange = ::selectWallet,
) ),
contentItems = getLoadingMultiCurrencyTokens(),
)
val selectedWalletIndex = state.walletsListConfig.selectedWalletIndex
val selectedWalletId = WalletPreviewData.wallets.keys.elementAt(selectedWalletIndex)
launchGetTokenListJob(selectedWalletId)
return state
}
private fun onBackClick() { private fun onBackClick() {
router.popBackStack() router.popBackStack()
@ -74,14 +98,45 @@ internal class WalletViewModel @Inject constructor(
Log.i("WalletViewModel", "selectWallet: $index") Log.i("WalletViewModel", "selectWallet: $index")
uiState = if (index % 2 == 0) { uiState = when (val state = uiState) {
WalletPreviewData.multicurrencyWalletScreenState.copy( is WalletStateHolder.MultiCurrencyContent -> state.copy(
walletsListConfig = uiState.walletsListConfig.copy(selectedWalletIndex = index), walletsListConfig = uiState.walletsListConfig.copy(selectedWalletIndex = index),
) )
} else { is WalletStateHolder.SingleCurrencyContent -> state.copy(
WalletPreviewData.singleWalletScreenState.copy(
walletsListConfig = uiState.walletsListConfig.copy(selectedWalletIndex = index), walletsListConfig = uiState.walletsListConfig.copy(selectedWalletIndex = index),
) )
} }
val selectedWalletId = WalletPreviewData.wallets.keys.elementAt(index)
launchGetTokenListJob(selectedWalletId)
}
private fun launchGetTokenListJob(userWalletId: UserWalletId) {
getTokenListJob = getTokenListUseCase(userWalletId)
.distinctUntilChanged()
.mapLatest(::updateStateWithTokenListOrError)
.onEach { uiState = it }
.flowOn(Dispatchers.Default)
.launchIn(viewModelScope)
}
private fun updateStateWithTokenListOrError(tokenList: Either<TokensError, TokenList>): WalletStateHolder {
val updateStateWithError = { error: TokensError ->
val converter = TokenErrorToWalletStateConverter(uiState)
converter.convert(error)
}
val updateState = { list: TokenList ->
val converter = TokenListToWalletStateConverter(
uiState,
isWalletContentHidden = false, // TODO: [REDACTED_JIRA]
fiatCurrencyCode = "USD", // TODO: [REDACTED_JIRA]
fiatCurrencySymbol = "$", // TODO: [REDACTED_JIRA]
)
converter.convert(list)
}
return tokenList.fold(ifLeft = updateStateWithError, ifRight = updateState)
} }
} }