Updated on 2026-08-14
This commit is contained in:
commit
95f45bbd89
14 changed files with 148 additions and 75 deletions
|
|
@ -4,7 +4,6 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.blockchain.common.IconsUtil
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.domain.common.extensions.toCoinId
|
||||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency.ID
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
|
|
@ -55,8 +54,7 @@ internal fun getTokenIconUrl(blockchain: Blockchain, token: SdkToken): String? {
|
|||
internal fun getCoinIconUrl(blockchain: Blockchain): String? {
|
||||
val coinId = when (blockchain) {
|
||||
Blockchain.Unknown -> null
|
||||
Blockchain.TerraV1, Blockchain.TerraV2, Blockchain.Near -> blockchain.toCoinId()
|
||||
else -> blockchain.toNetworkId()
|
||||
else -> blockchain.toCoinId()
|
||||
}
|
||||
|
||||
return coinId?.let(::getTokenIconUrlFromDefaultHost)
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
AggregatedSwapDataModel(
|
||||
dataModel = QuoteModel(
|
||||
toTokenAmount = createFromAmountWithOffset(response.toAmount, response.toDecimals),
|
||||
allowanceContract = response.allowanceContract,
|
||||
),
|
||||
)
|
||||
} catch (ex: Exception) {
|
||||
|
|
@ -218,6 +219,7 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
derivationPath: String?,
|
||||
tokenDecimalCount: Int,
|
||||
tokenAddress: String,
|
||||
spenderAddress: String,
|
||||
): BigDecimal {
|
||||
val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" }
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
|
|
@ -225,7 +227,6 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
blockchain = blockchain,
|
||||
derivationPath = derivationPath,
|
||||
)
|
||||
val spenderAddress = addressForTrust(networkId)
|
||||
|
||||
val result = (walletManager as? Approver)?.getAllowance(
|
||||
spenderAddress,
|
||||
|
|
@ -248,6 +249,7 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
derivationPath: String?,
|
||||
currency: CryptoCurrency,
|
||||
amount: BigDecimal?,
|
||||
spenderAddress: String,
|
||||
): String {
|
||||
val blockchain =
|
||||
requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" }
|
||||
|
|
@ -256,7 +258,6 @@ internal class SwapRepositoryImpl @Inject constructor(
|
|||
blockchain = blockchain,
|
||||
derivationPath = derivationPath,
|
||||
)
|
||||
val spenderAddress = addressForTrust(networkId)
|
||||
|
||||
return (walletManager as? Approver)?.getApproveData(
|
||||
spenderAddress,
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
package com.tangem.feature.swap.converters
|
||||
|
||||
import com.tangem.datasource.api.oneinch.models.QuoteResponse
|
||||
import com.tangem.feature.swap.domain.models.createFromAmountWithOffset
|
||||
import com.tangem.feature.swap.domain.models.domain.QuoteModel
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
class QuotesConverter : Converter<QuoteResponse, QuoteModel> {
|
||||
|
||||
override fun convert(value: QuoteResponse): QuoteModel {
|
||||
return QuoteModel(
|
||||
toTokenAmount = createFromAmountWithOffset(value.toTokenAmount, value.toToken.decimals),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -197,6 +197,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
fromToken = permissionOptions.fromToken,
|
||||
spenderAddress = permissionOptions.spenderAddress,
|
||||
)
|
||||
} else {
|
||||
permissionOptions.approveData.approveData
|
||||
|
|
@ -289,8 +290,22 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
amount: SwapAmount,
|
||||
isBalanceWithoutFeeEnough: Boolean,
|
||||
): Pair<SwapProvider, SwapState> {
|
||||
val quotes = repository.findBestQuote(
|
||||
fromContractAddress = fromToken.currency.getContractAddress(),
|
||||
fromNetwork = fromToken.currency.network.backendId,
|
||||
toContractAddress = toToken.currency.getContractAddress(),
|
||||
toNetwork = toToken.currency.network.backendId,
|
||||
fromAmount = amount.toStringWithRightOffset(),
|
||||
fromDecimals = amount.decimals,
|
||||
providerId = provider.providerId,
|
||||
rateType = RateType.FLOAT,
|
||||
)
|
||||
|
||||
val fromTokenAddress = getTokenAddress(fromToken.currency)
|
||||
val isAllowedToSpend = isAllowedToSpend(networkId, fromToken.currency, amount)
|
||||
val isAllowedToSpend = quotes.dataModel?.allowanceContract?.let {
|
||||
isAllowedToSpend(networkId, fromToken.currency, amount, it)
|
||||
} ?: false
|
||||
|
||||
if (isAllowedToSpend && allowPermissionsHandler.isAddressAllowanceInProgress(fromTokenAddress)) {
|
||||
allowPermissionsHandler.removeAddressFromProgress(fromTokenAddress)
|
||||
transactionManager.updateWalletManager(networkId, derivationPath)
|
||||
|
|
@ -305,15 +320,16 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
selectedFee = selectedFee,
|
||||
)
|
||||
} else {
|
||||
provider to loadQuoteData(
|
||||
provider to getQuotesState(
|
||||
exchangeProviderType = ExchangeProviderType.DEX,
|
||||
networkId = networkId,
|
||||
quoteDataModel = quotes,
|
||||
amount = amount,
|
||||
fromTokenStatus = fromToken,
|
||||
toTokenStatus = toToken,
|
||||
fromToken = fromToken,
|
||||
toToken = toToken,
|
||||
networkId = networkId,
|
||||
isAllowedToSpend = isAllowedToSpend,
|
||||
isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough,
|
||||
provider = provider,
|
||||
providerType = provider.type,
|
||||
selectedFee = selectedFee,
|
||||
)
|
||||
}
|
||||
|
|
@ -501,16 +517,22 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun isAllowedToSpend(networkId: String, fromToken: CryptoCurrency, amount: SwapAmount): Boolean {
|
||||
private suspend fun isAllowedToSpend(
|
||||
networkId: String,
|
||||
fromToken: CryptoCurrency,
|
||||
amount: SwapAmount,
|
||||
spenderAddress: String,
|
||||
): Boolean {
|
||||
if (fromToken is CryptoCurrency.Coin) return true
|
||||
return getSelectedWalletSyncUseCase().fold(
|
||||
ifRight = { userWallet ->
|
||||
val allowance = repository.getAllowance(
|
||||
userWallet.walletId,
|
||||
networkId,
|
||||
derivationPath,
|
||||
getTokenDecimals(fromToken),
|
||||
getTokenAddress(fromToken),
|
||||
userWalletId = userWallet.walletId,
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
tokenDecimalCount = getTokenDecimals(fromToken),
|
||||
tokenAddress = getTokenAddress(fromToken),
|
||||
spenderAddress = spenderAddress,
|
||||
)
|
||||
allowance >= amount.value
|
||||
},
|
||||
|
|
@ -620,6 +642,8 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
fromToken = fromToken.currency,
|
||||
swapAmount = amount,
|
||||
quotesLoadedState = swapState,
|
||||
isAllowedToSpend = isAllowedToSpend,
|
||||
spenderAddress = requireNotNull(quoteModel.allowanceContract) { "Allowance contract is null" },
|
||||
)
|
||||
state.copy(
|
||||
preparedSwapConfigState = state.preparedSwapConfigState.copy(
|
||||
|
|
@ -785,20 +809,32 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
userWalletId = userWalletId,
|
||||
cryptoCurrency = fromToken.currency,
|
||||
).firstOrNull()
|
||||
txFeeResult?.getOrNull()?.let { txFee ->
|
||||
return txFee.toTxFeeState(networkId)
|
||||
}
|
||||
return txFeeResult?.fold(
|
||||
ifLeft = {
|
||||
TxFeeState.Empty
|
||||
},
|
||||
ifRight = { txFee ->
|
||||
txFee.toTxFeeState(networkId)
|
||||
},
|
||||
) ?: TxFeeState.Empty
|
||||
}
|
||||
return TxFeeState.Empty
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Suppress("LongParameterList", "LongMethod")
|
||||
private suspend fun updatePermissionState(
|
||||
networkId: String,
|
||||
fromToken: CryptoCurrency,
|
||||
swapAmount: SwapAmount,
|
||||
quotesLoadedState: SwapState.QuotesLoadedState,
|
||||
spenderAddress: String,
|
||||
isAllowedToSpend: Boolean,
|
||||
): SwapState.QuotesLoadedState {
|
||||
if (isAllowedToSpend) {
|
||||
return quotesLoadedState.copy(
|
||||
permissionState = PermissionDataState.Empty,
|
||||
)
|
||||
}
|
||||
// if token balance ZERO not show permission state to avoid user to spend money for fee
|
||||
val isTokenZeroBalance = getTokenBalance(networkId, fromToken).value.signum() == 0
|
||||
if (isTokenZeroBalance) {
|
||||
|
|
@ -817,20 +853,28 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
derivationPath = derivationPath,
|
||||
fromToken = fromToken,
|
||||
swapAmount = swapAmount,
|
||||
spenderAddress = spenderAddress,
|
||||
)
|
||||
val feeData = transactionManager.getFee(
|
||||
networkId = networkId,
|
||||
amountToSend = BigDecimal.ZERO,
|
||||
currencyToSend = swapCurrencyConverter.convert(repository.getNativeTokenForNetwork(networkId)),
|
||||
destinationAddress = getTokenAddress(fromToken),
|
||||
increaseBy = INCREASE_GAS_LIMIT_BY,
|
||||
data = transactionData,
|
||||
derivationPath = derivationPath,
|
||||
)
|
||||
val feeState = when (feeData) {
|
||||
is ProxyFees.MultipleFees -> feeData.proxyFeesToFeeState(networkId)
|
||||
is ProxyFees.SingleFee -> feeData.proxyFeesToFeeState(networkId)
|
||||
val feeData = try {
|
||||
transactionManager.getFee(
|
||||
networkId = networkId,
|
||||
amountToSend = BigDecimal.ZERO,
|
||||
currencyToSend = swapCurrencyConverter.convert(repository.getNativeTokenForNetwork(networkId)),
|
||||
destinationAddress = fromToken.getContractAddress(),
|
||||
increaseBy = INCREASE_GAS_LIMIT_BY,
|
||||
data = transactionData,
|
||||
derivationPath = derivationPath,
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Failed to get fee")
|
||||
null
|
||||
}
|
||||
val feeState = feeData?.let {
|
||||
when (feeData) {
|
||||
is ProxyFees.MultipleFees -> feeData.proxyFeesToFeeState(networkId)
|
||||
is ProxyFees.SingleFee -> feeData.proxyFeesToFeeState(networkId)
|
||||
}
|
||||
} ?: TxFeeState.Empty
|
||||
val fee = when (feeState) {
|
||||
TxFeeState.Empty -> BigDecimal.ZERO
|
||||
is TxFeeState.MultipleFeeState -> feeState.normalFee.feeValue
|
||||
|
|
@ -852,6 +896,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
fee = feeState,
|
||||
approveData = transactionData,
|
||||
fromTokenAmount = swapAmount,
|
||||
spenderAddress = spenderAddress,
|
||||
),
|
||||
),
|
||||
preparedSwapConfigState = quotesLoadedState.preparedSwapConfigState.copy(
|
||||
|
|
@ -1084,6 +1129,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
derivationPath: String?,
|
||||
fromToken: CryptoCurrency,
|
||||
swapAmount: SwapAmount? = null,
|
||||
spenderAddress: String,
|
||||
): String {
|
||||
return getSelectedWalletSyncUseCase().fold(
|
||||
ifRight = { userWallet ->
|
||||
|
|
@ -1093,6 +1139,7 @@ internal class SwapInteractorImpl @Inject constructor(
|
|||
derivationPath = derivationPath,
|
||||
currency = fromToken,
|
||||
amount = swapAmount?.value,
|
||||
spenderAddress = spenderAddress,
|
||||
)
|
||||
},
|
||||
ifLeft = {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ interface SwapRepository {
|
|||
*/
|
||||
fun getTangemFee(): Double
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Throws(IllegalStateException::class)
|
||||
suspend fun getAllowance(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -46,8 +47,10 @@ interface SwapRepository {
|
|||
derivationPath: String?,
|
||||
tokenDecimalCount: Int,
|
||||
tokenAddress: String,
|
||||
spenderAddress: String,
|
||||
): BigDecimal
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Throws(IllegalStateException::class)
|
||||
suspend fun getApproveData(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -55,6 +58,7 @@ interface SwapRepository {
|
|||
derivationPath: String?,
|
||||
currency: CryptoCurrency,
|
||||
amount: BigDecimal?,
|
||||
spenderAddress: String,
|
||||
): String
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ data class PermissionOptions(
|
|||
val approveData: RequestApproveStateData,
|
||||
val forTokenContractAddress: String,
|
||||
val fromToken: CryptoCurrency,
|
||||
val spenderAddress: String,
|
||||
val approveType: SwapApproveType,
|
||||
val txFee: TxFee,
|
||||
)
|
||||
|
|
@ -9,4 +9,5 @@ import com.tangem.feature.swap.domain.models.SwapAmount
|
|||
*/
|
||||
data class QuoteModel(
|
||||
val toTokenAmount: SwapAmount,
|
||||
val allowanceContract: String?,
|
||||
)
|
||||
|
|
@ -61,6 +61,7 @@ data class RequestApproveStateData(
|
|||
val fee: TxFeeState,
|
||||
val approveData: String,
|
||||
val fromTokenAmount: SwapAmount,
|
||||
val spenderAddress: String,
|
||||
)
|
||||
|
||||
// data class SwapStateData(
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ data class SwapStateHolder(
|
|||
val onSuccess: (() -> Unit)? = null,
|
||||
val onMaxAmountSelected: (() -> Unit)? = null,
|
||||
val onShowPermissionBottomSheet: () -> Unit = {},
|
||||
val onCancelPermissionBottomSheet: () -> Unit = {},
|
||||
)
|
||||
|
||||
sealed class SwapCardState {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ data class UiActions(
|
|||
val onBackClicked: () -> Unit,
|
||||
val onMaxAmountSelected: () -> Unit,
|
||||
val openPermissionBottomSheet: () -> Unit,
|
||||
val hidePermissionBottomSheet: () -> Unit,
|
||||
val onChangeApproveType: (ApproveType) -> Unit,
|
||||
// region new actions
|
||||
val onClickFee: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.tangem.feature.swap.models.states
|
|||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.feature.swap.models.SwapPermissionState
|
||||
|
||||
class GivePermissionBottomSheetConfig(
|
||||
data class GivePermissionBottomSheetConfig(
|
||||
val data: SwapPermissionState.ReadyForRequest,
|
||||
val onCancel: () -> Unit,
|
||||
) : TangemBottomSheetConfigContent
|
||||
|
|
@ -87,7 +87,6 @@ internal class StateBuilder(
|
|||
onMaxAmountSelected = actions.onMaxAmountSelected,
|
||||
updateInProgress = true,
|
||||
onShowPermissionBottomSheet = actions.openPermissionBottomSheet,
|
||||
onCancelPermissionBottomSheet = actions.hidePermissionBottomSheet,
|
||||
providerState = ProviderState.Empty(),
|
||||
)
|
||||
}
|
||||
|
|
@ -394,10 +393,13 @@ internal class StateBuilder(
|
|||
}
|
||||
|
||||
fun updateApproveType(uiState: SwapStateHolder, approveType: ApproveType): SwapStateHolder {
|
||||
return if (uiState.permissionState is SwapPermissionState.ReadyForRequest) {
|
||||
val config = uiState.bottomSheetConfig?.content as? GivePermissionBottomSheetConfig
|
||||
return if (config != null) {
|
||||
uiState.copy(
|
||||
permissionState = uiState.permissionState.copy(
|
||||
approveType = approveType,
|
||||
bottomSheetConfig = uiState.bottomSheetConfig.copy(
|
||||
content = config.copy(
|
||||
data = config.data.copy(approveType = approveType),
|
||||
),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.feature.swap.domain.models.ui.RequestApproveStateData
|
|||
import com.tangem.feature.swap.domain.models.ui.SwapState
|
||||
import com.tangem.feature.swap.domain.models.ui.TokensDataStateExpress
|
||||
import com.tangem.feature.swap.domain.models.ui.TxFee
|
||||
import com.tangem.feature.swap.models.ApproveType
|
||||
|
||||
data class SwapProcessDataState(
|
||||
// Initial network id
|
||||
|
|
@ -16,6 +17,7 @@ data class SwapProcessDataState(
|
|||
// Amount from input
|
||||
val amount: String? = null,
|
||||
val approveDataModel: RequestApproveStateData? = null,
|
||||
val approveType: ApproveType? = null,
|
||||
val swapDataModel: SwapDataModel? = null,
|
||||
val selectedFee: TxFee? = null, // todo
|
||||
val tokensDataState: TokensDataStateExpress? = null,
|
||||
|
|
|
|||
|
|
@ -22,10 +22,7 @@ import com.tangem.feature.swap.domain.models.domain.SwapDataModel
|
|||
import com.tangem.feature.swap.domain.models.domain.SwapProvider
|
||||
import com.tangem.feature.swap.domain.models.formatToUIRepresentation
|
||||
import com.tangem.feature.swap.domain.models.ui.*
|
||||
import com.tangem.feature.swap.models.SwapPermissionState
|
||||
import com.tangem.feature.swap.models.SwapStateHolder
|
||||
import com.tangem.feature.swap.models.UiActions
|
||||
import com.tangem.feature.swap.models.toDomainApproveType
|
||||
import com.tangem.feature.swap.models.*
|
||||
import com.tangem.feature.swap.presentation.SwapFragment
|
||||
import com.tangem.feature.swap.router.SwapNavScreen
|
||||
import com.tangem.feature.swap.router.SwapRouter
|
||||
|
|
@ -295,7 +292,7 @@ internal class SwapViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun updateLoadedQuotes(state: Map<SwapProvider, SwapState>): Pair<SwapProvider, SwapState> {
|
||||
val selectedSwapProvider = dataState.selectedProvider ?: state.keys.first()
|
||||
val selectedSwapProvider = selectProvider(state)
|
||||
dataState = dataState.copy(
|
||||
selectedProvider = selectedSwapProvider,
|
||||
lastLoadedSwapStates = state,
|
||||
|
|
@ -303,6 +300,15 @@ internal class SwapViewModel @Inject constructor(
|
|||
return state.entries.first { it.key == selectedSwapProvider }.toPair()
|
||||
}
|
||||
|
||||
private fun selectProvider(state: Map<SwapProvider, SwapState>): SwapProvider {
|
||||
val currentSelected = dataState.selectedProvider
|
||||
return if (currentSelected != null && state.keys.contains(currentSelected)) {
|
||||
currentSelected
|
||||
} else {
|
||||
state.keys.first()
|
||||
}
|
||||
}
|
||||
|
||||
private fun fillLoadedDataState(
|
||||
state: SwapState.QuotesLoadedState,
|
||||
permissionState: PermissionDataState,
|
||||
|
|
@ -311,6 +317,7 @@ internal class SwapViewModel @Inject constructor(
|
|||
dataState = if (permissionState is PermissionDataState.PermissionReadyForRequest) {
|
||||
dataState.copy(
|
||||
approveDataModel = permissionState.requestApproveData,
|
||||
approveType = dataState.approveType ?: ApproveType.UNLIMITED,
|
||||
)
|
||||
} else {
|
||||
dataState.copy(
|
||||
|
|
@ -403,12 +410,15 @@ internal class SwapViewModel @Inject constructor(
|
|||
fromToken = requireNotNull(dataState.fromCryptoCurrency?.currency) {
|
||||
"dataState.fromCurrency might not be null"
|
||||
},
|
||||
approveType = requireNotNull(uiState.permissionState as? SwapPermissionState.ReadyForRequest) {
|
||||
"uiState.permissionState should be SwapPermissionState.ReadyForRequest"
|
||||
}.approveType.toDomainApproveType(),
|
||||
approveType = requireNotNull(dataState.approveType) {
|
||||
"uiState.permissionState should not be null"
|
||||
}.toDomainApproveType(),
|
||||
txFee = requireNotNull(dataState.selectedFee) {
|
||||
"dataState.selectedFee shouldn't be null"
|
||||
},
|
||||
spenderAddress = requireNotNull(dataState.approveDataModel?.spenderAddress) {
|
||||
"dataState.approveDataModel.spenderAddress shouldn't be null"
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -432,14 +442,35 @@ internal class SwapViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun onSearchEntered(searchQuery: String) {
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
runCatching(dispatchers.io) {
|
||||
swapInteractor.searchTokens(dataState.networkId, searchQuery)
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val tokenDataState = dataState.tokensDataState ?: return@launch
|
||||
val group = if (isOrderReversed) {
|
||||
tokenDataState.fromGroup
|
||||
} else {
|
||||
tokenDataState.toGroup
|
||||
}
|
||||
.onSuccess {
|
||||
// updateTokensState(it)
|
||||
}
|
||||
.onFailure { }
|
||||
val available = group.available.filter {
|
||||
it.currencyStatus.currency.name.contains(searchQuery, ignoreCase = true)
|
||||
}
|
||||
val unavailable = group.unavailable.filter {
|
||||
it.currencyStatus.currency.name.contains(searchQuery, ignoreCase = true)
|
||||
}
|
||||
val filteredTokenDataState = if (isOrderReversed) {
|
||||
tokenDataState.copy(
|
||||
fromGroup = tokenDataState.fromGroup.copy(
|
||||
available = available,
|
||||
unavailable = unavailable,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
tokenDataState.copy(
|
||||
toGroup = tokenDataState.toGroup.copy(
|
||||
available = available,
|
||||
unavailable = unavailable,
|
||||
),
|
||||
)
|
||||
}
|
||||
updateTokensState(filteredTokenDataState)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -480,6 +511,7 @@ internal class SwapViewModel @Inject constructor(
|
|||
toProvidersList = findSwapProviders(fromToken, toToken),
|
||||
)
|
||||
swapRouter.openScreen(SwapNavScreen.Main)
|
||||
updateTokensState(tokens)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -600,15 +632,16 @@ internal class SwapViewModel @Inject constructor(
|
|||
openPermissionBottomSheet = {
|
||||
singleTaskScheduler.cancelTask()
|
||||
analyticsEventHandler.send(SwapEvents.ButtonGivePermissionClicked)
|
||||
uiState = stateBuilder.showPermissionBottomSheet(uiState) { stateBuilder.dismissBottomSheet(uiState) }
|
||||
},
|
||||
hidePermissionBottomSheet = {
|
||||
startLoadingQuotesFromLastState()
|
||||
analyticsEventHandler.send(SwapEvents.ButtonPermissionCancelClicked)
|
||||
uiState = stateBuilder.showPermissionBottomSheet(uiState) {
|
||||
startLoadingQuotesFromLastState()
|
||||
analyticsEventHandler.send(SwapEvents.ButtonPermissionCancelClicked)
|
||||
stateBuilder.dismissBottomSheet(uiState)
|
||||
}
|
||||
},
|
||||
onAmountSelected = { onAmountSelected(it) },
|
||||
onChangeApproveType = { approveType ->
|
||||
uiState = stateBuilder.updateApproveType(uiState, approveType)
|
||||
dataState = dataState.copy(approveType = approveType)
|
||||
},
|
||||
onClickFee = {
|
||||
val selectedFee = dataState.selectedFee?.feeType ?: FeeType.NORMAL
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue