Updated on 2026-08-14
This commit is contained in:
parent
dff5b1f27c
commit
978d7c1da4
20 changed files with 202 additions and 855 deletions
|
|
@ -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<SwapStatusDTO>(
|
||||
key = PreferencesKeys.SWAP_TRANSACTIONS_STATUSES_KEY,
|
||||
),
|
||||
flow3 = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
multiAccountListSupplier()
|
||||
} else {
|
||||
flowOf(emptyList())
|
||||
},
|
||||
flow3 = multiAccountListSupplier(),
|
||||
) { savedTransactions, txStatuses, multiAccountList ->
|
||||
val currencyTxs = savedTransactions
|
||||
?.filter { swapTxList ->
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Throwable, TransactionData> {
|
||||
private suspend fun prepareTransferTransaction(): Either<Throwable, TransactionData> {
|
||||
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<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
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() }
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<UserWallet>.toAvailableWallets(): List<DestinationWalletUM> {
|
||||
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<List<DestinationWalletUM>> {
|
||||
return combine(
|
||||
flow = getWalletsUseCase().conflate(),
|
||||
|
|
|
|||
|
|
@ -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<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
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() {
|
||||
|
|
|
|||
|
|
@ -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<ExchangeStatusModel>(
|
||||
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 ->
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ->
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<SwapPairLeast>,
|
||||
cryptoCurrenciesList: List<CryptoCurrencyStatus>,
|
||||
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<SwapPairLeast>,
|
||||
cryptoCurrenciesList: Map<Account, List<CryptoCurrencyStatus>>,
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<Boolean>,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
) : Converter<CurrenciesGroupWithFromCurrency, SwapSelectTokenStateHolder> {
|
||||
private val tokensDataState: CurrenciesGroup,
|
||||
private val isBalanceHidden: Boolean,
|
||||
private val isAccountsMode: Boolean,
|
||||
appCurrencyProvider: Provider<AppCurrency>,
|
||||
) : Transformer<SwapStateHolder> {
|
||||
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<AppCurrency>,
|
||||
) : Transformer<SwapStateHolder> {
|
||||
|
||||
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,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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<CryptoCurrencyStatus?, Account.CryptoPortfolio?> {
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<AppCurrency>,
|
||||
private val isAccountsModeProvider: Provider<Boolean>,
|
||||
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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue