diff --git a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json index d662c63280..1a45030b37 100644 --- a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json @@ -46,11 +46,11 @@ }, { "name": "GASLESS_APPROVAL_ENABLED", - "version": "undefined" + "version": "5.37" }, { "name": "TANGEM_PAY_ACCOUNTS_REFACTOR_ENABLED", - "version": "undefined" + "version": "5.37" }, { "name": "DYNAMIC_ADDRESSES_ENABLED", @@ -66,7 +66,7 @@ }, { "name": "NEW_PROMO_BANNERS_ENABLED", - "version": "undefined" + "version": "5.37" }, { "name": "VIRTUAL_ACCOUNTS_ENABLED", diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/AddToPortfolioPreselectedDataModel.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/AddToPortfolioPreselectedDataModel.kt index 60acc73b60..a28a4fd173 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/AddToPortfolioPreselectedDataModel.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/portfolio/add/impl/model/AddToPortfolioPreselectedDataModel.kt @@ -15,6 +15,7 @@ import com.tangem.domain.markets.GetTokenMarketCryptoCurrency import com.tangem.domain.markets.TokenMarketInfo import com.tangem.domain.markets.TokenMarketParams import com.tangem.domain.models.account.AccountStatus +import com.tangem.domain.models.account.filterCryptoPortfolio import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet @@ -27,9 +28,9 @@ import com.tangem.features.feed.components.market.details.portfolio.impl.analyti import com.tangem.features.feed.impl.R import com.tangem.features.feed.model.earn.analytics.EarnAnalyticsEvent import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.logging.TangemLogger import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.* -import com.tangem.utils.logging.TangemLogger import java.math.BigDecimal import javax.inject.Inject @@ -172,12 +173,11 @@ internal class AddToPortfolioPreselectedDataModel @Inject constructor( val availableToAddInWallets = portfolioData.balances.mapNotNull { (walletId, balance) -> val wallet = balance.userWallet - val accounts = balance.accountsBalance.accountStatuses + val accounts = balance.accountsBalance.accountStatuses.filterCryptoPortfolio() val availableToAddAccounts = accounts.mapNotNull { accountStatus -> val accountIndex = when (accountStatus) { is AccountStatus.CryptoPortfolio -> accountStatus.account.derivationIndex - is AccountStatus.Payment -> TODO("[REDACTED_JIRA]") } val cryptoCurrency = getTokenMarketCryptoCurrency( @@ -224,7 +224,7 @@ internal class AddToPortfolioPreselectedDataModel @Inject constructor( ): CryptoCurrency? { val accountIndex = when (val accountStatus = account.account) { is AccountStatus.CryptoPortfolio -> accountStatus.account.derivationIndex - is AccountStatus.Payment -> TODO("[REDACTED_JIRA]") + is AccountStatus.Payment -> return null } return getTokenMarketCryptoCurrency( userWalletId = userWallet.walletId, diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt index 752787e5bb..23ec462f60 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt @@ -200,6 +200,7 @@ internal class SwapAmountModel @Inject constructor( if (content.swapRateMode != SwapRateMode.FLOAT_ONLY) { ExpressRateType.Fixed } else { + onSelectTokenClick() return } } diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/converter/SwapAmountFieldConverter.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/converter/SwapAmountFieldConverter.kt index 810a528c2d..0684369b44 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/converter/SwapAmountFieldConverter.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/converter/SwapAmountFieldConverter.kt @@ -1,5 +1,6 @@ package com.tangem.features.swap.v2.impl.amount.model.converter +import com.tangem.common.ui.account.AccountTitleUM import com.tangem.common.ui.amountScreen.AmountScreenClickIntents import com.tangem.common.ui.amountScreen.converters.AmountAccountConverter import com.tangem.common.ui.amountScreen.converters.AmountStateConverter @@ -66,15 +67,20 @@ internal class SwapAmountFieldConverter( maxEnterAmount = maxEnterAmountConverter.convert(cryptoCurrencyStatus), iconStateConverter = iconStateConverter, isBalanceHidden = isBalanceHidden, - accountTitleUM = AmountAccountConverter( - isAccountsMode = isAccountsMode, - walletTitle = walletTitle, - prefixText = when { - swapAmountType.isEnteringField() -> resourceReference(R.string.common_from) - swapAmountType.isViewingField() -> resourceReference(R.string.common_to) - else -> TextReference.Companion.EMPTY - }, - ).convert(account), + accountTitleUM = if (swapAmountType.isViewingField()) { + AccountTitleUM.Text( + resourceReference(R.string.send_with_swap_recipient_get_amount, wrappedList("")), + ) + } else { + AmountAccountConverter( + isAccountsMode = isAccountsMode, + walletTitle = walletTitle, + prefixText = when { + swapAmountType.isEnteringField() -> resourceReference(R.string.common_from) + else -> TextReference.Companion.EMPTY + }, + ).convert(account) + }, ).convert( AmountParameters( title = walletTitle, 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 18dc50d0b6..a8f4b68486 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 @@ -72,7 +72,11 @@ import com.tangem.utils.logging.TangemLogger import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.supervisorScope import java.math.BigDecimal import java.math.BigInteger import java.math.RoundingMode @@ -346,63 +350,82 @@ internal class SwapInteractorImpl @AssistedInject constructor( """.trimIndent(), ) - return providers.map { provider -> - val amountDecimal = toBigDecimalOrNull(amountToSwap) - if (amountDecimal == null || amountDecimal.signum() == 0) { - return providers.associateWith { createEmptyAmountState() } - } - val amount = SwapAmount(amountDecimal, fromToken.currency.decimals) - val isBalanceWithoutFeeEnough = when (fromAccount) { - is Account.Payment -> true - else -> isBalanceEnough(fromToken, amount, null) - } - val networkId = fromToken.currency.network.backendId - when (provider.type) { - ExchangeProviderType.DEX, ExchangeProviderType.DEX_BRIDGE -> { - if (isSolana(networkId)) { - manageDexSolana( - networkId = networkId, + val amountDecimal = toBigDecimalOrNull(amountToSwap) + if (amountDecimal == null || amountDecimal.signum() == 0) { + return providers.associateWith { createEmptyAmountState() } + } + val amount = SwapAmount(amountDecimal, fromToken.currency.decimals) + val isBalanceWithoutFeeEnough = when (fromAccount) { + is Account.Payment -> true + else -> isBalanceEnough(fromToken, amount, null) + } + val networkId = fromToken.currency.network.backendId + + return supervisorScope { + providers.map { provider -> + async { + try { + when (provider.type) { + ExchangeProviderType.DEX, ExchangeProviderType.DEX_BRIDGE -> { + if (isSolana(networkId)) { + manageDexSolana( + networkId = networkId, + fromToken = fromToken, + fromAccount = fromAccount, + toToken = toToken, + toAccount = toAccount, + provider = provider, + txFeeSealedState = txFeeSealedState, + amount = amount, + isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough, + expressOperationType = ExpressOperationType.SWAP, + ) + } else { + manageDex( + networkId = networkId, + fromToken = fromToken, + fromAccount = fromAccount, + toToken = toToken, + toAccount = toAccount, + provider = provider, + txFeeSealedState = txFeeSealedState, + amount = amount, + isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough, + expressOperationType = ExpressOperationType.SWAP, + ) + } + } + ExchangeProviderType.CEX -> { + manageCex( + networkId = networkId, + fromToken = fromToken, + fromAccount = fromAccount, + toToken = toToken, + toAccount = toAccount, + provider = provider, + amount = amount, + reduceBalanceBy = reduceBalanceBy, + isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough, + txFeeSealedState = txFeeSealedState, + ) + } + } + } catch (e: Throwable) { + if (e is CancellationException) { + throw e + } + TangemLogger.e("Failed to find quote for provider: ${provider.providerId}", e) + provider to createSwapErrorWith( fromToken = fromToken, fromAccount = fromAccount, - toToken = toToken, - toAccount = toAccount, - provider = provider, - txFeeSealedState = txFeeSealedState, amount = amount, - isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough, - expressOperationType = ExpressOperationType.SWAP, - ) - } else { - manageDex( - networkId = networkId, - fromToken = fromToken, - fromAccount = fromAccount, - toToken = toToken, - toAccount = toAccount, - provider = provider, - txFeeSealedState = txFeeSealedState, - amount = amount, - isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough, - expressOperationType = ExpressOperationType.SWAP, + includeFeeInAmount = IncludeFeeInAmount.Excluded, + expressDataError = ExpressDataError.UnknownError, ) } } - ExchangeProviderType.CEX -> { - manageCex( - networkId = networkId, - fromToken = fromToken, - fromAccount = fromAccount, - toToken = toToken, - toAccount = toAccount, - provider = provider, - amount = amount, - reduceBalanceBy = reduceBalanceBy, - isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough, - txFeeSealedState = txFeeSealedState, - ) - } - } - }.toMap() + }.awaitAll().toMap() + } } @Suppress("LongMethod")