Updated on 2026-08-14
This commit is contained in:
parent
a730af0f1f
commit
98915e2507
21 changed files with 448 additions and 45 deletions
|
|
@ -47,6 +47,17 @@ internal object TokensDomainModule {
|
|||
return GetTokenListUseCase(currenciesRepository, quotesRepository, networksRepository, dispatchers)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideGetCardTokensListUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): GetCardTokensListUseCase {
|
||||
return GetCardTokensListUseCase(currenciesRepository, quotesRepository, networksRepository, dispatchers)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideRemoveCurrencyUseCase(
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
|
||||
@Suppress("LargeClass")
|
||||
internal class DefaultCurrenciesRepository(
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
private val userTokensStore: UserTokensStore,
|
||||
|
|
@ -152,6 +153,29 @@ internal class DefaultCurrenciesRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getSingleCurrencyWalletWithCardCurrencies(userWalletId: UserWalletId): List<CryptoCurrency> {
|
||||
return withContext(dispatchers.io) {
|
||||
val userWallet = getUserWallet(userWalletId)
|
||||
ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = false)
|
||||
|
||||
cardCurrenciesFactory.createCurrenciesForSingleCurrencyCardWithToken(userWallet.scanResponse)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getSingleCurrencyWalletWithCardCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
id: CryptoCurrency.ID,
|
||||
): CryptoCurrency {
|
||||
return withContext(dispatchers.io) {
|
||||
val userWallet = getUserWallet(userWalletId)
|
||||
ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = false)
|
||||
|
||||
val currency = cardCurrenciesFactory.createCurrenciesForSingleCurrencyCardWithToken(userWallet.scanResponse)
|
||||
.find { it.id == id }
|
||||
requireNotNull(currency) { "Unable to find currency with provided ID: $id" }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMultiCurrencyWalletCurrenciesUpdates(userWalletId: UserWalletId): Flow<List<CryptoCurrency>> {
|
||||
return channelFlow {
|
||||
val userWallet = getUserWallet(userWalletId)
|
||||
|
|
|
|||
|
|
@ -58,4 +58,28 @@ internal class CardCryptoCurrenciesFactory(private val demoConfig: DemoConfig) {
|
|||
|
||||
return primaryToken ?: coin
|
||||
}
|
||||
|
||||
fun createCurrenciesForSingleCurrencyCardWithToken(scanResponse: ScanResponse): List<CryptoCurrency> {
|
||||
val cardDerivationStyleProvider = scanResponse.derivationStyleProvider
|
||||
val resolver = scanResponse.cardTypesResolver
|
||||
val blockchain = resolver.getBlockchain()
|
||||
|
||||
val coin = cryptoCurrencyFactory.createCoin(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
derivationStyleProvider = cardDerivationStyleProvider,
|
||||
)
|
||||
requireNotNull(coin) { "Coin for the single currency card cannot be null" }
|
||||
|
||||
val primaryToken = resolver.getPrimaryToken()?.let { token ->
|
||||
cryptoCurrencyFactory.createToken(
|
||||
sdkToken = token,
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
derivationStyleProvider = cardDerivationStyleProvider,
|
||||
)
|
||||
}
|
||||
|
||||
return listOfNotNull(coin, primaryToken)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.tokens.error.mapper.mapToTokenListError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
|
||||
import com.tangem.domain.tokens.operations.TokenListOperations
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
class GetCardTokensListUseCase(
|
||||
internal val currenciesRepository: CurrenciesRepository,
|
||||
internal val quotesRepository: QuotesRepository,
|
||||
internal val networksRepository: NetworksRepository,
|
||||
internal val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
operator fun invoke(userWalletId: UserWalletId): Flow<Either<TokenListError, TokenList>> {
|
||||
return getTokensStatuses(userWalletId).transformLatest { maybeTokens ->
|
||||
maybeTokens.fold(
|
||||
ifLeft = { error ->
|
||||
emit(error.left())
|
||||
},
|
||||
ifRight = { tokens ->
|
||||
emitAll(createTokenList(userWalletId, tokens))
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTokensStatuses(
|
||||
userWalletId: UserWalletId,
|
||||
): Flow<Either<TokenListError, List<CryptoCurrencyStatus>>> {
|
||||
val operations = CurrenciesStatusesOperations(
|
||||
userWalletId = userWalletId,
|
||||
currenciesRepository = currenciesRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
networksRepository = networksRepository,
|
||||
)
|
||||
|
||||
return operations.getCardCurrenciesStatusesFlow()
|
||||
.map { maybeCurrenciesStatuses ->
|
||||
maybeCurrenciesStatuses.mapLeft(CurrenciesStatusesOperations.Error::mapToTokenListError)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTokenList(
|
||||
userWalletId: UserWalletId,
|
||||
tokens: List<CryptoCurrencyStatus>,
|
||||
): Flow<Either<TokenListError, TokenList>> {
|
||||
val operations = TokenListOperations(
|
||||
userWalletId = userWalletId,
|
||||
tokens = tokens,
|
||||
currenciesRepository = currenciesRepository,
|
||||
)
|
||||
|
||||
return operations.getTokenListForSingleCurrencyFlow().map { maybeTokenList ->
|
||||
maybeTokenList.mapLeft(TokenListOperations.Error::mapToTokenListError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -34,15 +34,24 @@ class GetCurrencyStatusUpdatesUseCase(
|
|||
* @param userWalletId The unique identifier of the user's wallet.
|
||||
* @param currencyId The unique identifier of the cryptocurrency.
|
||||
* @param derivationPath currency derivation path.
|
||||
* @param isSingleWalletWithTokens Indicates whether the user wallet contains only one token on card (old cards)
|
||||
* @return A [Flow] emitting either a [CurrencyStatusError] or a [CryptoCurrencyStatus], indicating the result of the fetch operation.
|
||||
*/
|
||||
operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
isSingleWalletWithTokens: Boolean,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return flow {
|
||||
emitAll(getCurrency(userWalletId, currencyId, derivationPath))
|
||||
emitAll(
|
||||
getCurrency(
|
||||
userWalletId,
|
||||
currencyId,
|
||||
derivationPath,
|
||||
isSingleWalletWithTokens,
|
||||
),
|
||||
)
|
||||
}.flowOn(dispatchers.io)
|
||||
}
|
||||
|
||||
|
|
@ -50,6 +59,7 @@ class GetCurrencyStatusUpdatesUseCase(
|
|||
userWalletId: UserWalletId,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
isSingleWalletWithTokens: Boolean,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
val operations = CurrenciesStatusesOperations(
|
||||
currenciesRepository = currenciesRepository,
|
||||
|
|
@ -58,7 +68,12 @@ class GetCurrencyStatusUpdatesUseCase(
|
|||
userWalletId = userWalletId,
|
||||
)
|
||||
|
||||
return operations.getCurrencyStatusFlow(currencyId, derivationPath).map { maybeCurrency ->
|
||||
val currencyFlow = if (isSingleWalletWithTokens) {
|
||||
operations.getCurrencyStatusSingleWalletWithTokensFlow(currencyId)
|
||||
} else {
|
||||
operations.getCurrencyStatusFlow(currencyId, derivationPath)
|
||||
}
|
||||
return currencyFlow.map { maybeCurrency ->
|
||||
maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ class GetCurrencyWarningsUseCase(
|
|||
userWalletId: UserWalletId,
|
||||
currency: CryptoCurrency,
|
||||
derivationPath: Network.DerivationPath,
|
||||
isSingleWalletWithTokens: Boolean,
|
||||
): Flow<Set<CryptoCurrencyWarning>> {
|
||||
return combine(
|
||||
getFeeWarningFlow(
|
||||
|
|
@ -32,6 +33,7 @@ class GetCurrencyWarningsUseCase(
|
|||
networkId = currency.network.id,
|
||||
currencyId = currency.id,
|
||||
derivationPath = derivationPath,
|
||||
isSingleWalletWithTokens = isSingleWalletWithTokens,
|
||||
),
|
||||
flowOf(walletManagersFacade.getRentInfo(userWalletId, currency.network)),
|
||||
flowOf(walletManagersFacade.getExistentialDeposit(userWalletId, currency.network)),
|
||||
|
|
@ -54,6 +56,7 @@ class GetCurrencyWarningsUseCase(
|
|||
networkId: Network.ID,
|
||||
currencyId: CryptoCurrency.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
isSingleWalletWithTokens: Boolean,
|
||||
): Flow<CryptoCurrencyWarning?> {
|
||||
val operations = CurrenciesStatusesOperations(
|
||||
currenciesRepository = currenciesRepository,
|
||||
|
|
@ -62,9 +65,19 @@ class GetCurrencyWarningsUseCase(
|
|||
userWalletId = userWalletId,
|
||||
)
|
||||
|
||||
val currencyFlow = if (isSingleWalletWithTokens) {
|
||||
operations.getCurrencyStatusSingleWalletWithTokensFlow(currencyId)
|
||||
} else {
|
||||
operations.getCurrencyStatusFlow(currencyId, derivationPath)
|
||||
}
|
||||
val networkFlow = if (isSingleWalletWithTokens) {
|
||||
operations.getNetworkCoinForSingleWalletWithTokenFlow(networkId)
|
||||
} else {
|
||||
operations.getNetworkCoinFlow(networkId, derivationPath)
|
||||
}
|
||||
return combine(
|
||||
operations.getCurrencyStatusFlow(currencyId, derivationPath).map { it.getOrNull() },
|
||||
operations.getNetworkCoinFlow(networkId, derivationPath).map { it.getOrNull() },
|
||||
currencyFlow.map { it.getOrNull() },
|
||||
networkFlow.map { it.getOrNull() },
|
||||
) { tokenStatus, coinStatus ->
|
||||
when {
|
||||
tokenStatus != null && coinStatus != null -> {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class GetNetworkCoinStatusUseCase(
|
|||
userWalletId: UserWalletId,
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
isSingleWalletWithTokens: Boolean,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return flow {
|
||||
emitAll(
|
||||
|
|
@ -31,6 +32,7 @@ class GetNetworkCoinStatusUseCase(
|
|||
userWalletId = userWalletId,
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
isSingleWalletWithTokens = isSingleWalletWithTokens,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -41,6 +43,7 @@ class GetNetworkCoinStatusUseCase(
|
|||
userWalletId: UserWalletId,
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
isSingleWalletWithTokens: Boolean,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
val operations = CurrenciesStatusesOperations(
|
||||
currenciesRepository = currenciesRepository,
|
||||
|
|
@ -48,8 +51,12 @@ class GetNetworkCoinStatusUseCase(
|
|||
networksRepository = networksRepository,
|
||||
userWalletId = userWalletId,
|
||||
)
|
||||
|
||||
return operations.getNetworkCoinFlow(networkId, derivationPath).map { maybeCurrency ->
|
||||
val networkFlow = if (isSingleWalletWithTokens) {
|
||||
operations.getNetworkCoinForSingleWalletWithTokenFlow(networkId)
|
||||
} else {
|
||||
operations.getNetworkCoinFlow(networkId, derivationPath)
|
||||
}
|
||||
return networkFlow.map { maybeCurrency ->
|
||||
maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,44 @@ internal class CurrenciesStatusesOperations(
|
|||
}
|
||||
}
|
||||
|
||||
fun getCardCurrenciesStatusesFlow(): Flow<Either<Error, List<CryptoCurrencyStatus>>> {
|
||||
return flow {
|
||||
val nonEmptyCurrencies = recover(
|
||||
block = { getCurrenciesFromCard(userWalletId) },
|
||||
recover = {
|
||||
emit(it.left())
|
||||
return@flow
|
||||
},
|
||||
).toNonEmptyListOrNull()
|
||||
|
||||
if (nonEmptyCurrencies == null) {
|
||||
val emptyCurrenciesStatuses = emptyList<CryptoCurrencyStatus>()
|
||||
|
||||
emit(emptyCurrenciesStatuses.right())
|
||||
return@flow
|
||||
}
|
||||
|
||||
val maybeLoadingCurrenciesStatuses = createCurrenciesStatuses(
|
||||
currencies = nonEmptyCurrencies,
|
||||
maybeNetworkStatuses = null,
|
||||
maybeQuotes = null,
|
||||
)
|
||||
|
||||
emit(maybeLoadingCurrenciesStatuses)
|
||||
|
||||
val (networks, currenciesIds) = getIds(nonEmptyCurrencies)
|
||||
|
||||
val currenciesFlow = combine(
|
||||
getQuotes(currenciesIds),
|
||||
getNetworksStatuses(networks),
|
||||
) { maybeQuotes, maybeNetworksStatuses ->
|
||||
createCurrenciesStatuses(nonEmptyCurrencies, maybeQuotes, maybeNetworksStatuses)
|
||||
}
|
||||
|
||||
emitAll(currenciesFlow)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getCurrencyStatusFlow(
|
||||
currencyId: CryptoCurrency.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
|
|
@ -79,6 +117,17 @@ internal class CurrenciesStatusesOperations(
|
|||
return getCurrencyStatusFlow(currency)
|
||||
}
|
||||
|
||||
suspend fun getCurrencyStatusSingleWalletWithTokensFlow(
|
||||
currencyId: CryptoCurrency.ID,
|
||||
): Flow<Either<Error, CryptoCurrencyStatus>> {
|
||||
val currency = recover(
|
||||
block = { getSingleCurrencyWalletWithCardTokensCurrency(currencyId) },
|
||||
recover = { return flowOf(it.left()) },
|
||||
)
|
||||
|
||||
return getCurrencyStatusFlow(currency)
|
||||
}
|
||||
|
||||
suspend fun getNetworkCoinFlow(
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
|
|
@ -91,6 +140,18 @@ internal class CurrenciesStatusesOperations(
|
|||
return getCurrencyStatusFlow(currency)
|
||||
}
|
||||
|
||||
suspend fun getNetworkCoinForSingleWalletWithTokenFlow(
|
||||
networkId: Network.ID,
|
||||
): Flow<Either<Error,
|
||||
CryptoCurrencyStatus,>,> {
|
||||
val currency = recover(
|
||||
block = { getNetworkCoinForSingleWalletWithToken(networkId) },
|
||||
recover = { return flowOf(it.left()) },
|
||||
)
|
||||
|
||||
return getCurrencyStatusFlow(currency)
|
||||
}
|
||||
|
||||
suspend fun getPrimaryCurrencyStatusFlow(): Flow<Either<Error, CryptoCurrencyStatus>> {
|
||||
val currency = recover(
|
||||
block = { getPrimaryCurrency() },
|
||||
|
|
@ -199,6 +260,14 @@ internal class CurrenciesStatusesOperations(
|
|||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.getSingleCurrencyWalletWithCardTokensCurrency(
|
||||
currencyId: CryptoCurrency.ID,
|
||||
): CryptoCurrency {
|
||||
return Either.catch { currenciesRepository.getSingleCurrencyWalletWithCardCurrency(userWalletId, currencyId) }
|
||||
.mapLeft { Error.DataError(it) }
|
||||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.getNetworkCoin(
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
|
|
@ -208,6 +277,16 @@ internal class CurrenciesStatusesOperations(
|
|||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.getNetworkCoinForSingleWalletWithToken(networkId: Network.ID): CryptoCurrency {
|
||||
return Either.catch {
|
||||
currenciesRepository.getSingleCurrencyWalletWithCardCurrencies(userWalletId)
|
||||
.find { it.network.id == networkId && it is CryptoCurrency.Coin }
|
||||
?: raise(Error.DataError(IllegalStateException("Coin with network $networkId not found for this card")))
|
||||
}
|
||||
.mapLeft { Error.DataError(it) }
|
||||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.getPrimaryCurrency(): CryptoCurrency {
|
||||
return catch(
|
||||
block = { currenciesRepository.getSingleCurrencyWalletPrimaryCurrency(userWalletId) },
|
||||
|
|
@ -215,6 +294,12 @@ internal class CurrenciesStatusesOperations(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.getCurrenciesFromCard(userWalletId: UserWalletId): List<CryptoCurrency> {
|
||||
return catch({ currenciesRepository.getSingleCurrencyWalletWithCardCurrencies(userWalletId) }) {
|
||||
raise(Error.DataError(it))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getQuotes(tokensIds: NonEmptySet<CryptoCurrency.ID>): Flow<Either<Error, Set<Quote>>> {
|
||||
return quotesRepository.getQuotesUpdates(tokensIds)
|
||||
.map<Set<Quote>, Either<Error, Set<Quote>>> { quotes ->
|
||||
|
|
|
|||
|
|
@ -39,6 +39,16 @@ internal class TokenListOperations(
|
|||
}
|
||||
}
|
||||
|
||||
fun getTokenListForSingleCurrencyFlow(): Flow<Either<Error, TokenList>> {
|
||||
return flow {
|
||||
emit(
|
||||
either {
|
||||
createTokenList()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Raise<Error>.createTokenList(isGrouped: Boolean, isSortedByBalance: Boolean): TokenList {
|
||||
val nonEmptyCurrencies = tokens.toNonEmptyListOrNull()
|
||||
?: return TokenList.Empty
|
||||
|
|
@ -55,6 +65,22 @@ internal class TokenListOperations(
|
|||
)
|
||||
}
|
||||
|
||||
private fun Raise<Error>.createTokenList(): TokenList {
|
||||
val nonEmptyCurrencies = tokens.toNonEmptyListOrNull()
|
||||
?: return TokenList.Empty
|
||||
|
||||
val isAnyTokenLoading = nonEmptyCurrencies.any { it.value is CryptoCurrencyStatus.Loading }
|
||||
val fiatBalanceOperations = TokenListFiatBalanceOperations(nonEmptyCurrencies, isAnyTokenLoading)
|
||||
|
||||
return createTokenList(
|
||||
currencies = nonEmptyCurrencies,
|
||||
fiatBalance = fiatBalanceOperations.calculateFiatBalance(),
|
||||
isAnyTokenLoading = isAnyTokenLoading,
|
||||
isGrouped = false,
|
||||
isSortedByBalance = false,
|
||||
)
|
||||
}
|
||||
|
||||
private fun Raise<Error>.createTokenList(
|
||||
currencies: NonEmptyList<CryptoCurrencyStatus>,
|
||||
fiatBalance: TokenList.FiatBalance,
|
||||
|
|
|
|||
|
|
@ -68,6 +68,31 @@ interface CurrenciesRepository {
|
|||
*/
|
||||
suspend fun getSingleCurrencyWalletPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency
|
||||
|
||||
/**
|
||||
* Retrieves the cryptocurrencies for a specific single-currency user wallet with tokens on the card.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @return The primary cryptocurrency associated with the user wallet.
|
||||
* @throws com.tangem.domain.core.error.DataError.UserWalletError.WrongUserWallet If multi-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
suspend fun getSingleCurrencyWalletWithCardCurrencies(userWalletId: UserWalletId): List<CryptoCurrency>
|
||||
|
||||
/**
|
||||
* Retrieves the cryptocurrency for a specific single-currency user old wallet
|
||||
* that stores token on card
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @param id The unique identifier of the cryptocurrency to be retrieved.
|
||||
* @return The cryptocurrency associated with the user wallet and ID.
|
||||
* @throws com.tangem.domain.core.error.DataError.UserWalletError.WrongUserWallet If single-currency user wallet
|
||||
* ID provided.
|
||||
*/
|
||||
suspend fun getSingleCurrencyWalletWithCardCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
id: CryptoCurrency.ID,
|
||||
): CryptoCurrency
|
||||
|
||||
/**
|
||||
* Retrieves updates of the list of cryptocurrencies within a multi-currency wallet.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -60,6 +60,17 @@ internal class MockCurrenciesRepository(
|
|||
return token.getOrElse { e -> throw e }
|
||||
}
|
||||
|
||||
override suspend fun getSingleCurrencyWalletWithCardCurrencies(userWalletId: UserWalletId): List<CryptoCurrency> {
|
||||
return tokens.first().getOrElse { e -> throw e }
|
||||
}
|
||||
|
||||
override suspend fun getSingleCurrencyWalletWithCardCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
id: CryptoCurrency.ID,
|
||||
): CryptoCurrency {
|
||||
return token.getOrElse { e -> throw e }
|
||||
}
|
||||
|
||||
override fun getMultiCurrencyWalletCurrenciesUpdates(userWalletId: UserWalletId): Flow<List<CryptoCurrency>> {
|
||||
return tokens.map { it.getOrElse { e -> throw e } }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.tangem.domain.tokens.models.analytics.TokenReceiveAnalyticsEvent
|
|||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetExploreUrlUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
|
||||
|
|
@ -133,10 +134,12 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
|
||||
private fun updateWarnings() {
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val wallet = getUserWalletUseCase(userWalletId).getOrElse { return@launch }
|
||||
getCurrencyWarningsUseCase.invoke(
|
||||
userWalletId = userWalletId,
|
||||
currency = cryptoCurrency,
|
||||
derivationPath = cryptoCurrency.network.derivationPath,
|
||||
isSingleWalletWithTokens = isSingleWalletWithTokens(wallet),
|
||||
)
|
||||
.distinctUntilChanged()
|
||||
.onEach { uiState = stateFactory.getStateWithNotifications(it) }
|
||||
|
|
@ -145,22 +148,30 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun updateMarketPrice() {
|
||||
getCurrencyStatusUpdatesUseCase(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = cryptoCurrency.id,
|
||||
derivationPath = cryptoCurrency.network.derivationPath,
|
||||
)
|
||||
.distinctUntilChanged()
|
||||
.onEach { either ->
|
||||
uiState = stateFactory.getCurrencyLoadedBalanceState(either)
|
||||
either.onRight { status ->
|
||||
cryptoCurrencyStatus = status
|
||||
updateButtons(userWalletId = userWalletId, currencyStatus = status)
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val wallet = getUserWalletUseCase(userWalletId).getOrElse { return@launch }
|
||||
getCurrencyStatusUpdatesUseCase(
|
||||
userWalletId = userWalletId,
|
||||
currencyId = cryptoCurrency.id,
|
||||
derivationPath = cryptoCurrency.network.derivationPath,
|
||||
isSingleWalletWithTokens = isSingleWalletWithTokens(wallet),
|
||||
)
|
||||
.distinctUntilChanged()
|
||||
.onEach { either ->
|
||||
uiState = stateFactory.getCurrencyLoadedBalanceState(either)
|
||||
either.onRight { status ->
|
||||
cryptoCurrencyStatus = status
|
||||
updateButtons(userWalletId = userWalletId, currencyStatus = status)
|
||||
}
|
||||
}
|
||||
}
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(viewModelScope)
|
||||
.saveIn(marketPriceJobHolder)
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(viewModelScope)
|
||||
.saveIn(marketPriceJobHolder)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSingleWalletWithTokens(userWallet: UserWallet): Boolean {
|
||||
return userWallet.scanResponse.walletData?.token != null && !userWallet.isMultiCurrency
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -251,10 +262,12 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
|
||||
private fun sendToken(status: CryptoCurrencyStatus) {
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val wallet = getUserWalletUseCase(userWalletId).getOrElse { return@launch }
|
||||
val maybeCoinStatus = getNetworkCoinStatusUseCase(
|
||||
userWalletId = userWalletId,
|
||||
networkId = status.currency.network.id,
|
||||
derivationPath = status.currency.network.derivationPath,
|
||||
isSingleWalletWithTokens = isSingleWalletWithTokens(wallet),
|
||||
).firstOrNull()
|
||||
|
||||
maybeCoinStatus?.onRight { coinStatus ->
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ internal sealed class WalletMultiCurrencyState : WalletState.ContentState() {
|
|||
override val tokensListState: WalletTokensListState,
|
||||
override val event: StateEvent<WalletEvent> = consumedEvent(),
|
||||
override val isBalanceHidden: Boolean,
|
||||
val isManageTokensAvailable: Boolean = true,
|
||||
val tokenActionsBottomSheet: ActionsBottomSheetConfig?,
|
||||
val onManageTokensClick: () -> Unit,
|
||||
) : WalletMultiCurrencyState()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.factory
|
||||
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
||||
data class TokenListWithWallet(
|
||||
val tokenList: TokenList,
|
||||
val wallet: UserWallet,
|
||||
)
|
||||
|
|
@ -31,7 +31,7 @@ internal class WalletLoadedTokensListConverter(
|
|||
appCurrencyProvider: Provider<AppCurrency>,
|
||||
currentWalletProvider: Provider<UserWallet>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) : Converter<Either<TokenListError, TokenList>, WalletState> {
|
||||
) : Converter<Either<TokenListError, TokenListWithWallet>, WalletState> {
|
||||
|
||||
private val tokenListStateConverter = TokenListToWalletStateConverter(
|
||||
currentStateProvider = currentStateProvider,
|
||||
|
|
@ -40,7 +40,7 @@ internal class WalletLoadedTokensListConverter(
|
|||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
override fun convert(value: Either<TokenListError, TokenList>): WalletState {
|
||||
override fun convert(value: Either<TokenListError, TokenListWithWallet>): WalletState {
|
||||
return value.fold(
|
||||
ifLeft = tokenListErrorConverter::convert,
|
||||
ifRight = tokenListStateConverter::convert,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,9 @@ internal class WalletSkeletonStateConverter(
|
|||
override fun convert(value: SkeletonModel): WalletState.ContentState {
|
||||
val selectedWallet = value.wallets[value.selectedWalletIndex]
|
||||
|
||||
return if (selectedWallet.isMultiCurrency) {
|
||||
val isSingleWalletWithToken = !selectedWallet.isMultiCurrency &&
|
||||
selectedWallet.scanResponse.walletData?.token != null
|
||||
return if (selectedWallet.isMultiCurrency || isSingleWalletWithToken) {
|
||||
createMultiCurrencyState(value = value)
|
||||
} else {
|
||||
createSingleCurrencyState(value = value, currencyName = selectedWallet.getPrimaryCurrencyName())
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import com.tangem.domain.tokens.error.CurrencyStatusError
|
|||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.TokenActionsState
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import com.tangem.domain.txhistory.models.TxHistoryListError
|
||||
import com.tangem.domain.txhistory.models.TxHistoryStateError
|
||||
|
|
@ -160,8 +159,8 @@ internal class WalletStateFactory(
|
|||
)
|
||||
}
|
||||
|
||||
fun getStateByTokensList(maybeTokenList: Either<TokenListError, TokenList>): WalletState {
|
||||
return loadedTokensListConverter.convert(maybeTokenList)
|
||||
fun getStateByTokensList(maybeTokenListWithWallet: Either<TokenListError, TokenListWithWallet>): WalletState {
|
||||
return loadedTokensListConverter.convert(maybeTokenListWithWallet)
|
||||
}
|
||||
|
||||
fun getStateByTokenListError(error: TokenListError): WalletState {
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ private fun BaseScaffold(
|
|||
topBar = { WalletTopBar(config = state.topBarConfig) },
|
||||
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
|
||||
floatingActionButton = {
|
||||
if (state is WalletMultiCurrencyState.Content) {
|
||||
if (state is WalletMultiCurrencyState.Content && state.isManageTokensAvailable) {
|
||||
ManageTokensButton(onManageTokensClick = state.onManageTokensClick)
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.tangem.domain.tokens.model.TokenList
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState.OrganizeTokensButtonState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState.TokensListItemState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.factory.TokenListWithWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
|
|
@ -18,23 +19,25 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
internal class TokenListToContentItemsConverter(
|
||||
appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
) : Converter<TokenList, WalletTokensListState> {
|
||||
) : Converter<TokenListWithWallet, WalletTokensListState> {
|
||||
|
||||
private val tokenStatusConverter = CryptoCurrencyStatusToTokenItemConverter(
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
override fun convert(value: TokenList): WalletTokensListState {
|
||||
return when (value) {
|
||||
override fun convert(value: TokenListWithWallet): WalletTokensListState {
|
||||
val isSingleCurrencyWalletWithToken = !value.wallet.isMultiCurrency &&
|
||||
value.wallet.scanResponse.walletData?.token != null
|
||||
return when (val tokenList = value.tokenList) {
|
||||
is TokenList.Empty -> WalletTokensListState.Empty
|
||||
is TokenList.GroupedByNetwork -> WalletTokensListState.Content(
|
||||
items = value.mapToMultiCurrencyItems(),
|
||||
organizeTokensButton = value.mapToOrganizeTokensButtonState(),
|
||||
items = tokenList.mapToMultiCurrencyItems(),
|
||||
organizeTokensButton = tokenList.mapToOrganizeTokensButtonState(isSingleCurrencyWalletWithToken),
|
||||
)
|
||||
is TokenList.Ungrouped -> WalletTokensListState.Content(
|
||||
items = value.mapToMultiCurrencyItems(),
|
||||
organizeTokensButton = value.mapToOrganizeTokensButtonState(),
|
||||
items = tokenList.mapToMultiCurrencyItems(),
|
||||
organizeTokensButton = tokenList.mapToOrganizeTokensButtonState(isSingleCurrencyWalletWithToken),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -51,17 +54,23 @@ internal class TokenListToContentItemsConverter(
|
|||
}
|
||||
}
|
||||
|
||||
private fun TokenList.GroupedByNetwork.mapToOrganizeTokensButtonState(): OrganizeTokensButtonState {
|
||||
private fun TokenList.GroupedByNetwork.mapToOrganizeTokensButtonState(
|
||||
isSingleCurrencyWithTokenWallet: Boolean,
|
||||
): OrganizeTokensButtonState {
|
||||
return getOrganizeTokensButtonState(
|
||||
isLoading = totalFiatBalance is TokenList.FiatBalance.Loading,
|
||||
currenciesSize = groups.flatMap(NetworkGroup::currencies).size,
|
||||
isSingleCurrencyWithTokenWallet = isSingleCurrencyWithTokenWallet,
|
||||
)
|
||||
}
|
||||
|
||||
private fun TokenList.Ungrouped.mapToOrganizeTokensButtonState(): OrganizeTokensButtonState {
|
||||
private fun TokenList.Ungrouped.mapToOrganizeTokensButtonState(
|
||||
isSingleCurrencyWithTokenWallet: Boolean,
|
||||
): OrganizeTokensButtonState {
|
||||
return getOrganizeTokensButtonState(
|
||||
isLoading = totalFiatBalance is TokenList.FiatBalance.Loading,
|
||||
currenciesSize = currencies.size,
|
||||
isSingleCurrencyWithTokenWallet = isSingleCurrencyWithTokenWallet,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -88,8 +97,12 @@ internal class TokenListToContentItemsConverter(
|
|||
return this
|
||||
}
|
||||
|
||||
private fun getOrganizeTokensButtonState(isLoading: Boolean, currenciesSize: Int): OrganizeTokensButtonState {
|
||||
return if (currenciesSize > 1) {
|
||||
private fun getOrganizeTokensButtonState(
|
||||
isLoading: Boolean,
|
||||
currenciesSize: Int,
|
||||
isSingleCurrencyWithTokenWallet: Boolean,
|
||||
): OrganizeTokensButtonState {
|
||||
return if (currenciesSize > 1 && !isSingleCurrencyWithTokenWallet) {
|
||||
OrganizeTokensButtonState.Visible(
|
||||
isEnabled = !isLoading,
|
||||
onClick = clickIntents::onOrganizeTokensClick,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencySt
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletsListConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.factory.TokenListWithWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
|
@ -18,19 +19,23 @@ internal class TokenListToWalletStateConverter(
|
|||
private val currentWalletProvider: Provider<UserWallet>,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) : Converter<TokenList, WalletState> {
|
||||
) : Converter<TokenListWithWallet, WalletState> {
|
||||
|
||||
private val tokenListToContentConverter = TokenListToContentItemsConverter(
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
override fun convert(value: TokenList): WalletState {
|
||||
override fun convert(value: TokenListWithWallet): WalletState {
|
||||
val tokenList = value.tokenList
|
||||
val isSingleCurrencyWalletWithToken = !value.wallet.isMultiCurrency &&
|
||||
value.wallet.scanResponse.walletData?.token != null
|
||||
return when (val state = currentStateProvider()) {
|
||||
is WalletMultiCurrencyState.Content -> {
|
||||
state.copy(
|
||||
walletsListConfig = state.updateSelectedWallet(fiatBalance = value.totalFiatBalance),
|
||||
walletsListConfig = state.updateSelectedWallet(fiatBalance = tokenList.totalFiatBalance),
|
||||
tokensListState = tokenListToContentConverter.convert(value = value),
|
||||
isManageTokensAvailable = !isSingleCurrencyWalletWithToken,
|
||||
)
|
||||
}
|
||||
is WalletMultiCurrencyState.Locked,
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ import com.tangem.feature.wallet.presentation.wallet.analytics.PortfolioEvent
|
|||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.factory.TokenListWithWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.factory.WalletStateFactory
|
||||
import com.tangem.operations.derivation.ExtendedPublicKeysMap
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -92,6 +93,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
private val updateWalletUseCase: UpdateWalletUseCase,
|
||||
private val deleteWalletUseCase: DeleteWalletUseCase,
|
||||
private val getTokenListUseCase: GetTokenListUseCase,
|
||||
private val getCardTokensListUseCase: GetCardTokensListUseCase,
|
||||
private val fetchTokenListUseCase: FetchTokenListUseCase,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
|
||||
|
|
@ -592,10 +594,14 @@ internal class WalletViewModel @Inject constructor(
|
|||
viewModelScope.launch(dispatchers.io) {
|
||||
val userWallet = getWallet(index = state.walletsListConfig.selectedWalletIndex)
|
||||
|
||||
val isSingleWalletWithTokens = !userWallet.isMultiCurrency &&
|
||||
userWallet.scanResponse.walletData?.token != null
|
||||
|
||||
getNetworkCoinStatusUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
networkId = cryptoCurrencyStatus.currency.network.id,
|
||||
derivationPath = cryptoCurrencyStatus.currency.network.derivationPath,
|
||||
isSingleWalletWithTokens = isSingleWalletWithTokens,
|
||||
)
|
||||
.take(count = 1)
|
||||
.collectLatest {
|
||||
|
|
@ -916,6 +922,9 @@ internal class WalletViewModel @Inject constructor(
|
|||
uiState = stateFactory.getLockedState()
|
||||
}
|
||||
wallet.isMultiCurrency -> getMultiCurrencyContent(wallet, index)
|
||||
isSingleWalletWithTokens(wallet) -> {
|
||||
getSingleCurrencyWithTokenContent(index)
|
||||
}
|
||||
!wallet.isMultiCurrency -> getSingleCurrencyContent(index)
|
||||
}
|
||||
}
|
||||
|
|
@ -933,7 +942,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
tokenListFlow
|
||||
.distinctUntilChanged()
|
||||
.onEach { maybeTokenList ->
|
||||
uiState = stateFactory.getStateByTokensList(maybeTokenList)
|
||||
uiState = stateFactory.getStateByTokensList(maybeTokenList.getTokenListWithWallet(wallet))
|
||||
|
||||
maybeTokenList.onRight { checkMultiWalletWithFunds(it) }
|
||||
|
||||
|
|
@ -978,6 +987,10 @@ internal class WalletViewModel @Inject constructor(
|
|||
.saveIn(updateWcJobHolder)
|
||||
}
|
||||
|
||||
private fun isSingleWalletWithTokens(userWallet: UserWallet): Boolean {
|
||||
return userWallet.scanResponse.walletData?.token != null && !userWallet.isMultiCurrency
|
||||
}
|
||||
|
||||
private fun List<CryptoCurrencyStatus>.isAllCurrenciesLoaded(): Boolean {
|
||||
return !this.any { it.value is CryptoCurrencyStatus.Loading }
|
||||
}
|
||||
|
|
@ -1008,6 +1021,14 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun Either<TokenListError, TokenList>.getTokenListWithWallet(
|
||||
userWallet: UserWallet,
|
||||
): Either<TokenListError, TokenListWithWallet> {
|
||||
return this.map {
|
||||
TokenListWithWallet(it, userWallet)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSingleCurrencyContent(index: Int) {
|
||||
val wallet = getWallet(index)
|
||||
getPrimaryCurrencyStatusUpdatesUseCase(wallet.walletId)
|
||||
|
|
@ -1032,6 +1053,30 @@ internal class WalletViewModel @Inject constructor(
|
|||
.saveIn(marketPriceJobHolder)
|
||||
}
|
||||
|
||||
private fun getSingleCurrencyWithTokenContent(walletIndex: Int) {
|
||||
val state = requireNotNull(uiState as? WalletMultiCurrencyState) {
|
||||
"Impossible to get a token list updates if state isn't WalletMultiCurrencyState"
|
||||
}
|
||||
|
||||
val wallet = getWallet(walletIndex)
|
||||
|
||||
getCardTokensListUseCase(userWalletId = state.walletsListConfig.wallets[walletIndex].id)
|
||||
.distinctUntilChanged()
|
||||
.onEach { maybeTokenList ->
|
||||
uiState = stateFactory.getStateByTokensList(maybeTokenList.getTokenListWithWallet(wallet))
|
||||
|
||||
maybeTokenList.onRight { checkMultiWalletWithFunds(it) }
|
||||
|
||||
updateNotifications(
|
||||
index = walletIndex,
|
||||
tokenList = maybeTokenList.fold(ifLeft = { null }, ifRight = { it }),
|
||||
)
|
||||
}
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(viewModelScope)
|
||||
.saveIn(tokensJobHolder)
|
||||
}
|
||||
|
||||
private fun updateTxHistory(userWalletId: UserWalletId, currency: CryptoCurrency, refresh: Boolean) {
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val txHistoryItemsCountEither = txHistoryItemsCountUseCase(
|
||||
|
|
@ -1095,10 +1140,15 @@ internal class WalletViewModel @Inject constructor(
|
|||
val wallet = getWallet(walletIndex)
|
||||
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val result = fetchTokenListUseCase(wallet.walletId, refresh = true)
|
||||
if (isSingleWalletWithTokens(wallet)) {
|
||||
// TODO add refresh for nodl cards ([REDACTED_JIRA])
|
||||
delay(timeMillis = 1000)
|
||||
} else {
|
||||
val result = fetchTokenListUseCase(wallet.walletId, refresh = true)
|
||||
uiState = result.fold(stateFactory::getStateByTokenListError) { uiState }
|
||||
}
|
||||
|
||||
uiState = stateFactory.getRefreshedState()
|
||||
uiState = result.fold(stateFactory::getStateByTokenListError) { uiState }
|
||||
}.saveIn(refreshContentJobHolder)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue