Updated on 2026-08-14
This commit is contained in:
parent
df9318faef
commit
c1b426ef9f
9 changed files with 75 additions and 41 deletions
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ internal class TokenActionsHandler @AssistedInject constructor(
|
|||
AppRoute.Swap(
|
||||
currency = cryptoCurrencyData.status.currency,
|
||||
userWalletId = cryptoCurrencyData.userWallet.walletId,
|
||||
isInitialReverseOrder = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<CryptoCurrencySwapInfo>,
|
||||
val unavailable: List<CryptoCurrencySwapInfo>,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,9 @@ internal class SwapViewModel @Inject constructor(
|
|||
?.unbundle(UserWalletId.serializer())
|
||||
?: error("no expected parameter UserWalletId found")
|
||||
|
||||
private val isInitiallyReversed: Boolean = savedStateHandle.get<Boolean>(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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue