From 978d7c1da466749124a22eb7c06cb02e937dc976 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 3 Mar 2026 11:21:00 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../swap/DefaultSwapTransactionRepository.kt | 9 +- .../com/tangem/data/swap/di/SwapDataModule.kt | 3 - .../feed/components/FeedEntryChildFactory.kt | 3 - .../DefaultMarketsTokenDetailsComponent.kt | 3 - .../detailed/MarketsTokenDetailsContent.kt | 7 +- .../components/TokenMarketDetailsBody.kt | 11 +- .../features/send/v2/send/model/SendModel.kt | 126 ++------- .../send/v2/sendnft/model/NFTSendModel.kt | 72 ++---- .../destination/model/SendDestinationModel.kt | 58 +---- .../sendviaswap/model/SendWithSwapModel.kt | 91 +------ .../swap/DefaultSwapTransactionRepository.kt | 9 +- .../tangem/feature/swap/di/SwapDataModule.kt | 3 - .../DefaultInitialToCurrencyResolver.kt | 27 +- .../swap/domain/InitialToCurrencyResolver.kt | 12 +- .../feature/swap/domain/SwapInteractor.kt | 8 +- .../feature/swap/domain/SwapInteractorImpl.kt | 111 +------- .../swap/converters/TokensDataConverter.kt | 155 +++++------- .../swap/converters/TokensDataConverterV2.kt | 80 ------ .../tangem/feature/swap/model/SwapModel.kt | 239 ++++++------------ .../tangem/feature/swap/ui/StateBuilder.kt | 30 +-- 20 files changed, 202 insertions(+), 855 deletions(-) delete mode 100644 features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverterV2.kt diff --git a/data/swap/src/main/java/com/tangem/data/swap/DefaultSwapTransactionRepository.kt b/data/swap/src/main/java/com/tangem/data/swap/DefaultSwapTransactionRepository.kt index 3734069fb2..37c6ab2dfb 100644 --- a/data/swap/src/main/java/com/tangem/data/swap/DefaultSwapTransactionRepository.kt +++ b/data/swap/src/main/java/com/tangem/data/swap/DefaultSwapTransactionRepository.kt @@ -15,7 +15,6 @@ import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.utils.getObjectList import com.tangem.datasource.local.preferences.utils.getObjectListSync import com.tangem.datasource.local.preferences.utils.getObjectMap -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.supplier.MultiAccountListSupplier import com.tangem.domain.models.account.Account import com.tangem.domain.models.account.AccountId @@ -30,7 +29,6 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.addOrReplace import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn internal class DefaultSwapTransactionRepository( @@ -39,7 +37,6 @@ internal class DefaultSwapTransactionRepository( private val networkFactory: NetworkFactory, private val dispatchers: CoroutineDispatcherProvider, private val multiAccountListSupplier: MultiAccountListSupplier, - private val accountsFeatureToggles: AccountsFeatureToggles, ) : SwapTransactionRepository { private val listConverter by lazy(LazyThreadSafetyMode.NONE) { @@ -122,11 +119,7 @@ internal class DefaultSwapTransactionRepository( flow2 = appPreferencesStore.getObjectMap( key = PreferencesKeys.SWAP_TRANSACTIONS_STATUSES_KEY, ), - flow3 = if (accountsFeatureToggles.isFeatureEnabled) { - multiAccountListSupplier() - } else { - flowOf(emptyList()) - }, + flow3 = multiAccountListSupplier(), ) { savedTransactions, txStatuses, multiAccountList -> val currencyTxs = savedTransactions ?.filter { swapTxList -> diff --git a/data/swap/src/main/java/com/tangem/data/swap/di/SwapDataModule.kt b/data/swap/src/main/java/com/tangem/data/swap/di/SwapDataModule.kt index fd3fadb12b..6fee629eea 100644 --- a/data/swap/src/main/java/com/tangem/data/swap/di/SwapDataModule.kt +++ b/data/swap/src/main/java/com/tangem/data/swap/di/SwapDataModule.kt @@ -12,7 +12,6 @@ import com.tangem.datasource.api.express.models.response.ExpressErrorResponse import com.tangem.datasource.crypto.DataSignatureVerifier import com.tangem.datasource.di.NetworkMoshi import com.tangem.datasource.local.preferences.AppPreferencesStore -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.supplier.MultiAccountListSupplier import com.tangem.domain.express.ExpressRepository import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher @@ -71,7 +70,6 @@ internal object SwapDataModule { responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory, networkFactory: NetworkFactory, multiAccountListSupplier: MultiAccountListSupplier, - accountsFeatureToggles: AccountsFeatureToggles, dispatchers: CoroutineDispatcherProvider, ): SwapTransactionRepository { return DefaultSwapTransactionRepository( @@ -79,7 +77,6 @@ internal object SwapDataModule { responseCryptoCurrenciesFactory = responseCryptoCurrenciesFactory, networkFactory = networkFactory, multiAccountListSupplier = multiAccountListSupplier, - accountsFeatureToggles = accountsFeatureToggles, dispatchers = dispatchers, ) } diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/FeedEntryChildFactory.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/FeedEntryChildFactory.kt index 02b1c82ab7..31b71bb3ea 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/FeedEntryChildFactory.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/FeedEntryChildFactory.kt @@ -6,7 +6,6 @@ import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.navigation.Route import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.features.feed.components.earn.DefaultEarnComponent import com.tangem.features.feed.components.feed.DefaultFeedComponent import com.tangem.features.feed.components.market.details.DefaultMarketsTokenDetailsComponent @@ -20,7 +19,6 @@ import javax.inject.Inject internal class FeedEntryChildFactory @Inject constructor( private val analyticsEventHandler: AnalyticsEventHandler, - private val accountsFeatureToggles: AccountsFeatureToggles, private val portfolioComponentFactory: MarketsPortfolioComponent.Factory, private val addToPortfolioPreselectedDataComponent: AddToPortfolioPreselectedDataComponent.Factory, ) { @@ -66,7 +64,6 @@ internal class FeedEntryChildFactory @Inject constructor( appComponentContext = appComponentContext, params = child.params, analyticsEventHandler = analyticsEventHandler, - accountsFeatureToggles = accountsFeatureToggles, portfolioComponentFactory = portfolioComponentFactory, ) } diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/DefaultMarketsTokenDetailsComponent.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/DefaultMarketsTokenDetailsComponent.kt index c3fc430041..d43ace2233 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/DefaultMarketsTokenDetailsComponent.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/components/market/details/DefaultMarketsTokenDetailsComponent.kt @@ -15,7 +15,6 @@ import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent import com.tangem.core.ui.res.LocalMainBottomSheetColor -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.markets.TokenMarketParams import com.tangem.domain.models.currency.CryptoCurrency @@ -33,7 +32,6 @@ internal class DefaultMarketsTokenDetailsComponent( appComponentContext: AppComponentContext, val params: Params, analyticsEventHandler: AnalyticsEventHandler, - private val accountsFeatureToggles: AccountsFeatureToggles, portfolioComponentFactory: MarketsPortfolioComponent.Factory, ) : ComposableModularBottomSheetContentComponent, AppComponentContext by appComponentContext { @@ -117,7 +115,6 @@ internal class DefaultMarketsTokenDetailsComponent( modifier = modifier, backgroundColor = LocalMainBottomSheetColor.current.value, state = state, - isAccountEnabled = accountsFeatureToggles.isFeatureEnabled, portfolioBlock = portfolioComponent?.let { component -> { blockModifier -> component.Content(blockModifier) diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/MarketsTokenDetailsContent.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/MarketsTokenDetailsContent.kt index 77c6da0b24..67cc815484 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/MarketsTokenDetailsContent.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/MarketsTokenDetailsContent.kt @@ -42,7 +42,6 @@ import com.tangem.core.ui.res.TangemThemePreview import com.tangem.domain.markets.PriceChangeInterval import com.tangem.features.feed.impl.R import com.tangem.features.feed.ui.market.detailed.components.* -import com.tangem.core.ui.R as CoreR import com.tangem.features.feed.ui.market.detailed.preview.MarketsTokenDetailsPreview import com.tangem.features.feed.ui.market.detailed.state.ExchangesBottomSheetContent import com.tangem.features.feed.ui.market.detailed.state.InfoBottomSheetContent @@ -50,13 +49,13 @@ import com.tangem.features.feed.ui.market.detailed.state.MarketsTokenDetailsUM import com.tangem.features.feed.ui.market.detailed.state.SecurityScoreBottomSheetContent import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.flow.distinctUntilChanged +import com.tangem.core.ui.R as CoreR @Suppress("LongParameterList") @Composable internal fun MarketsTokenDetailsContent( state: MarketsTokenDetailsUM, backgroundColor: Color, - isAccountEnabled: Boolean, modifier: Modifier = Modifier, portfolioBlock: @Composable ((Modifier) -> Unit)?, ) { @@ -65,7 +64,6 @@ internal fun MarketsTokenDetailsContent( backgroundColor = backgroundColor, state = state, portfolioBlock = portfolioBlock, - isAccountEnabled = isAccountEnabled, ) when (state.bottomSheetConfig.content) { @@ -80,7 +78,6 @@ internal fun MarketsTokenDetailsContent( private fun Content( state: MarketsTokenDetailsUM, backgroundColor: Color, - isAccountEnabled: Boolean, modifier: Modifier = Modifier, portfolioBlock: @Composable ((Modifier) -> Unit)?, ) { @@ -134,7 +131,6 @@ private fun Content( tokenMarketDetailsBody( state = state.body, - isAccountEnabled = isAccountEnabled, portfolioBlock = portfolioBlock, relatedNews = state.relatedNews, ) @@ -322,7 +318,6 @@ private fun MarketsTokenDetailsContent_Preview( state = params, backgroundColor = TangemTheme.colors.background.tertiary, portfolioBlock = {}, - isAccountEnabled = true, ) } } diff --git a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/TokenMarketDetailsBody.kt b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/TokenMarketDetailsBody.kt index 01d5c21f9d..a0457c58ec 100644 --- a/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/TokenMarketDetailsBody.kt +++ b/features/feed/impl/src/main/kotlin/com/tangem/features/feed/ui/market/detailed/components/TokenMarketDetailsBody.kt @@ -20,10 +20,9 @@ import com.tangem.features.feed.ui.feed.state.NewsSliderConfig import com.tangem.features.feed.ui.market.detailed.state.MarketsTokenDetailsUM import com.tangem.features.feed.ui.market.detailed.state.MarketsTokenDetailsUM.RelatedNews -@Suppress("CanBeNonNullable") // TODO will be removed after [REDACTED_JIRA] +@Suppress("CanBeNonNullable") internal fun LazyListScope.tokenMarketDetailsBody( state: MarketsTokenDetailsUM.Body, - isAccountEnabled: Boolean, portfolioBlock: @Composable ((Modifier) -> Unit)?, relatedNews: RelatedNews, ) { @@ -39,9 +38,7 @@ internal fun LazyListScope.tokenMarketDetailsBody( } } - if (isAccountEnabled) { - aboutCoinHeader() - } + aboutCoinHeader() loadingInfoBlocks() } @@ -60,9 +57,7 @@ internal fun LazyListScope.tokenMarketDetailsBody( relatedNews(relatedNews) } - if (isAccountEnabled) { - aboutCoinHeader() - } + aboutCoinHeader() infoBlocksList(state.infoBlocks) } diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/model/SendModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/model/SendModel.kt index c8eeee19df..e9d194d455 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/model/SendModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/model/SendModel.kt @@ -5,7 +5,6 @@ import arrow.core.Either import arrow.core.getOrElse import arrow.core.left import com.tangem.blockchain.common.TransactionData -import com.tangem.blockchain.common.transaction.Fee import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.common.ui.amountScreen.models.AmountState import com.tangem.common.ui.navigationButtons.NavigationUM @@ -16,29 +15,23 @@ import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router import com.tangem.core.ui.utils.parseBigDecimal import com.tangem.core.ui.utils.parseBigDecimalOrNull -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase -import com.tangem.domain.card.common.util.cardTypesResolver import com.tangem.domain.feedback.GetWalletMetaInfoUseCase import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.BlockchainErrorInfo import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.models.account.Account -import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.models.wallet.isMultiCurrency import com.tangem.domain.qrscanning.models.SourceType import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase -import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.transaction.models.TransactionFeeExtended import com.tangem.domain.transaction.usecase.CreateTransferTransactionUseCase @@ -55,7 +48,6 @@ import com.tangem.features.send.v2.api.entity.FeeSelectorUM import com.tangem.features.send.v2.api.entity.PredefinedValues import com.tangem.features.send.v2.api.subcomponents.destination.SendDestinationComponent import com.tangem.features.send.v2.api.subcomponents.destination.entity.DestinationUM -import com.tangem.features.send.v2.common.CommonSendRoute import com.tangem.features.send.v2.common.CommonSendRoute.* import com.tangem.features.send.v2.common.SendConfirmAlertFactory import com.tangem.features.send.v2.common.ui.state.ConfirmUM @@ -74,7 +66,6 @@ import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject import kotlin.properties.Delegates -import com.tangem.features.send.v2.api.entity.FeeSelectorUM as FeeSelectorUMRedesigned internal interface SendComponentCallback : SendAmountComponent.ModelCallback, @@ -90,7 +81,6 @@ internal class SendModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val router: Router, private val getUserWalletUseCase: GetUserWalletUseCase, - private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val listenToQrScanningUseCase: ListenToQrScanningUseCase, @@ -108,7 +98,6 @@ internal class SendModel @Inject constructor( private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase, private val sendAmountUpdateTrigger: SendAmountUpdateTrigger, private val analyticsEventHandler: AnalyticsEventHandler, - private val accountsFeatureToggles: AccountsFeatureToggles, ) : Model(), SendComponentCallback { private val params: SendComponent.Params = paramsContainer.require() @@ -254,7 +243,7 @@ internal class SendModel @Inject constructor( showAlertError() } - suspend fun prepareTransferTransaction(): Either { + private suspend fun prepareTransferTransaction(): Either { val predefinedValues = predefinedValues val cryptoCurrencyStatus = cryptoCurrencyStatusFlow.value return if (predefinedValues is PredefinedValues.Content.Deeplink) { @@ -360,34 +349,24 @@ internal class SendModel @Inject constructor( ifRight = { wallet -> userWallet = wallet - if (accountsFeatureToggles.isFeatureEnabled) { - getAccountCurrencyStatusUseCase( + getAccountCurrencyStatusUseCase( + userWalletId = params.userWalletId, + currency = cryptoCurrency, + ).onEach { (account, cryptoCurrencyStatus) -> + isAccountModeFlow.value = isAccountsModeEnabledUseCase.invokeSync() + accountFlow.value = account + + cryptoCurrencyStatusFlow.value = cryptoCurrencyStatus + feeCryptoCurrencyStatusFlow.value = getFeePaidCryptoCurrencyStatusSyncUseCase( userWalletId = params.userWalletId, - currency = cryptoCurrency, - ).onEach { (account, cryptoCurrencyStatus) -> - isAccountModeFlow.value = isAccountsModeEnabledUseCase.invokeSync() - accountFlow.value = account + cryptoCurrencyStatus = cryptoCurrencyStatus, + ).getOrNull() ?: cryptoCurrencyStatus - cryptoCurrencyStatusFlow.value = cryptoCurrencyStatus - feeCryptoCurrencyStatusFlow.value = getFeePaidCryptoCurrencyStatusSyncUseCase( - userWalletId = params.userWalletId, - cryptoCurrencyStatus = cryptoCurrencyStatus, - ).getOrNull() ?: cryptoCurrencyStatus - - if (params.amount != null) { - router.replaceAll(Confirm) - } - }.flowOn(dispatchers.default) - .launchIn(modelScope) - } else { - val isSingleWalletWithToken = wallet is UserWallet.Cold && - wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken() - val isMultiCurrency = wallet.isMultiCurrency - getCurrenciesStatusUpdates( - isSingleWalletWithToken = isSingleWalletWithToken, - isMultiCurrency = isMultiCurrency, - ) - } + if (params.amount != null) { + router.replaceAll(Confirm) + } + }.flowOn(dispatchers.default) + .launchIn(modelScope) }, ifLeft = { error -> Timber.w(error.toString()) @@ -409,77 +388,6 @@ internal class SendModel @Inject constructor( .saveIn(balanceHidingJobHolder) } - private fun getCurrenciesStatusUpdates(isSingleWalletWithToken: Boolean, isMultiCurrency: Boolean) { - getCurrencyStatus( - isSingleWalletWithToken = isSingleWalletWithToken, - isMultiCurrency = isMultiCurrency, - ).onEach { maybeCryptoCurrency -> - maybeCryptoCurrency.fold( - ifRight = { cryptoCurrencyStatus -> - cryptoCurrencyStatusFlow.value = cryptoCurrencyStatus - feeCryptoCurrencyStatusFlow.value = getFeeCurrencyStatus(cryptoCurrencyStatus, isMultiCurrency) - - if (params.amount != null) { - router.replaceAll(CommonSendRoute.Confirm) - } - }, - ifLeft = { - sendConfirmAlertFactory.getGenericErrorState( - onFailedTxEmailClick = { - onFailedTxEmailClick(it.toString()) - }, - popBack = router::pop, - ) - }, - ) - }.flowOn(dispatchers.default) - .launchIn(modelScope) - } - - private fun getCurrencyStatus( - isSingleWalletWithToken: Boolean, - isMultiCurrency: Boolean, - ): Flow> { - return when { - isSingleWalletWithToken -> getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( - userWalletId = params.userWalletId, - currencyId = cryptoCurrency.id, - isSingleWalletWithTokens = true, - ) - isMultiCurrency -> getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( - userWalletId = params.userWalletId, - currencyId = cryptoCurrency.id, - isSingleWalletWithTokens = false, - ) - else -> getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWalletId = params.userWalletId) - } - } - - fun getSelectedFeeToken(): CryptoCurrency { - val feeUMV2 = uiState.value.feeSelectorUM as? FeeSelectorUMRedesigned.Content - val feeExtended = feeUMV2?.feeExtraInfo?.transactionFeeExtended - val isFeeInTokenCurrency = feeExtended?.transactionFee?.normal is Fee.Ethereum.TokenCurrency - return if (isFeeInTokenCurrency) { - feeUMV2.feeExtraInfo.feeCryptoCurrencyStatus.currency - } else { - feeCryptoCurrencyStatusFlow.value.currency - } - } - - private suspend fun getFeeCurrencyStatus( - cryptoCurrencyStatus: CryptoCurrencyStatus, - isMultiCurrency: Boolean, - ): CryptoCurrencyStatus { - return if (isMultiCurrency) { - getFeePaidCryptoCurrencyStatusSyncUseCase( - userWalletId = params.userWalletId, - cryptoCurrencyStatus = cryptoCurrencyStatus, - ).getOrNull() ?: cryptoCurrencyStatus - } else { - cryptoCurrencyStatus - } - } - private fun subscribeOnQRScannerResult() { listenToQrScanningUseCase(SourceType.SEND) .getOrElse { emptyFlow() } diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt index 5128c82ff5..c7d65fec93 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt @@ -11,12 +11,10 @@ import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router import com.tangem.datasource.local.nft.converter.NFTSdkAssetConverter -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency -import com.tangem.domain.card.common.util.cardTypesResolver import com.tangem.domain.feedback.GetWalletMetaInfoUseCase import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.feedback.SendFeedbackEmailUseCase @@ -27,7 +25,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesProducer import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier import com.tangem.domain.transaction.error.GetFeeError @@ -66,7 +63,6 @@ internal class NFTSendModel @Inject constructor( private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val getUserWalletUseCase: GetUserWalletUseCase, private val multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier, - private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, private val createNFTTransferTransactionUseCase: CreateNFTTransferTransactionUseCase, private val getFeeUseCase: GetFeeUseCase, @@ -77,7 +73,6 @@ internal class NFTSendModel @Inject constructor( private val nftSendSuccessTrigger: NFTSendSuccessTrigger, private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase, private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase, - private val accountsFeatureToggles: AccountsFeatureToggles, ) : Model(), SendNFTComponentCallback, NFTSendSuccessComponent.ModelCallback { val params: NFTSendComponent.Params = paramsContainer.require() @@ -186,31 +181,24 @@ internal class NFTSendModel @Inject constructor( ?.firstOrNull { it is CryptoCurrency.Coin && it.network == nftAsset.network } ?: return@launch - if (accountsFeatureToggles.isFeatureEnabled) { - getAccountCurrencyStatusUseCase( - userWalletId, - cryptoCurrency, - ).onEach { (maybeAccount, cryptoStatus) -> - account = maybeAccount - isAccountsMode = isAccountsModeEnabledUseCase.invokeSync() + getAccountCurrencyStatusUseCase( + userWalletId, + cryptoCurrency, + ).onEach { (maybeAccount, cryptoStatus) -> + account = maybeAccount + isAccountsMode = isAccountsModeEnabledUseCase.invokeSync() - cryptoCurrencyStatus = cryptoStatus - feeCryptoCurrencyStatus = getFeePaidCryptoCurrencyStatusSyncUseCase( - userWalletId = userWalletId, - cryptoCurrencyStatus = cryptoStatus, - ).getOrNull() ?: cryptoStatus + cryptoCurrencyStatus = cryptoStatus + feeCryptoCurrencyStatus = getFeePaidCryptoCurrencyStatusSyncUseCase( + userWalletId = userWalletId, + cryptoCurrencyStatus = cryptoStatus, + ).getOrNull() ?: cryptoStatus - if (uiState.value.destinationUM is DestinationUM.Empty) { - router.replaceAll(Destination(isEditMode = false)) - } - }.flowOn(dispatchers.default) - .launchIn(modelScope) - } else { - getCurrenciesStatusUpdates( - isSingleWalletWithToken = wallet is UserWallet.Cold && - wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(), - ) - } + if (uiState.value.destinationUM is DestinationUM.Empty) { + router.replaceAll(Destination(isEditMode = false)) + } + }.flowOn(dispatchers.default) + .launchIn(modelScope) }, ifLeft = { alertFactory.getGenericErrorState(::onFailedTxEmailClick) @@ -246,34 +234,6 @@ internal class NFTSendModel @Inject constructor( } } - private fun getCurrenciesStatusUpdates(isSingleWalletWithToken: Boolean) { - getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( - userWalletId = userWalletId, - currencyId = cryptoCurrency.id, - isSingleWalletWithTokens = isSingleWalletWithToken, - ).onEach { maybeCryptoCurrency -> - maybeCryptoCurrency.fold( - ifRight = { cryptoStatus -> - cryptoCurrencyStatus = cryptoStatus - feeCryptoCurrencyStatus = getFeePaidCryptoCurrencyStatusSyncUseCase( - userWalletId = userWalletId, - cryptoCurrencyStatus = cryptoStatus, - ).getOrNull() ?: cryptoStatus - - if (uiState.value.destinationUM is DestinationUM.Empty) { - router.replaceAll(Destination(isEditMode = false)) - } - }, - ifLeft = { - alertFactory.getGenericErrorState( - onFailedTxEmailClick = { onFailedTxEmailClick(it.toString()) }, - popBack = { router.pop() }, - ) - }, - ) - }.launchIn(modelScope) - } - private fun initialState(): NFTSendUM = NFTSendUM( destinationUM = DestinationUM.Empty(), feeSelectorUM = FeeSelectorUM.Loading, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt index 96690cb647..e2c9a282c5 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/destination/model/SendDestinationModel.kt @@ -11,18 +11,14 @@ import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router import com.tangem.core.ui.extensions.resourceReference -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.status.supplier.MultiAccountStatusListSupplier import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase import com.tangem.domain.models.account.filterCryptoPortfolio import com.tangem.domain.models.network.CryptoCurrencyAddress -import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.isLocked -import com.tangem.domain.models.wallet.isMultiCurrency import com.tangem.domain.qrscanning.models.SourceType import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase -import com.tangem.domain.tokens.GetCryptoCurrencyUseCase import com.tangem.domain.tokens.GetNetworkAddressesUseCase import com.tangem.domain.transaction.usecase.IsSelfSendAvailableUseCase import com.tangem.domain.transaction.usecase.ValidateWalletAddressUseCase @@ -63,7 +59,6 @@ internal class SendDestinationModel @Inject constructor( private val validateWalletAddressUseCase: ValidateWalletAddressUseCase, private val validateWalletMemoUseCase: ValidateWalletMemoUseCase, private val getWalletsUseCase: GetWalletsUseCase, - private val getCryptoCurrencyUseCase: GetCryptoCurrencyUseCase, private val getNetworkAddressesUseCase: GetNetworkAddressesUseCase, private val getFixedTxHistoryItemsUseCase: GetFixedTxHistoryItemsUseCase, private val isSelfSendAvailableUseCase: IsSelfSendAvailableUseCase, @@ -71,7 +66,6 @@ internal class SendDestinationModel @Inject constructor( private val parseQrCodeUseCase: ParseQrCodeUseCase, private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase, private val analyticsEventHandler: AnalyticsEventHandler, - private val accountsFeatureToggles: AccountsFeatureToggles, private val multiAccountStatusListSupplier: MultiAccountStatusListSupplier, ) : Model(), SendDestinationClickIntents { private val params: SendDestinationComponentParams = paramsContainer.require() @@ -191,15 +185,7 @@ internal class SendDestinationModel @Inject constructor( private fun getWalletsAndRecent() { combine( - flow = if (accountsFeatureToggles.isFeatureEnabled) { - getAddedAddresses() - } else { - getWalletsUseCase().conflate().map { - waitForDelay(RECENT_LOAD_DELAY) { - it.toAvailableWallets() - } - } - }, + flow = getAddedAddresses(), flow2 = getFixedTxHistoryItemsUseCase( userWalletId = userWalletId, currency = cryptoCurrency, @@ -226,48 +212,6 @@ internal class SendDestinationModel @Inject constructor( }.flowOn(dispatchers.default).launchIn(modelScope) } - private suspend fun List.toAvailableWallets(): List { - return coroutineScope { - val cryptoCurrencyNetwork = cryptoCurrency.network - - return@coroutineScope filterNot { it.isLocked } - .map { wallet -> - async { - val addresses = if (!wallet.isMultiCurrency) { - getCryptoCurrencyUseCase(wallet.walletId).getOrNull()?.let { cryptoCurrency -> - if (cryptoCurrency.network.rawId == cryptoCurrencyNetwork.rawId) { - getNetworkAddressesUseCase.invokeSync( - userWalletId = wallet.walletId, - networkRawId = cryptoCurrency.network.id.rawId, - ) - } else { - null - } - } - } else { - getNetworkAddressesUseCase.invokeSync( - userWalletId = wallet.walletId, - networkRawId = cryptoCurrencyNetwork.id.rawId, - ) - } - wallet to addresses - } - }.awaitAll() - .asSequence() - .mapNotNull { (wallet, addresses) -> - addresses?.map { (cryptoCurrency, address) -> - DestinationWalletUM( - name = wallet.name, - address = address, - cryptoCurrency = cryptoCurrency, - userWalletId = wallet.walletId, - ) - } - }.flatten() - .toList() - } - } - private fun getAddedAddresses(): Flow> { return combine( flow = getWalletsUseCase().conflate(), diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/model/SendWithSwapModel.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/model/SendWithSwapModel.kt index 31b4ba8651..dc868296e8 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/model/SendWithSwapModel.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/model/SendWithSwapModel.kt @@ -1,29 +1,23 @@ package com.tangem.features.swap.v2.impl.sendviaswap.model -import arrow.core.Either import arrow.core.getOrElse import com.tangem.common.ui.navigationButtons.NavigationUM import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase -import com.tangem.domain.card.common.util.cardTypesResolver import com.tangem.domain.express.models.ExpressError import com.tangem.domain.models.account.Account import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.models.wallet.isMultiCurrency import com.tangem.domain.swap.models.SwapDirection import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase -import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase -import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents import com.tangem.features.send.v2.api.entity.FeeSelectorUM @@ -49,7 +43,6 @@ import kotlin.properties.Delegates internal class SendWithSwapModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val router: Router, - private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, private val getUserWalletUseCase: GetUserWalletUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, @@ -57,7 +50,6 @@ internal class SendWithSwapModel @Inject constructor( private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase, private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase, private val swapAlertFactory: SwapAlertFactory, - private val accountsFeatureToggles: AccountsFeatureToggles, paramsContainer: ParamsContainer, ) : Model(), SwapAmountComponent.ModelCallback, @@ -202,79 +194,20 @@ internal class SendWithSwapModel @Inject constructor( } private fun getPrimaryCurrencyStatusUpdates(cryptoCurrency: CryptoCurrency) { - val wallet = userWallet - val isMultiCurrency = wallet.isMultiCurrency - val isSingleWalletWithToken = wallet is UserWallet.Cold && - wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken() + getAccountCurrencyStatusUseCase( + userWalletId = params.userWalletId, + currency = cryptoCurrency, + ).onEach { (account, cryptoCurrencyStatus) -> + accountFlow.value = account + isAccountModeFlow.value = isAccountsModeEnabledUseCase.invokeSync() - if (accountsFeatureToggles.isFeatureEnabled) { - getAccountCurrencyStatusUseCase( + primaryCryptoCurrencyStatusFlow.value = cryptoCurrencyStatus + primaryFeePaidCurrencyStatusFlow.value = getFeePaidCryptoCurrencyStatusSyncUseCase( userWalletId = params.userWalletId, - currency = cryptoCurrency, - ).onEach { (account, cryptoCurrencyStatus) -> - accountFlow.value = account - isAccountModeFlow.value = isAccountsModeEnabledUseCase.invokeSync() - - primaryCryptoCurrencyStatusFlow.value = cryptoCurrencyStatus - primaryFeePaidCurrencyStatusFlow.value = getFeePaidCryptoCurrencyStatusSyncUseCase( - userWalletId = params.userWalletId, - cryptoCurrencyStatus = cryptoCurrencyStatus, - ).getOrNull() ?: cryptoCurrencyStatus - }.flowOn(dispatchers.default) - .launchIn(modelScope) - } else { - getCurrencyStatus( - cryptoCurrency = cryptoCurrency, - isSingleWalletWithToken = isSingleWalletWithToken, - isMultiCurrency = isMultiCurrency, - ).onEach { maybeCryptoCurrency -> - maybeCryptoCurrency.fold( - ifRight = { cryptoCurrencyStatus -> - primaryCryptoCurrencyStatusFlow.value = cryptoCurrencyStatus - primaryFeePaidCurrencyStatusFlow.value = getFeePaidCryptoCurrencyStatusSyncUseCase( - userWalletId = params.userWalletId, - cryptoCurrencyStatus = cryptoCurrencyStatus, - ).getOrNull() ?: cryptoCurrencyStatus - }, - ifLeft = { error -> - swapAlertFactory.getGenericErrorState( - expressError = ExpressError.UnknownError, - onFailedTxEmailClick = { - modelScope.launch { - swapAlertFactory.onFailedTxEmailClick( - userWallet = userWallet, - cryptoCurrency = params.currency, - errorMessage = error.toString(), - ) - } - }, - popBack = ::onBackClick, - ) - }, - ) - }.flowOn(dispatchers.default) - .launchIn(modelScope) - } - } - - private fun getCurrencyStatus( - cryptoCurrency: CryptoCurrency, - isSingleWalletWithToken: Boolean, - isMultiCurrency: Boolean, - ): Flow> { - return when { - isSingleWalletWithToken -> getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( - userWalletId = params.userWalletId, - currencyId = cryptoCurrency.id, - isSingleWalletWithTokens = true, - ) - isMultiCurrency -> getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( - userWalletId = params.userWalletId, - currencyId = cryptoCurrency.id, - isSingleWalletWithTokens = false, - ) - else -> getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWalletId = params.userWalletId) - } + cryptoCurrencyStatus = cryptoCurrencyStatus, + ).getOrNull() ?: cryptoCurrencyStatus + }.flowOn(dispatchers.default) + .launchIn(modelScope) } private fun subscribeOnBalanceHidden() { diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapTransactionRepository.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapTransactionRepository.kt index a04749322a..1d102e458e 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapTransactionRepository.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapTransactionRepository.kt @@ -8,7 +8,6 @@ import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.utils.getObjectList import com.tangem.datasource.local.preferences.utils.getObjectListSync import com.tangem.datasource.local.preferences.utils.getObjectMap -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.producer.SingleAccountListProducer import com.tangem.domain.account.supplier.SingleAccountListSupplier import com.tangem.domain.models.account.Account @@ -23,14 +22,12 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.extensions.addOrReplace import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn internal class DefaultSwapTransactionRepository( private val appPreferencesStore: AppPreferencesStore, private val dispatchers: CoroutineDispatcherProvider, private val singleAccountListSupplier: SingleAccountListSupplier, - private val accountsFeatureToggles: AccountsFeatureToggles, responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory, networkFactory: NetworkFactory, ) : SwapTransactionRepository { @@ -110,11 +107,7 @@ internal class DefaultSwapTransactionRepository( flow2 = appPreferencesStore.getObjectMap( key = PreferencesKeys.SWAP_TRANSACTIONS_STATUSES_KEY, ), - flow3 = if (accountsFeatureToggles.isFeatureEnabled) { - singleAccountListSupplier(SingleAccountListProducer.Params(userWallet.walletId)) - } else { - flowOf(null) - }, + flow3 = singleAccountListSupplier(SingleAccountListProducer.Params(userWallet.walletId)), ) { savedTransactions, txStatuses, accountList -> val currencyToTxs = savedTransactions?.filter { savedTx -> diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt index 669ba6fcd4..6057e6344e 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/di/SwapDataModule.kt @@ -8,7 +8,6 @@ import com.tangem.datasource.api.express.models.response.ExpressErrorResponse import com.tangem.datasource.crypto.DataSignatureVerifier import com.tangem.datasource.di.NetworkMoshi import com.tangem.datasource.local.preferences.AppPreferencesStore -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.supplier.SingleAccountListSupplier import com.tangem.domain.exchange.RampStateManager import com.tangem.domain.walletmanager.WalletManagersFacade @@ -59,7 +58,6 @@ internal class SwapDataModule { responseCryptoCurrenciesFactory: ResponseCryptoCurrenciesFactory, networkFactory: NetworkFactory, singleAccountListSupplier: SingleAccountListSupplier, - accountsFeatureToggles: AccountsFeatureToggles, dispatcherProvider: CoroutineDispatcherProvider, ): SwapTransactionRepository { return DefaultSwapTransactionRepository( @@ -67,7 +65,6 @@ internal class SwapDataModule { responseCryptoCurrenciesFactory = responseCryptoCurrenciesFactory, networkFactory = networkFactory, singleAccountListSupplier = singleAccountListSupplier, - accountsFeatureToggles = accountsFeatureToggles, dispatchers = dispatcherProvider, ) } 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 a9764ab530..e8d4a35b72 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 @@ -1,13 +1,11 @@ package com.tangem.feature.swap.domain import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.feature.swap.domain.models.ui.AccountSwapCurrency import com.tangem.feature.swap.domain.models.ui.TokensDataStateExpress import com.tangem.feature.swap.domain.models.ui.getGroupWithReverse import com.tangem.utils.extensions.orZero -import java.math.BigDecimal internal class DefaultInitialToCurrencyResolver( private val swapTransactionRepository: SwapTransactionRepository, @@ -18,22 +16,6 @@ internal class DefaultInitialToCurrencyResolver( initialCryptoCurrency: CryptoCurrency, state: TokensDataStateExpress, isReverseFromTo: Boolean, - ): CryptoCurrencyStatus? { - val id = swapTransactionRepository.getLastSwappedCryptoCurrencyId(userWallet.walletId) ?: return null - - return if (id != initialCryptoCurrency.id.value) { - val group = state.getGroupWithReverse(isReverseFromTo) - group.available.find { it.currencyStatus.currency.id.value == id }?.currencyStatus - } else { - null - } - } - - override suspend fun tryGetFromCacheV2( - userWallet: UserWallet, - initialCryptoCurrency: CryptoCurrency, - state: TokensDataStateExpress, - isReverseFromTo: Boolean, ): AccountSwapCurrency? { val id = swapTransactionRepository.getLastSwappedCryptoCurrencyId(userWallet.walletId) ?: return null @@ -48,14 +30,7 @@ internal class DefaultInitialToCurrencyResolver( } } - override fun tryGetWithMaxAmount(state: TokensDataStateExpress, isReverseFromTo: Boolean): CryptoCurrencyStatus? { - val group = state.getGroupWithReverse(isReverseFromTo) - return group.available.maxByOrNull { - it.currencyStatus.value.fiatAmount ?: BigDecimal.ZERO - }?.currencyStatus - } - - override fun tryGetWithMaxAmountV2(state: TokensDataStateExpress, isReverseFromTo: Boolean): AccountSwapCurrency? { + override fun tryGetWithMaxAmount(state: TokensDataStateExpress, isReverseFromTo: Boolean): AccountSwapCurrency? { val group = state.getGroupWithReverse(isReverseFromTo) return group.accountCurrencyList.firstNotNullOfOrNull { (_, currencyList) -> currencyList.maxByOrNull { swapAccountCurrency -> 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 7759a61e98..da6436ee57 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 @@ -1,7 +1,6 @@ package com.tangem.feature.swap.domain import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.feature.swap.domain.models.ui.AccountSwapCurrency import com.tangem.feature.swap.domain.models.ui.TokensDataStateExpress @@ -13,16 +12,7 @@ interface InitialToCurrencyResolver { initialCryptoCurrency: CryptoCurrency, state: TokensDataStateExpress, isReverseFromTo: Boolean, - ): CryptoCurrencyStatus? - - fun tryGetWithMaxAmount(state: TokensDataStateExpress, isReverseFromTo: Boolean): CryptoCurrencyStatus? - - suspend fun tryGetFromCacheV2( - userWallet: UserWallet, - initialCryptoCurrency: CryptoCurrency, - state: TokensDataStateExpress, - isReverseFromTo: Boolean, ): AccountSwapCurrency? - fun tryGetWithMaxAmountV2(state: TokensDataStateExpress, isReverseFromTo: Boolean): AccountSwapCurrency? + fun tryGetWithMaxAmount(state: TokensDataStateExpress, isReverseFromTo: Boolean): AccountSwapCurrency? } \ 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 c1193cdb4c..98165323aa 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 @@ -105,12 +105,6 @@ interface SwapInteractor { */ fun getTokenBalance(token: CryptoCurrencyStatus): SwapAmount - suspend fun getInitialCurrencyToSwap( - initialCryptoCurrency: CryptoCurrency, - state: TokensDataStateExpress, - isReverseFromTo: Boolean, - ): CryptoCurrencyStatus? - /** * Returns initial currency to swap as AccountSwapCurrency * @@ -118,7 +112,7 @@ interface SwapInteractor { * @param state current tokens data state * @param isReverseFromTo flag indicating the direction of the swap */ - suspend fun getInitialCurrencyToSwapV2( + suspend fun getInitialCurrencyToSwap( initialCryptoCurrency: CryptoCurrency, state: TokensDataStateExpress, isReverseFromTo: Boolean, 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 c3793db861..1856211b21 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 @@ -19,7 +19,6 @@ import com.tangem.blockchainsdk.utils.toBlockchain import com.tangem.blockchainsdk.utils.toNetworkId import com.tangem.core.ui.format.bigdecimal.fiat import com.tangem.core.ui.format.bigdecimal.format -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase @@ -75,7 +74,6 @@ import java.math.RoundingMode internal class SwapInteractorImpl @AssistedInject constructor( private val repository: SwapRepository, private val allowPermissionsHandler: AllowPermissionsHandler, - private val getMultiCryptoCurrencyStatusUseCase: GetMultiCryptoCurrencyStatusUseCase, private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase, private val sendTransactionUseCase: SendTransactionUseCase, private val createTransactionUseCase: CreateTransactionUseCase, @@ -106,7 +104,6 @@ internal class SwapInteractorImpl @AssistedInject constructor( private val rampStateManager: RampStateManager, private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier, private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase, - private val accountsFeatureToggles: AccountsFeatureToggles, private val walletManagersFacade: WalletManagersFacade, @Assisted private val userWalletId: UserWalletId, ) : SwapInteractor { @@ -123,58 +120,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( } override suspend fun getTokensDataState(currency: CryptoCurrency): TokensDataStateExpress { - return if (accountsFeatureToggles.isFeatureEnabled) { - getAccountCurrencyTokensDataState(currency) - } else { - getCurrencyTokensDataState(currency) - } - } - - private suspend fun getCurrencyTokensDataState(currency: CryptoCurrency): TokensDataStateExpress { - val walletCurrencyStatuses = getMultiCryptoCurrencyStatusUseCase - .invokeMultiWalletSync(userWalletId) - .getOrElse { emptyList() } - - val walletCurrencyStatusesExceptInitial = walletCurrencyStatuses - .filter { status -> - val isDifferentCurrency = status.currency.network.backendId != currency.network.backendId || - status.currency.getContractAddress() != currency.getContractAddress() - val hasValidStatus = - status.value is CryptoCurrencyStatus.Loaded || status.value is CryptoCurrencyStatus.NoAccount - val isNotCustomToken = !status.currency.isCustom - hasValidStatus && isDifferentCurrency && isNotCustomToken - } - - if (walletCurrencyStatusesExceptInitial.isEmpty()) { - return TokensDataStateExpress.EMPTY - } - - val pairsLeast = getPairs( - userWallet = userWallet, - initialCurrency = LeastTokenInfo( - contractAddress = (currency as? CryptoCurrency.Token)?.contractAddress ?: "0", - network = currency.network.backendId, - ), - currenciesList = walletCurrencyStatusesExceptInitial.map { it.currency }, - ) - - return TokensDataStateExpress( - fromGroup = getToCurrenciesGroup( - currency = currency, - leastPairs = pairsLeast.pairs, - cryptoCurrenciesList = walletCurrencyStatusesExceptInitial, - tokenInfoForFilter = { it.to }, - tokenInfoForAvailable = { it.from }, - ), - toGroup = getToCurrenciesGroup( - currency = currency, - leastPairs = pairsLeast.pairs, - cryptoCurrenciesList = walletCurrencyStatusesExceptInitial, - tokenInfoForFilter = { it.from }, - tokenInfoForAvailable = { it.to }, - ), - allProviders = pairsLeast.allProviders, - ) + return getAccountCurrencyTokensDataState(currency) } private suspend fun getAccountCurrencyTokensDataState(currency: CryptoCurrency): TokensDataStateExpress { @@ -212,14 +158,14 @@ internal class SwapInteractorImpl @AssistedInject constructor( ) return TokensDataStateExpress( - fromGroup = getToCurrenciesGroupV2( + fromGroup = getToCurrenciesGroup( currency = currency, leastPairs = pairsLeast.pairs, cryptoCurrenciesList = walletAccountCurrencyStatusesExceptInitial, tokenInfoForFilter = { it.to }, tokenInfoForAvailable = { it.from }, ), - toGroup = getToCurrenciesGroupV2( + toGroup = getToCurrenciesGroup( currency = currency, leastPairs = pairsLeast.pairs, cryptoCurrenciesList = walletAccountCurrencyStatusesExceptInitial, @@ -242,39 +188,6 @@ internal class SwapInteractorImpl @AssistedInject constructor( } private suspend fun getToCurrenciesGroup( - currency: CryptoCurrency, - leastPairs: List, - cryptoCurrenciesList: List, - tokenInfoForFilter: (SwapPairLeast) -> LeastTokenInfo, - tokenInfoForAvailable: (SwapPairLeast) -> LeastTokenInfo, - ): CurrenciesGroup { - val filteredPairs = leastPairs.filter { pair -> - tokenInfoForFilter(pair).contractAddress == currency.getContractAddress() && - tokenInfoForFilter(pair).network == currency.network.backendId - } - - val availableCryptoCurrencies = cryptoCurrenciesList.mapNotNull { cryptoCurrencyStatus -> - val providers = findProvidersForPair(cryptoCurrencyStatus, filteredPairs, tokenInfoForAvailable) - if (providers != null) { - CryptoCurrencySwapInfo(cryptoCurrencyStatus, providers) - } else { - null - } - } - - val unavailableCryptoCurrencies = cryptoCurrenciesList - availableCryptoCurrencies - .map { it.currencyStatus } - .toSet() - - return CurrenciesGroup( - available = availableCryptoCurrencies, - unavailable = unavailableCryptoCurrencies.map { CryptoCurrencySwapInfo(it, emptyList()) }, - accountCurrencyList = emptyList(), - isAfterSearch = false, - ) - } - - private suspend fun getToCurrenciesGroupV2( currency: CryptoCurrency, leastPairs: List, cryptoCurrenciesList: Map>, @@ -1323,7 +1236,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( initialCryptoCurrency: CryptoCurrency, state: TokensDataStateExpress, isReverseFromTo: Boolean, - ): CryptoCurrencyStatus? { + ): AccountSwapCurrency? { val group = state.getGroupWithReverse(isReverseFromTo) return initialToCurrencyResolver.tryGetFromCache( userWallet = userWallet, @@ -1332,22 +1245,6 @@ internal class SwapInteractorImpl @AssistedInject constructor( isReverseFromTo = isReverseFromTo, ) ?: initialToCurrencyResolver.tryGetWithMaxAmount(state = state, isReverseFromTo = isReverseFromTo) - ?: group.available.firstOrNull()?.currencyStatus - } - - override suspend fun getInitialCurrencyToSwapV2( - initialCryptoCurrency: CryptoCurrency, - state: TokensDataStateExpress, - isReverseFromTo: Boolean, - ): AccountSwapCurrency? { - val group = state.getGroupWithReverse(isReverseFromTo) - return initialToCurrencyResolver.tryGetFromCacheV2( - userWallet = userWallet, - initialCryptoCurrency = initialCryptoCurrency, - state = state, - isReverseFromTo = isReverseFromTo, - ) - ?: initialToCurrencyResolver.tryGetWithMaxAmountV2(state = state, isReverseFromTo = isReverseFromTo) ?: group.accountCurrencyList.firstNotNullOfOrNull { accountSwapAvailability -> accountSwapAvailability.currencyList.firstOrNull { accountSwapCurrency -> accountSwapCurrency.isAvailable diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt index 791af35a8c..d54ae4ecc1 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverter.kt @@ -1,113 +1,80 @@ package com.tangem.feature.swap.converters -import com.tangem.core.ui.components.currency.icon.CurrencyIconState -import com.tangem.core.ui.extensions.* -import com.tangem.core.ui.format.bigdecimal.crypto -import com.tangem.core.ui.format.bigdecimal.fiat -import com.tangem.core.ui.format.bigdecimal.format +import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM +import com.tangem.core.ui.extensions.resourceReference import com.tangem.domain.appcurrency.model.AppCurrency -import com.tangem.domain.models.currency.CryptoCurrency -import com.tangem.domain.models.currency.CryptoCurrencyStatus -import com.tangem.feature.swap.domain.models.domain.CryptoCurrencySwapInfo -import com.tangem.feature.swap.models.CurrenciesGroupWithFromCurrency +import com.tangem.feature.swap.domain.models.ui.CurrenciesGroup import com.tangem.feature.swap.models.SwapSelectTokenStateHolder -import com.tangem.feature.swap.models.TokenBalanceData +import com.tangem.feature.swap.models.SwapStateHolder import com.tangem.feature.swap.models.TokenListUMData -import com.tangem.feature.swap.models.TokenToSelectState import com.tangem.feature.swap.presentation.R import com.tangem.utils.Provider -import com.tangem.utils.converter.Converter +import com.tangem.utils.transformer.Transformer import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toImmutableList +import kotlinx.collections.immutable.plus +import kotlinx.collections.immutable.toPersistentList internal class TokensDataConverter( private val onSearchEntered: (String) -> Unit, private val onTokenSelected: (String) -> Unit, - private val isBalanceHiddenProvider: Provider, - private val appCurrencyProvider: Provider, -) : Converter { + private val tokensDataState: CurrenciesGroup, + private val isBalanceHidden: Boolean, + private val isAccountsMode: Boolean, + appCurrencyProvider: Provider, +) : Transformer { - override fun convert(value: CurrenciesGroupWithFromCurrency): SwapSelectTokenStateHolder { - val group = value.group - val availableTitle = TokenToSelectState.Title( - resourceReference(R.string.exchange_tokens_available_tokens_header), - ) - val allTokens = group.available + group.unavailable - return SwapSelectTokenStateHolder( - availableTokens = allTokens.map { tokenWithBalanceToTokenToSelect(it, true) } - .toMutableList() - .apply { - if (this.isNotEmpty()) { - this.add(0, availableTitle) + private val accountListItemConverter = AccountTokenItemConverter( + appCurrency = appCurrencyProvider(), + unavailableErrorText = resourceReference(R.string.tokens_list_unavailable_to_swap_source_header), + onItemClick = onTokenSelected, + ) + + override fun transform(prevState: SwapStateHolder): SwapStateHolder { + val accountList = tokensDataState.accountCurrencyList + val currentMarketsState = prevState.selectTokenState?.marketsState + return prevState.copy( + selectTokenState = SwapSelectTokenStateHolder( + availableTokens = persistentListOf(), + unavailableTokens = persistentListOf(), + tokensListData = if (isAccountsMode) { + val portfolioList = accountListItemConverter.convertList(accountList).toPersistentList() + val totalTokensCount = portfolioList.sumOf { it.tokens.size } + if (totalTokensCount > 0) { + TokenListUMData.AccountList( + tokensList = portfolioList, + totalTokensCount = totalTokensCount, + ) + } else { + TokenListUMData.EmptyList } - } - .toImmutableList(), - unavailableTokens = persistentListOf(), - tokensListData = TokenListUMData.EmptyList, - onSearchEntered = onSearchEntered, - onTokenSelected = onTokenSelected, - isBalanceHidden = isBalanceHiddenProvider(), - isAfterSearch = group.isAfterSearch, - ) - } + } else { + val tokensList = accountList.flatMap { (_, currencyList) -> + currencyList.asSequence().map { accountSwapCurrency -> + accountListItemConverter.createAvailableItemConverter() + .convert(accountSwapCurrency.cryptoCurrencyStatus) + }.map(TokensListItemUM::Token).toPersistentList() + }.toPersistentList() - private fun tokenWithBalanceToTokenToSelect( - cryptoCurrencySwapInfo: CryptoCurrencySwapInfo, - isAvailable: Boolean, - ): TokenToSelectState { - val cryptoCurrencyStatus = cryptoCurrencySwapInfo.currencyStatus - return TokenToSelectState.TokenToSelect( - id = cryptoCurrencyStatus.currency.id.value, - name = cryptoCurrencyStatus.currency.name, - symbol = cryptoCurrencyStatus.currency.symbol, - isAvailable = isAvailable, - tokenIcon = convertIcon(cryptoCurrencyStatus.currency, isAvailable), - addedTokenBalanceData = TokenBalanceData( - amount = formatCryptoAmount(cryptoCurrencyStatus), - amountEquivalent = formatFiatAmount(cryptoCurrencyStatus, appCurrencyProvider.invoke()), - isBalanceHidden = isBalanceHiddenProvider.invoke(), + if (tokensList.isNotEmpty()) { + TokenListUMData.TokenList( + tokensList = persistentListOf( + TokensListItemUM.GroupTitle( + id = "available_tokens_title", + text = resourceReference(R.string.exchange_tokens_available_tokens_header), + ), + ) + tokensList, + totalTokensCount = tokensList.size, + ) + } else { + TokenListUMData.EmptyList + } + }, + marketsState = currentMarketsState, + onSearchEntered = onSearchEntered, + onTokenSelected = onTokenSelected, + isBalanceHidden = isBalanceHidden, + isAfterSearch = tokensDataState.isAfterSearch, ), ) } - - private fun convertIcon(currency: CryptoCurrency, isAvailable: Boolean): CurrencyIconState { - return when (currency) { - is CryptoCurrency.Coin -> { - CurrencyIconState.CoinIcon( - url = currency.iconUrl, - fallbackResId = currency.networkIconResId, - isGrayscale = !isAvailable, - shouldShowCustomBadge = currency.isCustom, - ) - } - is CryptoCurrency.Token -> { - val isGrayscale = currency.network.isTestnet - val background = currency.tryGetBackgroundForTokenIcon(isGrayscale) - val tint = getTintForTokenIcon(background) - CurrencyIconState.TokenIcon( - url = currency.iconUrl, - isGrayscale = !isAvailable, - shouldShowCustomBadge = currency.isCustom, - topBadgeIconResId = currency.networkIconResId, - fallbackTint = tint, - fallbackBackground = background, - ) - } - } - } - - private fun formatCryptoAmount(cryptoCurrencyStatus: CryptoCurrencyStatus): String { - return cryptoCurrencyStatus.value.amount.format { - crypto(cryptoCurrencyStatus.currency) - } - } - - private fun formatFiatAmount(cryptoCurrencyStatus: CryptoCurrencyStatus, appCurrency: AppCurrency): String { - return cryptoCurrencyStatus.value.fiatAmount.format { - fiat( - fiatCurrencyCode = appCurrency.code, - fiatCurrencySymbol = appCurrency.symbol, - ) - } - } } \ No newline at end of file diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverterV2.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverterV2.kt deleted file mode 100644 index 1804474ea2..0000000000 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/converters/TokensDataConverterV2.kt +++ /dev/null @@ -1,80 +0,0 @@ -package com.tangem.feature.swap.converters - -import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.domain.appcurrency.model.AppCurrency -import com.tangem.feature.swap.domain.models.ui.CurrenciesGroup -import com.tangem.feature.swap.models.SwapSelectTokenStateHolder -import com.tangem.feature.swap.models.SwapStateHolder -import com.tangem.feature.swap.models.TokenListUMData -import com.tangem.feature.swap.presentation.R -import com.tangem.utils.Provider -import com.tangem.utils.transformer.Transformer -import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.plus -import kotlinx.collections.immutable.toPersistentList - -internal class TokensDataConverterV2( - private val onSearchEntered: (String) -> Unit, - private val onTokenSelected: (String) -> Unit, - private val tokensDataState: CurrenciesGroup, - private val isBalanceHidden: Boolean, - private val isAccountsMode: Boolean, - appCurrencyProvider: Provider, -) : Transformer { - - private val accountListItemConverter = AccountTokenItemConverter( - appCurrency = appCurrencyProvider(), - unavailableErrorText = resourceReference(R.string.tokens_list_unavailable_to_swap_source_header), - onItemClick = onTokenSelected, - ) - - override fun transform(prevState: SwapStateHolder): SwapStateHolder { - val accountList = tokensDataState.accountCurrencyList - val currentMarketsState = prevState.selectTokenState?.marketsState - return prevState.copy( - selectTokenState = SwapSelectTokenStateHolder( - availableTokens = persistentListOf(), - unavailableTokens = persistentListOf(), - tokensListData = if (isAccountsMode) { - val portfolioList = accountListItemConverter.convertList(accountList).toPersistentList() - val totalTokensCount = portfolioList.sumOf { it.tokens.size } - if (totalTokensCount > 0) { - TokenListUMData.AccountList( - tokensList = portfolioList, - totalTokensCount = totalTokensCount, - ) - } else { - TokenListUMData.EmptyList - } - } else { - val tokensList = accountList.flatMap { (_, currencyList) -> - currencyList.asSequence().map { accountSwapCurrency -> - accountListItemConverter.createAvailableItemConverter() - .convert(accountSwapCurrency.cryptoCurrencyStatus) - }.map(TokensListItemUM::Token).toPersistentList() - }.toPersistentList() - - if (tokensList.isNotEmpty()) { - TokenListUMData.TokenList( - tokensList = persistentListOf( - TokensListItemUM.GroupTitle( - id = "available_tokens_title", - text = resourceReference(R.string.exchange_tokens_available_tokens_header), - ), - ) + tokensList, - totalTokensCount = tokensList.size, - ) - } else { - TokenListUMData.EmptyList - } - }, - marketsState = currentMarketsState, - onSearchEntered = onSearchEntered, - onTokenSelected = onTokenSelected, - isBalanceHidden = isBalanceHidden, - isAfterSearch = tokensDataState.isAfterSearch, - ), - ) - } -} \ No newline at end of file diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt index b2ce189459..a0e992a13c 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt @@ -14,8 +14,6 @@ import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.common.routing.AppRouter import com.tangem.common.ui.bottomsheet.permission.state.ApproveType import com.tangem.common.ui.bottomsheet.permission.state.GiveTxPermissionState.InProgress.getApproveTypeOrNull -import com.tangem.features.approval.api.GiveApprovalComponent -import com.tangem.features.approval.api.GiveApprovalFeatureToggles import com.tangem.common.ui.markets.models.MarketsListItemUM import com.tangem.core.analytics.api.AnalyticsErrorHandler import com.tangem.core.analytics.api.AnalyticsEventHandler @@ -36,7 +34,6 @@ import com.tangem.core.ui.message.EventMessageAction import com.tangem.core.ui.utils.InputNumberFormatter import com.tangem.core.ui.utils.parseBigDecimal import com.tangem.datasource.local.appsflyer.AppsFlyerStore -import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles import com.tangem.domain.account.status.model.AccountCryptoCurrencyStatus import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase @@ -103,6 +100,8 @@ import com.tangem.feature.swap.router.SwapNavScreen import com.tangem.feature.swap.router.SwapRouter import com.tangem.feature.swap.ui.StateBuilder import com.tangem.feature.swap.utils.formatToUIRepresentation +import com.tangem.features.approval.api.GiveApprovalComponent +import com.tangem.features.approval.api.GiveApprovalFeatureToggles import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioComponent import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioManager import com.tangem.features.send.v2.api.entity.FeeSelectorUM @@ -114,8 +113,6 @@ import com.tangem.utils.Provider import com.tangem.utils.TangemBlogUrlBuilder.RESOURCE_TO_LEARN_ABOUT_APPROVING_IN_SWAP import com.tangem.utils.coroutines.* import com.tangem.utils.isNullOrZero -import kotlinx.coroutines.NonCancellable -import kotlinx.coroutines.delay import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import timber.log.Timber @@ -156,7 +153,6 @@ internal class SwapModel @Inject constructor( router: AppRouter, private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase, private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase, - private val accountsFeatureToggles: AccountsFeatureToggles, private val getTangemPayCurrencyStatusUseCase: GetTangemPayCurrencyStatusUseCase, private val tangemPayWithdrawUseCase: TangemPayWithdrawUseCase, private val iGaslessFeeSupportedForNetwork: IsGaslessFeeSupportedForNetwork, @@ -244,12 +240,12 @@ internal class SwapModel @Inject constructor( private var toAccountCurrencyStatus: AccountCryptoCurrencyStatus? = null /** - * If accountsFeatureToggles is off OR user came from Tangem Pay -> fromAccountCurrencyStatus == null - * If accountsFeatureToggles is on AND user didn't come from Tangem Pay -> fromAccountCurrencyStatus != null + * If user came from Tangem Pay -> fromAccountCurrencyStatus == null + * If user didn't come from Tangem Pay -> fromAccountCurrencyStatus != null * * Remove when accounts are integrated into Tangem Pay */ - private val canUseFromAccountCurrencyStatus = accountsFeatureToggles.isFeatureEnabled && tangemPayInput == null + private val canUseFromAccountCurrencyStatus = tangemPayInput == null private val isUserResolvableError: (SwapState) -> Boolean = { swapState -> swapState is SwapState.SwapError && @@ -514,25 +510,25 @@ internal class SwapModel @Inject constructor( }.onSuccess { state -> updateTokensState(state) - val (selectedCurrency, selectedAccount) = if (accountsFeatureToggles.isFeatureEnabled) { - val selectedAccountCurrency = toAccountCurrencyStatus ?: swapInteractor.getInitialCurrencyToSwapV2( - initialCryptoCurrency = initialCurrencyFrom, - state = state, - isReverseFromTo = isReverseFromTo, - )?.let { accountSwapCurrency -> - AccountCryptoCurrencyStatus( - account = accountSwapCurrency.account, - status = accountSwapCurrency.cryptoCurrencyStatus, + val (selectedCurrency, selectedAccount) = run { + var selectedAccountCurrency = toAccountCurrencyStatus + + if (selectedAccountCurrency == null) { + val amountSwapCurrency = swapInteractor.getInitialCurrencyToSwap( + initialCryptoCurrency = initialCurrencyFrom, + state = state, + isReverseFromTo = isReverseFromTo, ) + + if (amountSwapCurrency != null) { + selectedAccountCurrency = AccountCryptoCurrencyStatus( + account = amountSwapCurrency.account, + status = amountSwapCurrency.cryptoCurrencyStatus, + ) + } } + selectedAccountCurrency?.status to selectedAccountCurrency?.account - } else { - val selectedCurrency = initialToStatus ?: swapInteractor.getInitialCurrencyToSwap( - initialCryptoCurrency = initialCurrencyFrom, - state = state, - isReverseFromTo = isReverseFromTo, - ) - selectedCurrency to null } applyInitialTokenChoice( @@ -695,19 +691,11 @@ internal class SwapModel @Inject constructor( private fun updateTokensState(tokenDataState: TokensDataStateExpress) { val tokensDataState = if (isOrderReversed) tokenDataState.fromGroup else tokenDataState.toGroup - uiState = if (accountsFeatureToggles.isFeatureEnabled) { - stateBuilder.addTokensToStateV2( - uiState = uiState, - tokensDataState = tokensDataState, - isAccountsMode = isAccountsMode, - ) - } else { - stateBuilder.addTokensToState( - uiState = uiState, - tokensDataState = tokensDataState, - fromToken = dataState.fromCryptoCurrency?.currency ?: initialCurrencyFrom, - ) - } + uiState = stateBuilder.addTokensToStateV2( + uiState = uiState, + tokensDataState = tokensDataState, + isAccountsMode = isAccountsMode, + ) latestMarketsState?.let(::applyMarketsState) } @@ -1366,11 +1354,7 @@ internal class SwapModel @Inject constructor( fromToken = foundToken fromAccount = foundAccount toToken = initialFromStatus - toAccount = if (accountsFeatureToggles.isFeatureEnabled) { - fromAccountCurrencyStatus?.account - } else { - null - } + toAccount = fromAccountCurrencyStatus?.account val newToken = fromToken.currency as? CryptoCurrency.Coin if (newToken != null) { @@ -1384,11 +1368,7 @@ internal class SwapModel @Inject constructor( } } else { fromToken = initialFromStatus - fromAccount = if (accountsFeatureToggles.isFeatureEnabled) { - fromAccountCurrencyStatus?.account - } else { - null - } + fromAccount = fromAccountCurrencyStatus?.account toToken = foundToken toAccount = foundAccount @@ -1446,26 +1426,16 @@ internal class SwapModel @Inject constructor( tokens: TokensDataStateExpress, id: String, ): Pair { - return if (accountsFeatureToggles.isFeatureEnabled) { - val accountCryptoCurrencyStatus = if (isOrderReversed) { - tokens.fromGroup - } else { - tokens.toGroup - }.accountCurrencyList.firstNotNullOfOrNull { accountSwapAvailability -> - accountSwapAvailability.currencyList.firstOrNull { accountSwapCurrency -> - accountSwapCurrency.cryptoCurrencyStatus.currency.id.value == id - } - } - accountCryptoCurrencyStatus?.cryptoCurrencyStatus to accountCryptoCurrencyStatus?.account + val accountCryptoCurrencyStatus = if (isOrderReversed) { + tokens.fromGroup } else { - if (isOrderReversed) { - tokens.fromGroup - } else { - tokens.toGroup - }.available.firstOrNull { swapAvailability -> - swapAvailability.currencyStatus.currency.id.value == id - }?.currencyStatus to null + tokens.toGroup + }.accountCurrencyList.firstNotNullOfOrNull { accountSwapAvailability -> + accountSwapAvailability.currencyList.firstOrNull { accountSwapCurrency -> + accountSwapCurrency.cryptoCurrencyStatus.currency.id.value == id + } } + return accountCryptoCurrencyStatus?.cryptoCurrencyStatus to accountCryptoCurrencyStatus?.account } @Suppress("LongMethod", "CyclomaticComplexMethod") @@ -1476,79 +1446,44 @@ internal class SwapModel @Inject constructor( ) { Timber.d("Subscribe to ${coin.id} balance updates") - if (accountsFeatureToggles.isFeatureEnabled) { - getAccountCurrencyStatusUseCase( - userWalletId = userWalletId, - currency = coin, - ).distinctUntilChanged { old, new -> old.status.value.amount == new.status.value.amount } // Check only balance changes - .onEach { (account, currencyStatus) -> - Timber.d("${coin.id} balance is ${currencyStatus.value.amount ?: "null"}") + getAccountCurrencyStatusUseCase( + userWalletId = userWalletId, + currency = coin, + ).distinctUntilChanged { old, new -> old.status.value.amount == new.status.value.amount } // Check only balance changes + .onEach { (account, currencyStatus) -> + Timber.d("${coin.id} balance is ${currencyStatus.value.amount ?: "null"}") - if (isFromCurrency) { - dataState = dataState.copy( - feePaidCryptoCurrency = getFeePaidCryptoCurrencyStatusSyncUseCase( - userWalletId = userWalletId, - cryptoCurrencyStatus = currencyStatus, - ).getOrNull() ?: currencyStatus, - ) - } - - uiState = when { - isFromCurrency && currencyStatus.currency.id == dataState.fromCryptoCurrency?.currency?.id -> { - dataState = dataState.copy( - fromCryptoCurrency = currencyStatus, - fromAccount = account, - ) - stateBuilder.updateSendCurrencyBalance(uiState, currencyStatus) - } - !isFromCurrency && currencyStatus.currency.id == dataState.toCryptoCurrency?.currency?.id -> { - dataState = dataState.copy( - toCryptoCurrency = currencyStatus, - toAccount = account, - ) - stateBuilder.updateReceiveCurrencyBalance(uiState, currencyStatus) - } - else -> { - uiState - } - } - startLoadingQuotesFromLastState(isSilent = true) + if (isFromCurrency) { + dataState = dataState.copy( + feePaidCryptoCurrency = getFeePaidCryptoCurrencyStatusSyncUseCase( + userWalletId = userWalletId, + cryptoCurrencyStatus = currencyStatus, + ).getOrNull() ?: currencyStatus, + ) } - } else { - getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( - userWalletId = userWalletId, - currencyId = coin.id, - isSingleWalletWithTokens = false, - ).mapNotNull { either -> (either as? Either.Right)?.value } - .distinctUntilChanged { old, new -> old.value.amount == new.value.amount } // Check only balance changes - .onEach { status -> - Timber.d("${coin.id} balance is ${status.value.amount ?: "null"}") - if (isFromCurrency) { + uiState = when { + isFromCurrency && currencyStatus.currency.id == dataState.fromCryptoCurrency?.currency?.id -> { dataState = dataState.copy( - feePaidCryptoCurrency = getFeePaidCryptoCurrencyStatusSyncUseCase( - userWalletId = userWalletId, - cryptoCurrencyStatus = status, - ).getOrNull() ?: status, + fromCryptoCurrency = currencyStatus, + fromAccount = account, ) + stateBuilder.updateSendCurrencyBalance(uiState, currencyStatus) } - - uiState = when { - isFromCurrency && status.currency.id == dataState.fromCryptoCurrency?.currency?.id -> { - dataState = dataState.copy(fromCryptoCurrency = status) - stateBuilder.updateSendCurrencyBalance(uiState, status) - } - !isFromCurrency && status.currency.id == dataState.toCryptoCurrency?.currency?.id -> { - dataState = dataState.copy(toCryptoCurrency = status) - stateBuilder.updateReceiveCurrencyBalance(uiState, status) - } - else -> { - uiState - } + !isFromCurrency && currencyStatus.currency.id == dataState.toCryptoCurrency?.currency?.id -> { + dataState = dataState.copy( + toCryptoCurrency = currencyStatus, + toAccount = account, + ) + stateBuilder.updateReceiveCurrencyBalance(uiState, currencyStatus) + } + else -> { + uiState } - startLoadingQuotesFromLastState(isSilent = true) } - }.flowOn(dispatchers.main) + startLoadingQuotesFromLastState(isSilent = true) + } + .flowOn(dispatchers.main) .launchIn(modelScope) .saveIn(if (isFromCurrency) fromTokenBalanceJobHolder else toTokenBalanceJobHolder) } @@ -2027,18 +1962,12 @@ internal class SwapModel @Inject constructor( toToken.currency.id.value } - return if (accountsFeatureToggles.isFeatureEnabled) { - groupToFind.accountCurrencyList.firstNotNullOfOrNull { (_, currencyList) -> - currencyList.find { accountSwapCurrency -> - idToFind == accountSwapCurrency.cryptoCurrencyStatus.currency.id.value && - accountSwapCurrency.isAvailable - } - }?.providers - } else { - groupToFind.available.find { swapAvailability -> - idToFind == swapAvailability.currencyStatus.currency.id.value - }?.providers - } + return groupToFind.accountCurrencyList.firstNotNullOfOrNull { (_, currencyList) -> + currencyList.find { accountSwapCurrency -> + idToFind == accountSwapCurrency.cryptoCurrencyStatus.currency.id.value && + accountSwapCurrency.isAvailable + } + }?.providers ?.filterForTangemPayWithdrawal() .orEmpty() } @@ -2082,16 +2011,10 @@ internal class SwapModel @Inject constructor( val group = if (isReverseFromTo) state.fromGroup else state.toGroup val idToFind = selectedCurrency.currency.id.value - return if (accountsFeatureToggles.isFeatureEnabled) { - group.accountCurrencyList.any { (_, currencyList) -> - currencyList.any { accountSwapCurrency -> - idToFind == accountSwapCurrency.cryptoCurrencyStatus.currency.id.value && - accountSwapCurrency.isAvailable - } - } - } else { - group.available.any { swapAvailability -> - idToFind == swapAvailability.currencyStatus.currency.id.value + return group.accountCurrencyList.any { (_, currencyList) -> + currencyList.any { accountSwapCurrency -> + idToFind == accountSwapCurrency.cryptoCurrencyStatus.currency.id.value && + accountSwapCurrency.isAvailable } } } @@ -2128,14 +2051,10 @@ internal class SwapModel @Inject constructor( val chosen = if (isOrderReversed) from else to - return if (accountsFeatureToggles.isFeatureEnabled) { - currenciesGroup.accountCurrencyList.flatMap { accountSwapAvailability -> - accountSwapAvailability.currencyList.map { accountSwapCurrency -> - accountSwapCurrency.cryptoCurrencyStatus - } + return currenciesGroup.accountCurrencyList.flatMap { accountSwapAvailability -> + accountSwapAvailability.currencyList.map { accountSwapCurrency -> + accountSwapCurrency.cryptoCurrencyStatus } - } else { - currenciesGroup.available.map { swapAvailability -> swapAvailability.currencyStatus } }.map { currencyStatus -> currencyStatus.currency }.contains(chosen.currency) } diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt index 3b0249e51b..3f8b76b556 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt @@ -9,6 +9,7 @@ import com.tangem.common.ui.bottomsheet.permission.state.* import com.tangem.common.ui.notifications.NotificationUM import com.tangem.common.ui.swapStoriesScreen.SwapStoriesFactory import com.tangem.common.ui.userwallet.ext.walletInterationIcon +import com.tangem.core.ui.HoldToConfirmButtonFeatureToggles import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter import com.tangem.core.ui.extensions.* @@ -20,13 +21,11 @@ import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.account.Account import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus -import com.tangem.core.ui.HoldToConfirmButtonFeatureToggles import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.isHotWallet import com.tangem.domain.promo.models.StoryContent import com.tangem.domain.transaction.usecase.gasless.IsGaslessFeeSupportedForNetwork import com.tangem.feature.swap.converters.TokensDataConverter -import com.tangem.feature.swap.converters.TokensDataConverterV2 import com.tangem.feature.swap.domain.models.ExpressDataError import com.tangem.feature.swap.domain.models.SwapAmount import com.tangem.feature.swap.domain.models.domain.ExchangeProviderType @@ -62,7 +61,7 @@ internal class StateBuilder( private val appCurrencyProvider: Provider, private val isAccountsModeProvider: Provider, private val iGaslessFeeSupportedForNetwork: IsGaslessFeeSupportedForNetwork, - private val holdToConfirmButtonFeatureToggles: HoldToConfirmButtonFeatureToggles, + holdToConfirmButtonFeatureToggles: HoldToConfirmButtonFeatureToggles, ) { private val isHoldToConfirmEnabled: Boolean = @@ -70,13 +69,6 @@ internal class StateBuilder( private val iconStateConverter by lazy(::CryptoCurrencyToIconStateConverter) - private val tokensDataConverter = TokensDataConverter( - onSearchEntered = actions.onSearchEntered, - onTokenSelected = actions.onTokenSelected, - isBalanceHiddenProvider = isBalanceHiddenProvider, - appCurrencyProvider = appCurrencyProvider, - ) - private val notificationsFactory by lazy(LazyThreadSafetyMode.NONE) { SwapNotificationsFactory(actions, iGaslessFeeSupportedForNetwork) } @@ -677,28 +669,12 @@ internal class StateBuilder( ) } - fun addTokensToState( - uiState: SwapStateHolder, - fromToken: CryptoCurrency, - tokensDataState: CurrenciesGroup, - ): SwapStateHolder { - val currentMarketsState = uiState.selectTokenState?.marketsState - return uiState.copy( - selectTokenState = tokensDataConverter.convert( - value = CurrenciesGroupWithFromCurrency( - fromCurrency = fromToken, - group = tokensDataState, - ), - ).copy(marketsState = currentMarketsState), - ) - } - fun addTokensToStateV2( uiState: SwapStateHolder, tokensDataState: CurrenciesGroup, isAccountsMode: Boolean, ): SwapStateHolder { - return TokensDataConverterV2( + return TokensDataConverter( onSearchEntered = actions.onSearchEntered, onTokenSelected = actions.onTokenSelected, appCurrencyProvider = appCurrencyProvider,