From c1b426ef9f3b0ac0d6d01de0e85318b80139773e Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 16 Sep 2024 17:05:19 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../com/tangem/common/routing/AppRoute.kt | 5 +- .../impl/model/TokenActionsHandler.kt | 1 + .../models/ui/TokensDataStateExpress.kt | 8 +++ .../DefaultInitialToCurrencyResolver.kt | 17 ++--- .../swap/domain/InitialToCurrencyResolver.kt | 5 +- .../feature/swap/domain/SwapInteractor.kt | 3 +- .../feature/swap/domain/SwapInteractorImpl.kt | 10 +-- .../swap/domain/di/SwapDomainModule.kt | 4 -- .../feature/swap/viewmodels/SwapViewModel.kt | 63 ++++++++++++------- 9 files changed, 75 insertions(+), 41 deletions(-) diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt index 0d8cee2df5..2c60258331 100644 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt +++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt @@ -220,13 +220,16 @@ sealed class AppRoute(val path: String) : Route { data class Swap( val currency: CryptoCurrency, val userWalletId: UserWalletId, - ) : AppRoute(path = "/swap/${currency.id.value}/${userWalletId.stringValue}"), RouteBundleParams { + val isInitialReverseOrder: Boolean = false, + ) : AppRoute(path = "/swap/${currency.id.value}/${userWalletId.stringValue}/$isInitialReverseOrder"), + RouteBundleParams { override fun getBundle(): Bundle = bundle(serializer()) companion object { const val CURRENCY_BUNDLE_KEY = "currency" const val USER_WALLET_ID_KEY = "userWalletId" + const val IS_INITIAL_REVERSE_ORDER = "isInitialReverseOrder" } } diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt index fc2464a7f9..8d7bc12e6c 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt @@ -151,6 +151,7 @@ internal class TokenActionsHandler @AssistedInject constructor( AppRoute.Swap( currency = cryptoCurrencyData.status.currency, userWalletId = cryptoCurrencyData.userWallet.walletId, + isInitialReverseOrder = true, ), ) } diff --git a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/TokensDataStateExpress.kt b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/TokensDataStateExpress.kt index 1aa9ba51d1..93e4308f49 100644 --- a/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/TokensDataStateExpress.kt +++ b/features/swap/domain/models/src/main/java/com/tangem/feature/swap/domain/models/ui/TokensDataStateExpress.kt @@ -18,6 +18,14 @@ data class TokensDataStateExpress( } } +fun TokensDataStateExpress.getGroupWithReverse(isReverseFromTo: Boolean): CurrenciesGroup { + return if (isReverseFromTo) { + this.fromGroup + } else { + this.toGroup + } +} + data class CurrenciesGroup( val available: List, val unavailable: List, diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/DefaultInitialToCurrencyResolver.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/DefaultInitialToCurrencyResolver.kt index 42e6f2331b..42d6c02e93 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/DefaultInitialToCurrencyResolver.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/DefaultInitialToCurrencyResolver.kt @@ -2,31 +2,34 @@ package com.tangem.feature.swap.domain import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus -import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase +import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.swap.domain.models.ui.TokensDataStateExpress +import com.tangem.feature.swap.domain.models.ui.getGroupWithReverse import java.math.BigDecimal internal class DefaultInitialToCurrencyResolver( - private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, private val swapTransactionRepository: SwapTransactionRepository, ) : InitialToCurrencyResolver { override suspend fun tryGetFromCache( + userWallet: UserWallet, initialCryptoCurrency: CryptoCurrency, state: TokensDataStateExpress, + isReverseFromTo: Boolean, ): CryptoCurrencyStatus? { - val selectedId = getSelectedWalletSyncUseCase().getOrNull() ?: return null - val id = swapTransactionRepository.getLastSwappedCryptoCurrencyId(selectedId.walletId) ?: return null + val id = swapTransactionRepository.getLastSwappedCryptoCurrencyId(userWallet.walletId) ?: return null return if (id != initialCryptoCurrency.id.value) { - state.toGroup.available.find { it.currencyStatus.currency.id.value == id }?.currencyStatus + val group = state.getGroupWithReverse(isReverseFromTo) + group.available.find { it.currencyStatus.currency.id.value == id }?.currencyStatus } else { null } } - override fun tryGetWithMaxAmount(state: TokensDataStateExpress): CryptoCurrencyStatus? { - return state.toGroup.available.maxByOrNull { + override fun tryGetWithMaxAmount(state: TokensDataStateExpress, isReverseFromTo: Boolean): CryptoCurrencyStatus? { + val group = state.getGroupWithReverse(isReverseFromTo) + return group.available.maxByOrNull { it.currencyStatus.value.fiatAmount ?: BigDecimal.ZERO }?.currencyStatus } diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/InitialToCurrencyResolver.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/InitialToCurrencyResolver.kt index da0b0f1b37..6c15921326 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/InitialToCurrencyResolver.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/InitialToCurrencyResolver.kt @@ -2,14 +2,17 @@ package com.tangem.feature.swap.domain import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.swap.domain.models.ui.TokensDataStateExpress interface InitialToCurrencyResolver { suspend fun tryGetFromCache( + userWallet: UserWallet, initialCryptoCurrency: CryptoCurrency, state: TokensDataStateExpress, + isReverseFromTo: Boolean, ): CryptoCurrencyStatus? - fun tryGetWithMaxAmount(state: TokensDataStateExpress): CryptoCurrencyStatus? + fun tryGetWithMaxAmount(state: TokensDataStateExpress, isReverseFromTo: Boolean): CryptoCurrencyStatus? } \ No newline at end of file diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt index 8c6f6a8de7..3154fa4293 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt @@ -79,9 +79,10 @@ interface SwapInteractor { */ fun getTokenBalance(token: CryptoCurrencyStatus): SwapAmount - suspend fun selectInitialCurrencyToSwap( + suspend fun getInitialCurrencyToSwap( initialCryptoCurrency: CryptoCurrency, state: TokensDataStateExpress, + isReverseFromTo: Boolean, ): CryptoCurrencyStatus? fun getNativeToken(networkId: String): CryptoCurrency diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index b892338148..2a1a873a96 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -965,13 +965,15 @@ internal class SwapInteractorImpl @AssistedInject constructor( return SwapAmount(token.value.amount ?: BigDecimal.ZERO, token.currency.decimals) } - override suspend fun selectInitialCurrencyToSwap( + override suspend fun getInitialCurrencyToSwap( initialCryptoCurrency: CryptoCurrency, state: TokensDataStateExpress, + isReverseFromTo: Boolean, ): CryptoCurrencyStatus? { - return initialToCurrencyResolver.tryGetFromCache(initialCryptoCurrency, state) - ?: initialToCurrencyResolver.tryGetWithMaxAmount(state) - ?: state.toGroup.available.firstOrNull()?.currencyStatus + val group = state.getGroupWithReverse(isReverseFromTo) + return initialToCurrencyResolver.tryGetFromCache(userWallet, initialCryptoCurrency, state, isReverseFromTo) + ?: initialToCurrencyResolver.tryGetWithMaxAmount(state, isReverseFromTo) + ?: group.available.firstOrNull()?.currencyStatus } override fun getNativeToken(networkId: String): CryptoCurrency { diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt index 9f95b3e0c6..52e15d5933 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/di/SwapDomainModule.kt @@ -5,8 +5,6 @@ import com.tangem.domain.tokens.GetCryptoCurrencyStatusesSyncUseCase 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.transaction.usecase.* -import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.feature.swap.domain.* import com.tangem.lib.crypto.TransactionManager import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -60,11 +58,9 @@ internal class SwapDomainModule { @Provides @Singleton fun provideInitialToCurrencyResolver( - getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase, swapTransactionRepository: SwapTransactionRepository, ): InitialToCurrencyResolver { return DefaultInitialToCurrencyResolver( - getSelectedWalletSyncUseCase = getSelectedWalletSyncUseCase, swapTransactionRepository = swapTransactionRepository, ) } diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt index 1958445de2..cc9b9d3132 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt @@ -84,6 +84,9 @@ internal class SwapViewModel @Inject constructor( ?.unbundle(UserWalletId.serializer()) ?: error("no expected parameter UserWalletId found") + private val isInitiallyReversed: Boolean = savedStateHandle.get(AppRoute.Swap.IS_INITIAL_REVERSE_ORDER) + ?: false + private val swapInteractor = swapInteractorFactory.create(userWalletId) private lateinit var initialCryptoCurrencyStatus: CryptoCurrencyStatus @@ -137,7 +140,7 @@ internal class SwapViewModel @Inject constructor( uiState = stateBuilder.addAlert(uiState = uiState, onClick = swapRouter::back) } else { initialCryptoCurrencyStatus = cryptoCurrencyStatus - initTokens() + initTokens(isInitiallyReversed) } } } @@ -180,18 +183,21 @@ internal class SwapViewModel @Inject constructor( analyticsEventHandler.send(SwapEvents.ChooseTokenScreenOpened(availableTokens = isAnyAvailableTokens)) } - private fun initTokens() { + private fun initTokens(isReverseFromTo: Boolean) { viewModelScope.launch(dispatchers.main) { runCatching(dispatchers.io) { swapInteractor.getTokensDataState(initialCryptoCurrency) }.onSuccess { state -> updateTokensState(state) + val selectedCurrency = swapInteractor.getInitialCurrencyToSwap( + initialCryptoCurrency = initialCryptoCurrency, + state = state, + isReverseFromTo = isReverseFromTo, + ) applyInitialTokenChoice( - state, - swapInteractor.selectInitialCurrencyToSwap( - initialCryptoCurrency, - state, - ), + state = state, + selectedCurrency = selectedCurrency, + isReverseFromTo = isReverseFromTo, ) (dataState.fromCryptoCurrency?.currency as? CryptoCurrency.Coin)?.let { @@ -215,6 +221,7 @@ internal class SwapViewModel @Inject constructor( applyInitialTokenChoice( state = TokensDataStateExpress.EMPTY, selectedCurrency = null, + isReverseFromTo = isReverseFromTo, ) uiState = stateBuilder.createInitialErrorState( @@ -227,33 +234,43 @@ internal class SwapViewModel @Inject constructor( initialCryptoCurrency.network.backendId, ), ) - initTokens() + initTokens(isReverseFromTo) } } } } - private fun applyInitialTokenChoice(state: TokensDataStateExpress, selectedCurrency: CryptoCurrencyStatus?) { - val fromCurrencyStatus = initialCryptoCurrencyStatus - dataState = dataState.copy( - fromCryptoCurrency = fromCurrencyStatus, - toCryptoCurrency = selectedCurrency, - tokensDataState = state, - ) + private fun applyInitialTokenChoice( + state: TokensDataStateExpress, + selectedCurrency: CryptoCurrencyStatus?, + isReverseFromTo: Boolean, + ) { + // exceptional case if (selectedCurrency == null) { analyticsEventHandler.send(SwapEvents.NoticeNoAvailableTokensToSwap) uiState = stateBuilder.createNoAvailableTokensToSwapState( uiStateHolder = uiState, - fromToken = fromCurrencyStatus, - ) - } else { - startLoadingQuotes( - fromToken = fromCurrencyStatus, - toToken = selectedCurrency, - amount = lastAmount.value, - toProvidersList = findSwapProviders(fromCurrencyStatus, selectedCurrency), + fromToken = initialCryptoCurrencyStatus, ) + return } + isOrderReversed = isReverseFromTo + val (fromCurrencyStatus, toCurrencyStatus) = if (isOrderReversed) { + selectedCurrency to initialCryptoCurrencyStatus + } else { + initialCryptoCurrencyStatus to selectedCurrency + } + dataState = dataState.copy( + fromCryptoCurrency = fromCurrencyStatus, + toCryptoCurrency = toCurrencyStatus, + tokensDataState = state, + ) + startLoadingQuotes( + fromToken = fromCurrencyStatus, + toToken = toCurrencyStatus, + amount = lastAmount.value, + toProvidersList = findSwapProviders(fromCurrencyStatus, toCurrencyStatus), + ) } private fun updateTokensState(tokenDataState: TokensDataStateExpress) {