Updated on 2026-08-14
This commit is contained in:
parent
8c9452f46c
commit
71380aec64
18 changed files with 312 additions and 139 deletions
|
|
@ -14,6 +14,7 @@ dependencies {
|
||||||
implementation(projects.domain.models)
|
implementation(projects.domain.models)
|
||||||
implementation(projects.domain.nft.models)
|
implementation(projects.domain.nft.models)
|
||||||
implementation(projects.domain.wallets.models)
|
implementation(projects.domain.wallets.models)
|
||||||
|
implementation(projects.domain.account)
|
||||||
|
|
||||||
/* Project - Core */
|
/* Project - Core */
|
||||||
implementation(projects.core.decompose)
|
implementation(projects.core.decompose)
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ dependencies {
|
||||||
implementation(projects.domain.nft)
|
implementation(projects.domain.nft)
|
||||||
implementation(projects.domain.notifications)
|
implementation(projects.domain.notifications)
|
||||||
implementation(projects.domain.swap.models)
|
implementation(projects.domain.swap.models)
|
||||||
|
implementation(projects.domain.account)
|
||||||
|
implementation(projects.domain.account.status)
|
||||||
|
|
||||||
|
|
||||||
/** Compose libraries */
|
/** Compose libraries */
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,8 @@ internal class DefaultSendComponent @AssistedInject constructor(
|
||||||
userWalletId = params.userWalletId,
|
userWalletId = params.userWalletId,
|
||||||
cryptoCurrency = params.currency,
|
cryptoCurrency = params.currency,
|
||||||
cryptoCurrencyStatusFlow = model.cryptoCurrencyStatusFlow,
|
cryptoCurrencyStatusFlow = model.cryptoCurrencyStatusFlow,
|
||||||
|
accountFlow = model.accountFlow,
|
||||||
|
isAccountModeFlow = model.isAccountModeFlow,
|
||||||
callback = model,
|
callback = model,
|
||||||
predefinedValues = model.predefinedValues,
|
predefinedValues = model.predefinedValues,
|
||||||
analyticsSendSource = model.analyticsSendSource,
|
analyticsSendSource = model.analyticsSendSource,
|
||||||
|
|
@ -201,6 +203,8 @@ internal class DefaultSendComponent @AssistedInject constructor(
|
||||||
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
|
||||||
cryptoCurrencyStatusFlow = model.cryptoCurrencyStatusFlow,
|
cryptoCurrencyStatusFlow = model.cryptoCurrencyStatusFlow,
|
||||||
feeCryptoCurrencyStatusFlow = model.feeCryptoCurrencyStatusFlow,
|
feeCryptoCurrencyStatusFlow = model.feeCryptoCurrencyStatusFlow,
|
||||||
|
accountFlow = model.accountFlow,
|
||||||
|
isAccountModeFlow = model.isAccountModeFlow,
|
||||||
appCurrency = model.appCurrency,
|
appCurrency = model.appCurrency,
|
||||||
callback = model,
|
callback = model,
|
||||||
predefinedValues = model.predefinedValues,
|
predefinedValues = model.predefinedValues,
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import com.tangem.core.decompose.context.child
|
||||||
import com.tangem.core.decompose.model.getOrCreateModel
|
import com.tangem.core.decompose.model.getOrCreateModel
|
||||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
|
import com.tangem.domain.models.account.Account
|
||||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.domain.transaction.error.GetFeeError
|
import com.tangem.domain.transaction.error.GetFeeError
|
||||||
|
|
@ -73,6 +74,8 @@ internal class SendConfirmComponent(
|
||||||
cryptoCurrencyStatusFlow = params.cryptoCurrencyStatusFlow,
|
cryptoCurrencyStatusFlow = params.cryptoCurrencyStatusFlow,
|
||||||
isBalanceHidingFlow = params.isBalanceHidingFlow,
|
isBalanceHidingFlow = params.isBalanceHidingFlow,
|
||||||
analyticsSendSource = params.analyticsSendSource,
|
analyticsSendSource = params.analyticsSendSource,
|
||||||
|
accountFlow = params.accountFlow,
|
||||||
|
isAccountModeFlow = params.isAccountModeFlow,
|
||||||
),
|
),
|
||||||
onResult = model::onAmountResult,
|
onResult = model::onAmountResult,
|
||||||
onClick = model::showEditAmount,
|
onClick = model::showEditAmount,
|
||||||
|
|
@ -152,6 +155,8 @@ internal class SendConfirmComponent(
|
||||||
val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
|
val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||||
val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
||||||
val feeCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
val feeCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
||||||
|
val accountFlow: StateFlow<Account.CryptoPortfolio?>,
|
||||||
|
val isAccountModeFlow: StateFlow<Boolean>,
|
||||||
val appCurrency: AppCurrency,
|
val appCurrency: AppCurrency,
|
||||||
val callback: ModelCallback,
|
val callback: ModelCallback,
|
||||||
val currentRoute: Flow<CommonSendRoute>,
|
val currentRoute: Flow<CommonSendRoute>,
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,9 @@ import com.tangem.core.decompose.model.ParamsContainer
|
||||||
import com.tangem.core.decompose.navigation.Router
|
import com.tangem.core.decompose.navigation.Router
|
||||||
import com.tangem.core.ui.utils.parseBigDecimal
|
import com.tangem.core.ui.utils.parseBigDecimal
|
||||||
import com.tangem.core.ui.utils.parseBigDecimalOrNull
|
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.GetSelectedAppCurrencyUseCase
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||||
|
|
@ -23,6 +26,7 @@ import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
|
||||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||||
import com.tangem.domain.feedback.models.BlockchainErrorInfo
|
import com.tangem.domain.feedback.models.BlockchainErrorInfo
|
||||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||||
|
import com.tangem.domain.models.account.Account
|
||||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||||
|
|
@ -91,8 +95,11 @@ internal class SendModel @Inject constructor(
|
||||||
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||||
private val createTransferTransactionUseCase: CreateTransferTransactionUseCase,
|
private val createTransferTransactionUseCase: CreateTransferTransactionUseCase,
|
||||||
private val getFeeUseCase: GetFeeUseCase,
|
private val getFeeUseCase: GetFeeUseCase,
|
||||||
|
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||||
|
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||||
private val sendAmountUpdateTrigger: SendAmountUpdateTrigger,
|
private val sendAmountUpdateTrigger: SendAmountUpdateTrigger,
|
||||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||||
|
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||||
) : Model(), SendComponentCallback {
|
) : Model(), SendComponentCallback {
|
||||||
|
|
||||||
private val params: SendComponent.Params = paramsContainer.require()
|
private val params: SendComponent.Params = paramsContainer.require()
|
||||||
|
|
@ -115,21 +122,26 @@ internal class SendModel @Inject constructor(
|
||||||
|
|
||||||
val currentRoute = MutableStateFlow(initialRoute)
|
val currentRoute = MutableStateFlow(initialRoute)
|
||||||
|
|
||||||
private val _cryptoCurrencyStatusFlow = MutableStateFlow(
|
val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
|
||||||
CryptoCurrencyStatus(
|
field = MutableStateFlow(
|
||||||
params.currency,
|
CryptoCurrencyStatus(
|
||||||
value = CryptoCurrencyStatus.Loading,
|
params.currency,
|
||||||
),
|
value = CryptoCurrencyStatus.Loading,
|
||||||
)
|
),
|
||||||
val cryptoCurrencyStatusFlow = _cryptoCurrencyStatusFlow.asStateFlow()
|
)
|
||||||
|
|
||||||
private val _feeCryptoCurrencyStatusFlow = MutableStateFlow(
|
val feeCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
|
||||||
CryptoCurrencyStatus(
|
field = MutableStateFlow(
|
||||||
params.currency,
|
CryptoCurrencyStatus(
|
||||||
value = CryptoCurrencyStatus.Loading,
|
params.currency,
|
||||||
),
|
value = CryptoCurrencyStatus.Loading,
|
||||||
)
|
),
|
||||||
val feeCryptoCurrencyStatusFlow = _feeCryptoCurrencyStatusFlow.asStateFlow()
|
)
|
||||||
|
|
||||||
|
val accountFlow: StateFlow<Account.CryptoPortfolio?>
|
||||||
|
field = MutableStateFlow(null)
|
||||||
|
val isAccountModeFlow: StateFlow<Boolean>
|
||||||
|
field = MutableStateFlow(false)
|
||||||
|
|
||||||
var userWallet: UserWallet by Delegates.notNull()
|
var userWallet: UserWallet by Delegates.notNull()
|
||||||
var appCurrency: AppCurrency = AppCurrency.Default
|
var appCurrency: AppCurrency = AppCurrency.Default
|
||||||
|
|
@ -317,13 +329,34 @@ internal class SendModel @Inject constructor(
|
||||||
ifRight = { wallet ->
|
ifRight = { wallet ->
|
||||||
userWallet = wallet
|
userWallet = wallet
|
||||||
|
|
||||||
val isSingleWalletWithToken = wallet is UserWallet.Cold &&
|
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||||
wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
getAccountCurrencyStatusUseCase(
|
||||||
val isMultiCurrency = wallet.isMultiCurrency
|
userWalletId = params.userWalletId,
|
||||||
getCurrenciesStatusUpdates(
|
currency = cryptoCurrency,
|
||||||
isSingleWalletWithToken = isSingleWalletWithToken,
|
).onEach { (account, cryptoCurrencyStatus) ->
|
||||||
isMultiCurrency = isMultiCurrency,
|
cryptoCurrencyStatusFlow.value = cryptoCurrencyStatus
|
||||||
)
|
feeCryptoCurrencyStatusFlow.value = getFeePaidCryptoCurrencyStatusSyncUseCase(
|
||||||
|
userWalletId = params.userWalletId,
|
||||||
|
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||||
|
).getOrNull() ?: cryptoCurrencyStatus
|
||||||
|
|
||||||
|
isAccountModeFlow.value = isAccountsModeEnabledUseCase.invokeSync()
|
||||||
|
accountFlow.value = account
|
||||||
|
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ifLeft = {
|
ifLeft = {
|
||||||
Timber.w(it.toString())
|
Timber.w(it.toString())
|
||||||
|
|
@ -352,10 +385,12 @@ internal class SendModel @Inject constructor(
|
||||||
).onEach { maybeCryptoCurrency ->
|
).onEach { maybeCryptoCurrency ->
|
||||||
maybeCryptoCurrency.fold(
|
maybeCryptoCurrency.fold(
|
||||||
ifRight = { cryptoCurrencyStatus ->
|
ifRight = { cryptoCurrencyStatus ->
|
||||||
onDataLoaded(
|
cryptoCurrencyStatusFlow.value = cryptoCurrencyStatus
|
||||||
currencyStatus = cryptoCurrencyStatus,
|
feeCryptoCurrencyStatusFlow.value = getFeeCurrencyStatus(cryptoCurrencyStatus, isMultiCurrency)
|
||||||
feeCurrencyStatus = getFeeCurrencyStatus(cryptoCurrencyStatus, isMultiCurrency),
|
|
||||||
)
|
if (params.amount != null) {
|
||||||
|
router.replaceAll(CommonSendRoute.Confirm)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ifLeft = {
|
ifLeft = {
|
||||||
sendConfirmAlertFactory.getGenericErrorState(
|
sendConfirmAlertFactory.getGenericErrorState(
|
||||||
|
|
@ -366,7 +401,8 @@ internal class SendModel @Inject constructor(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}.launchIn(modelScope)
|
}.flowOn(dispatchers.default)
|
||||||
|
.launchIn(modelScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCurrencyStatus(
|
private fun getCurrencyStatus(
|
||||||
|
|
@ -402,15 +438,6 @@ internal class SendModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onDataLoaded(currencyStatus: CryptoCurrencyStatus, feeCurrencyStatus: CryptoCurrencyStatus) {
|
|
||||||
_cryptoCurrencyStatusFlow.value = currencyStatus
|
|
||||||
_feeCryptoCurrencyStatusFlow.value = feeCurrencyStatus
|
|
||||||
|
|
||||||
if (params.amount != null) {
|
|
||||||
router.replaceAll(CommonSendRoute.Confirm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun subscribeOnQRScannerResult() {
|
private fun subscribeOnQRScannerResult() {
|
||||||
listenToQrScanningUseCase(SourceType.SEND)
|
listenToQrScanningUseCase(SourceType.SEND)
|
||||||
.getOrElse { emptyFlow() }
|
.getOrElse { emptyFlow() }
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@ import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.model.ParamsContainer
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
import com.tangem.core.decompose.navigation.Router
|
import com.tangem.core.decompose.navigation.Router
|
||||||
import com.tangem.datasource.local.nft.converter.NFTSdkAssetConverter
|
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.GetSelectedAppCurrencyUseCase
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||||
|
|
@ -19,6 +22,7 @@ import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
|
||||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||||
import com.tangem.domain.feedback.models.BlockchainErrorInfo
|
import com.tangem.domain.feedback.models.BlockchainErrorInfo
|
||||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
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.CryptoCurrency
|
||||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
|
|
@ -71,6 +75,9 @@ internal class NFTSendModel @Inject constructor(
|
||||||
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
||||||
private val alertFactory: SendConfirmAlertFactory,
|
private val alertFactory: SendConfirmAlertFactory,
|
||||||
private val nftSendSuccessTrigger: NFTSendSuccessTrigger,
|
private val nftSendSuccessTrigger: NFTSendSuccessTrigger,
|
||||||
|
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||||
|
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||||
|
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||||
) : Model(), SendNFTComponentCallback, NFTSendSuccessComponent.ModelCallback {
|
) : Model(), SendNFTComponentCallback, NFTSendSuccessComponent.ModelCallback {
|
||||||
|
|
||||||
val params: NFTSendComponent.Params = paramsContainer.require()
|
val params: NFTSendComponent.Params = paramsContainer.require()
|
||||||
|
|
@ -94,6 +101,9 @@ internal class NFTSendModel @Inject constructor(
|
||||||
var feeCryptoCurrencyStatus: CryptoCurrencyStatus by Delegates.notNull()
|
var feeCryptoCurrencyStatus: CryptoCurrencyStatus by Delegates.notNull()
|
||||||
var appCurrency: AppCurrency = AppCurrency.Default
|
var appCurrency: AppCurrency = AppCurrency.Default
|
||||||
|
|
||||||
|
var account: Account.CryptoPortfolio? = null
|
||||||
|
var isAccountsMode: Boolean = false
|
||||||
|
|
||||||
init {
|
init {
|
||||||
subscribeOnCurrencyStatusUpdates()
|
subscribeOnCurrencyStatusUpdates()
|
||||||
initAppCurrency()
|
initAppCurrency()
|
||||||
|
|
@ -176,10 +186,31 @@ internal class NFTSendModel @Inject constructor(
|
||||||
?.firstOrNull { it is CryptoCurrency.Coin && it.network == nftAsset.network }
|
?.firstOrNull { it is CryptoCurrency.Coin && it.network == nftAsset.network }
|
||||||
?: return@launch
|
?: return@launch
|
||||||
|
|
||||||
getCurrenciesStatusUpdates(
|
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||||
isSingleWalletWithToken = wallet is UserWallet.Cold &&
|
getAccountCurrencyStatusUseCase(
|
||||||
wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(),
|
userWalletId,
|
||||||
)
|
cryptoCurrency,
|
||||||
|
).onEach { (maybeAccount, cryptoStatus) ->
|
||||||
|
account = maybeAccount
|
||||||
|
isAccountsMode = isAccountsModeEnabledUseCase.invokeSync()
|
||||||
|
|
||||||
|
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(),
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
ifLeft = {
|
ifLeft = {
|
||||||
alertFactory.getGenericErrorState(::onFailedTxEmailClick)
|
alertFactory.getGenericErrorState(::onFailedTxEmailClick)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.tangem.features.send.v2.subcomponents.amount
|
||||||
|
|
||||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
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.CryptoCurrency
|
||||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
|
|
@ -23,6 +24,8 @@ internal sealed class SendAmountComponentParams {
|
||||||
abstract val cryptoCurrency: CryptoCurrency
|
abstract val cryptoCurrency: CryptoCurrency
|
||||||
abstract val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
|
abstract val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
|
||||||
abstract val isBalanceHidingFlow: StateFlow<Boolean>
|
abstract val isBalanceHidingFlow: StateFlow<Boolean>
|
||||||
|
abstract val accountFlow: StateFlow<Account.CryptoPortfolio?>
|
||||||
|
abstract val isAccountModeFlow: StateFlow<Boolean>
|
||||||
|
|
||||||
data class AmountParams(
|
data class AmountParams(
|
||||||
override val state: AmountState,
|
override val state: AmountState,
|
||||||
|
|
@ -34,6 +37,8 @@ internal sealed class SendAmountComponentParams {
|
||||||
override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
||||||
override val isBalanceHidingFlow: StateFlow<Boolean>,
|
override val isBalanceHidingFlow: StateFlow<Boolean>,
|
||||||
override val analyticsSendSource: CommonSendAnalyticEvents.CommonSendSource,
|
override val analyticsSendSource: CommonSendAnalyticEvents.CommonSendSource,
|
||||||
|
override val accountFlow: StateFlow<Account.CryptoPortfolio?>,
|
||||||
|
override val isAccountModeFlow: StateFlow<Boolean>,
|
||||||
val callback: ModelCallback,
|
val callback: ModelCallback,
|
||||||
val currentRoute: StateFlow<CommonSendRoute>,
|
val currentRoute: StateFlow<CommonSendRoute>,
|
||||||
) : SendAmountComponentParams()
|
) : SendAmountComponentParams()
|
||||||
|
|
@ -48,6 +53,8 @@ internal sealed class SendAmountComponentParams {
|
||||||
override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
override val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
||||||
override val isBalanceHidingFlow: StateFlow<Boolean>,
|
override val isBalanceHidingFlow: StateFlow<Boolean>,
|
||||||
override val analyticsSendSource: CommonSendAnalyticEvents.CommonSendSource,
|
override val analyticsSendSource: CommonSendAnalyticEvents.CommonSendSource,
|
||||||
|
override val accountFlow: StateFlow<Account.CryptoPortfolio?>,
|
||||||
|
override val isAccountModeFlow: StateFlow<Boolean>,
|
||||||
val userWallet: UserWallet,
|
val userWallet: UserWallet,
|
||||||
val blockClickEnableFlow: StateFlow<Boolean>,
|
val blockClickEnableFlow: StateFlow<Boolean>,
|
||||||
) : SendAmountComponentParams()
|
) : SendAmountComponentParams()
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.exchange.RampStateManager
|
import com.tangem.domain.exchange.RampStateManager
|
||||||
|
import com.tangem.domain.models.account.Account
|
||||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||||
|
|
@ -118,42 +119,7 @@ internal class SendAmountModel @Inject constructor(
|
||||||
|
|
||||||
private fun subscribeOnBalanceHiddenUpdates() {
|
private fun subscribeOnBalanceHiddenUpdates() {
|
||||||
params.isBalanceHidingFlow.onEach { isBalanceHidden ->
|
params.isBalanceHidingFlow.onEach { isBalanceHidden ->
|
||||||
_uiState.update(
|
if (cryptoCurrencyStatus.value != CryptoCurrencyStatus.Loading) {
|
||||||
AmountBoundaryUpdateTransformer(
|
|
||||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
|
||||||
maxEnterAmount = maxAmountBoundary,
|
|
||||||
appCurrency = appCurrency,
|
|
||||||
isBalanceHidden = params.isBalanceHidingFlow.value,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}.launchIn(modelScope)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun subscribeOnCryptoCurrencyStatusFlow() {
|
|
||||||
params.cryptoCurrencyStatusFlow
|
|
||||||
.onEach { newCryptoCurrencyStatus ->
|
|
||||||
cryptoCurrencyStatus = newCryptoCurrencyStatus
|
|
||||||
maxAmountBoundary = MaxEnterAmountConverter().convert(cryptoCurrencyStatus)
|
|
||||||
initMinBoundary()
|
|
||||||
}
|
|
||||||
.launchIn(modelScope)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initMinBoundary() {
|
|
||||||
modelScope.launch {
|
|
||||||
minAmountBoundary = getMinimumTransactionAmountSyncUseCase(
|
|
||||||
userWalletId = params.userWalletId,
|
|
||||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
|
||||||
).getOrNull()?.let {
|
|
||||||
EnterAmountBoundary(
|
|
||||||
amount = it,
|
|
||||||
fiatRate = cryptoCurrencyStatus.value.fiatRate.orZero(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default }
|
|
||||||
|
|
||||||
if (uiState.value is AmountState.Data) {
|
|
||||||
_uiState.update(
|
_uiState.update(
|
||||||
AmountBoundaryUpdateTransformer(
|
AmountBoundaryUpdateTransformer(
|
||||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||||
|
|
@ -162,13 +128,61 @@ internal class SendAmountModel @Inject constructor(
|
||||||
isBalanceHidden = params.isBalanceHidingFlow.value,
|
isBalanceHidden = params.isBalanceHidingFlow.value,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
initialState()
|
|
||||||
}
|
}
|
||||||
|
}.launchIn(modelScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun subscribeOnCryptoCurrencyStatusFlow() {
|
||||||
|
combine(
|
||||||
|
flow = params.cryptoCurrencyStatusFlow.distinctUntilChanged { old, new ->
|
||||||
|
old.value.amount == new.value.amount
|
||||||
|
}, // Check only balance changes,
|
||||||
|
flow2 = params.accountFlow,
|
||||||
|
flow3 = params.isAccountModeFlow,
|
||||||
|
) { newCryptoCurrencyStatus, account, isAccountsMode ->
|
||||||
|
cryptoCurrencyStatus = newCryptoCurrencyStatus
|
||||||
|
maxAmountBoundary = MaxEnterAmountConverter().convert(cryptoCurrencyStatus)
|
||||||
|
initMinBoundary(cryptoCurrencyStatus, account, isAccountsMode)
|
||||||
|
}.flowOn(dispatchers.default)
|
||||||
|
.launchIn(modelScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun initMinBoundary(
|
||||||
|
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||||
|
account: Account.CryptoPortfolio?,
|
||||||
|
isAccountsMode: Boolean,
|
||||||
|
) {
|
||||||
|
minAmountBoundary = getMinimumTransactionAmountSyncUseCase(
|
||||||
|
userWalletId = params.userWalletId,
|
||||||
|
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||||
|
).getOrNull()?.let {
|
||||||
|
EnterAmountBoundary(
|
||||||
|
amount = it,
|
||||||
|
fiatRate = cryptoCurrencyStatus.value.fiatRate.orZero(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default }
|
||||||
|
|
||||||
|
if (uiState.value is AmountState.Data) {
|
||||||
|
_uiState.update(
|
||||||
|
AmountBoundaryUpdateTransformer(
|
||||||
|
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||||
|
maxEnterAmount = maxAmountBoundary,
|
||||||
|
appCurrency = appCurrency,
|
||||||
|
isBalanceHidden = params.isBalanceHidingFlow.value,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
initialState(cryptoCurrencyStatus, account, isAccountsMode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initialState() {
|
private fun initialState(
|
||||||
|
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||||
|
@Suppress("UnusedParameter") account: Account.CryptoPortfolio?,
|
||||||
|
@Suppress("UnusedParameter") isAccountsMode: Boolean,
|
||||||
|
) {
|
||||||
if (uiState.value is AmountState.Empty && userWallet != null) {
|
if (uiState.value is AmountState.Empty && userWallet != null) {
|
||||||
val isOnlyOneWallet = getWalletsUseCase.invokeSync().size == 1
|
val isOnlyOneWallet = getWalletsUseCase.invokeSync().size == 1
|
||||||
_uiState.update {
|
_uiState.update {
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ dependencies {
|
||||||
implementation(projects.domain.notifications)
|
implementation(projects.domain.notifications)
|
||||||
implementation(projects.domain.feedback.models)
|
implementation(projects.domain.feedback.models)
|
||||||
implementation(projects.domain.feedback)
|
implementation(projects.domain.feedback)
|
||||||
|
implementation(projects.domain.account)
|
||||||
|
implementation(projects.domain.account.status)
|
||||||
|
|
||||||
/** Compose */
|
/** Compose */
|
||||||
implementation(deps.compose.foundation)
|
implementation(deps.compose.foundation)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.tangem.features.swap.v2.impl.amount
|
||||||
|
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
import com.tangem.domain.express.models.ExpressProviderType
|
import com.tangem.domain.express.models.ExpressProviderType
|
||||||
|
import com.tangem.domain.models.account.Account
|
||||||
import com.tangem.domain.models.currency.CryptoCurrency
|
import com.tangem.domain.models.currency.CryptoCurrency
|
||||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
|
|
@ -23,6 +24,8 @@ internal sealed class SwapAmountComponentParams {
|
||||||
abstract val primaryCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
|
abstract val primaryCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
|
||||||
abstract val secondaryCryptoCurrency: CryptoCurrency?
|
abstract val secondaryCryptoCurrency: CryptoCurrency?
|
||||||
abstract val filterProviderTypes: List<ExpressProviderType>
|
abstract val filterProviderTypes: List<ExpressProviderType>
|
||||||
|
abstract val accountFlow: StateFlow<Account.CryptoPortfolio?>
|
||||||
|
abstract val isAccountModeFlow: StateFlow<Boolean>
|
||||||
|
|
||||||
data class AmountParams(
|
data class AmountParams(
|
||||||
override val amountUM: SwapAmountUM,
|
override val amountUM: SwapAmountUM,
|
||||||
|
|
@ -34,6 +37,8 @@ internal sealed class SwapAmountComponentParams {
|
||||||
override val secondaryCryptoCurrency: CryptoCurrency?,
|
override val secondaryCryptoCurrency: CryptoCurrency?,
|
||||||
override val filterProviderTypes: List<ExpressProviderType> = emptyList(),
|
override val filterProviderTypes: List<ExpressProviderType> = emptyList(),
|
||||||
override val analyticsSendSource: CommonSendAnalyticEvents.CommonSendSource,
|
override val analyticsSendSource: CommonSendAnalyticEvents.CommonSendSource,
|
||||||
|
override val accountFlow: StateFlow<Account.CryptoPortfolio?>,
|
||||||
|
override val isAccountModeFlow: StateFlow<Boolean>,
|
||||||
val title: TextReference,
|
val title: TextReference,
|
||||||
val callback: SwapAmountComponent.ModelCallback,
|
val callback: SwapAmountComponent.ModelCallback,
|
||||||
val currentRoute: Flow<SendWithSwapRoute>,
|
val currentRoute: Flow<SendWithSwapRoute>,
|
||||||
|
|
@ -49,6 +54,8 @@ internal sealed class SwapAmountComponentParams {
|
||||||
override val secondaryCryptoCurrency: CryptoCurrency?,
|
override val secondaryCryptoCurrency: CryptoCurrency?,
|
||||||
override val filterProviderTypes: List<ExpressProviderType> = emptyList(),
|
override val filterProviderTypes: List<ExpressProviderType> = emptyList(),
|
||||||
override val analyticsSendSource: CommonSendAnalyticEvents.CommonSendSource,
|
override val analyticsSendSource: CommonSendAnalyticEvents.CommonSendSource,
|
||||||
|
override val accountFlow: StateFlow<Account.CryptoPortfolio?>,
|
||||||
|
override val isAccountModeFlow: StateFlow<Boolean>,
|
||||||
val blockClickEnableFlow: StateFlow<Boolean>,
|
val blockClickEnableFlow: StateFlow<Boolean>,
|
||||||
) : SwapAmountComponentParams()
|
) : SwapAmountComponentParams()
|
||||||
}
|
}
|
||||||
|
|
@ -342,6 +342,8 @@ internal class SwapAmountModel @Inject constructor(
|
||||||
appCurrency = appCurrency,
|
appCurrency = appCurrency,
|
||||||
swapDirection = swapDirection,
|
swapDirection = swapDirection,
|
||||||
clickIntents = this,
|
clickIntents = this,
|
||||||
|
isAccountsMode = params.isAccountModeFlow.value,
|
||||||
|
account = params.accountFlow.value,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}.launchIn(modelScope)
|
}.launchIn(modelScope)
|
||||||
|
|
@ -367,6 +369,8 @@ internal class SwapAmountModel @Inject constructor(
|
||||||
isBalanceHidden = params.isBalanceHidingFlow.value,
|
isBalanceHidden = params.isBalanceHidingFlow.value,
|
||||||
showBestRateAnimation = showBestRateAnimation,
|
showBestRateAnimation = showBestRateAnimation,
|
||||||
isSingleWallet = isOnlyOneWallet,
|
isSingleWallet = isOnlyOneWallet,
|
||||||
|
isAccountsMode = params.isAccountModeFlow.value,
|
||||||
|
account = params.accountFlow.value,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -384,38 +388,45 @@ internal class SwapAmountModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun subscribeOnCryptoCurrencyStatusFlow() {
|
private fun subscribeOnCryptoCurrencyStatusFlow() {
|
||||||
params.primaryCryptoCurrencyStatusFlow
|
combine(
|
||||||
.distinctUntilChanged { old, new -> old.value.amount == new.value.amount } // Check only balance changes
|
flow = params.primaryCryptoCurrencyStatusFlow.distinctUntilChanged { old, new ->
|
||||||
.onEach { primaryCurrencyStatus ->
|
old.value.amount == new.value.amount
|
||||||
val secondaryStatus = (uiState.value as? SwapAmountUM.Content)?.secondaryCryptoCurrencyStatus
|
}, // Check only balance changes,
|
||||||
initCurrencies(
|
flow2 = params.accountFlow,
|
||||||
primaryStatus = primaryCurrencyStatus,
|
flow3 = params.isAccountModeFlow,
|
||||||
secondaryStatus = secondaryStatus,
|
) { primaryCurrencyStatus, account, isAccountsMode ->
|
||||||
|
val secondaryStatus = (uiState.value as? SwapAmountUM.Content)?.secondaryCryptoCurrencyStatus
|
||||||
|
initCurrencies(
|
||||||
|
primaryStatus = primaryCurrencyStatus,
|
||||||
|
secondaryStatus = secondaryStatus,
|
||||||
|
)
|
||||||
|
if (secondaryStatus != null) {
|
||||||
|
uiState.transformerUpdate(
|
||||||
|
SwapAmountUpdateBalanceTransformer(
|
||||||
|
cryptoCurrencyStatus = primaryCurrencyStatus,
|
||||||
|
primaryMaximumAmountBoundary = primaryMaximumAmountBoundary,
|
||||||
|
primaryMinimumAmountBoundary = primaryMinimumAmountBoundary,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
if (secondaryStatus != null) {
|
} else {
|
||||||
uiState.transformerUpdate(
|
val isOnlyOneWallet = getWalletsUseCase.invokeSync().size == 1
|
||||||
SwapAmountUpdateBalanceTransformer(
|
uiState.transformerUpdate(
|
||||||
cryptoCurrencyStatus = primaryCurrencyStatus,
|
SwapAmountPrimaryReadyStateTransformer(
|
||||||
primaryMaximumAmountBoundary = primaryMaximumAmountBoundary,
|
userWallet = userWallet,
|
||||||
primaryMinimumAmountBoundary = primaryMinimumAmountBoundary,
|
primaryCryptoCurrencyStatus = primaryCurrencyStatus,
|
||||||
),
|
appCurrency = appCurrency,
|
||||||
)
|
swapDirection = swapDirection,
|
||||||
} else {
|
clickIntents = this,
|
||||||
val isOnlyOneWallet = getWalletsUseCase.invokeSync().size == 1
|
isBalanceHidden = params.isBalanceHidingFlow.value,
|
||||||
uiState.transformerUpdate(
|
showBestRateAnimation = showBestRateAnimation,
|
||||||
SwapAmountPrimaryReadyStateTransformer(
|
isSingleWallet = isOnlyOneWallet,
|
||||||
userWallet = userWallet,
|
isAccountsMode = isAccountsMode,
|
||||||
primaryCryptoCurrencyStatus = primaryCurrencyStatus,
|
account = account,
|
||||||
appCurrency = appCurrency,
|
),
|
||||||
swapDirection = swapDirection,
|
)
|
||||||
clickIntents = this,
|
}
|
||||||
isBalanceHidden = params.isBalanceHidingFlow.value,
|
}.flowOn(dispatchers.default)
|
||||||
showBestRateAnimation = showBestRateAnimation,
|
.launchIn(modelScope)
|
||||||
isSingleWallet = isOnlyOneWallet,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}.launchIn(modelScope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun subscribeOnAmountUpdateTriggerUpdates() {
|
private fun subscribeOnAmountUpdateTriggerUpdates() {
|
||||||
|
|
@ -523,6 +534,8 @@ internal class SwapAmountModel @Inject constructor(
|
||||||
isBalanceHidden = params.isBalanceHidingFlow.value,
|
isBalanceHidden = params.isBalanceHidingFlow.value,
|
||||||
showBestRateAnimation = showBestRateAnimation,
|
showBestRateAnimation = showBestRateAnimation,
|
||||||
isSingleWallet = isOnlyOneWallet,
|
isSingleWallet = isOnlyOneWallet,
|
||||||
|
isAccountsMode = params.isAccountModeFlow.value,
|
||||||
|
account = params.accountFlow.value,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
startLoadingQuotesTask(isSilentReload = false)
|
startLoadingQuotesTask(isSilentReload = false)
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import com.tangem.core.ui.format.bigdecimal.crypto
|
||||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||||
import com.tangem.core.ui.format.bigdecimal.format
|
import com.tangem.core.ui.format.bigdecimal.format
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
|
import com.tangem.domain.models.account.Account
|
||||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.domain.swap.models.SwapDirection
|
import com.tangem.domain.swap.models.SwapDirection
|
||||||
|
|
@ -19,6 +20,7 @@ import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountFieldUM
|
||||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountType
|
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountType
|
||||||
import com.tangem.utils.StringsSigns.DOT
|
import com.tangem.utils.StringsSigns.DOT
|
||||||
|
|
||||||
|
@Suppress("LongParameterList")
|
||||||
internal class SwapAmountFieldConverter(
|
internal class SwapAmountFieldConverter(
|
||||||
private val swapDirection: SwapDirection,
|
private val swapDirection: SwapDirection,
|
||||||
private val isBalanceHidden: Boolean,
|
private val isBalanceHidden: Boolean,
|
||||||
|
|
@ -26,6 +28,8 @@ internal class SwapAmountFieldConverter(
|
||||||
private val appCurrency: AppCurrency,
|
private val appCurrency: AppCurrency,
|
||||||
private val clickIntents: AmountScreenClickIntents,
|
private val clickIntents: AmountScreenClickIntents,
|
||||||
private val isSingleWallet: Boolean,
|
private val isSingleWallet: Boolean,
|
||||||
|
@Suppress("UnusedPrivateProperty") private val isAccountsMode: Boolean,
|
||||||
|
@Suppress("UnusedPrivateProperty") private val account: Account.CryptoPortfolio?,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val iconStateConverter = CryptoCurrencyToIconStateConverter()
|
private val iconStateConverter = CryptoCurrencyToIconStateConverter()
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.tangem.features.swap.v2.impl.amount.model.transformers
|
||||||
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
||||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
|
import com.tangem.domain.models.account.Account
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.domain.swap.models.SwapDirection
|
import com.tangem.domain.swap.models.SwapDirection
|
||||||
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountFieldUM
|
import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountFieldUM
|
||||||
|
|
@ -11,6 +12,7 @@ import com.tangem.features.swap.v2.impl.amount.entity.SwapAmountUM
|
||||||
import com.tangem.features.swap.v2.impl.amount.model.converter.SwapAmountFieldConverter
|
import com.tangem.features.swap.v2.impl.amount.model.converter.SwapAmountFieldConverter
|
||||||
import com.tangem.utils.transformer.Transformer
|
import com.tangem.utils.transformer.Transformer
|
||||||
|
|
||||||
|
@Suppress("LongParameterList")
|
||||||
internal class SwapAmountBalanceHiddenTransformer(
|
internal class SwapAmountBalanceHiddenTransformer(
|
||||||
private val isBalanceHidden: Boolean,
|
private val isBalanceHidden: Boolean,
|
||||||
private val isSingleWallet: Boolean,
|
private val isSingleWallet: Boolean,
|
||||||
|
|
@ -18,6 +20,8 @@ internal class SwapAmountBalanceHiddenTransformer(
|
||||||
private val appCurrency: AppCurrency,
|
private val appCurrency: AppCurrency,
|
||||||
private val swapDirection: SwapDirection,
|
private val swapDirection: SwapDirection,
|
||||||
private val clickIntents: AmountScreenClickIntents,
|
private val clickIntents: AmountScreenClickIntents,
|
||||||
|
private val isAccountsMode: Boolean,
|
||||||
|
private val account: Account.CryptoPortfolio?,
|
||||||
) : Transformer<SwapAmountUM> {
|
) : Transformer<SwapAmountUM> {
|
||||||
|
|
||||||
override fun transform(prevState: SwapAmountUM): SwapAmountUM {
|
override fun transform(prevState: SwapAmountUM): SwapAmountUM {
|
||||||
|
|
@ -30,6 +34,8 @@ internal class SwapAmountBalanceHiddenTransformer(
|
||||||
appCurrency = appCurrency,
|
appCurrency = appCurrency,
|
||||||
clickIntents = clickIntents,
|
clickIntents = clickIntents,
|
||||||
isSingleWallet = isSingleWallet,
|
isSingleWallet = isSingleWallet,
|
||||||
|
isAccountsMode = isAccountsMode,
|
||||||
|
account = account,
|
||||||
)
|
)
|
||||||
|
|
||||||
val recalculatedPrimary = amountFieldConverter.convert(
|
val recalculatedPrimary = amountFieldConverter.convert(
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.tangem.features.swap.v2.impl.amount.model.transformers
|
||||||
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.express.models.ExpressRateType
|
import com.tangem.domain.express.models.ExpressRateType
|
||||||
|
import com.tangem.domain.models.account.Account
|
||||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.domain.swap.models.SwapCurrencies
|
import com.tangem.domain.swap.models.SwapCurrencies
|
||||||
|
|
@ -25,6 +26,8 @@ internal class SwapAmountPrimaryReadyStateTransformer(
|
||||||
private val isBalanceHidden: Boolean,
|
private val isBalanceHidden: Boolean,
|
||||||
private val showBestRateAnimation: Boolean,
|
private val showBestRateAnimation: Boolean,
|
||||||
private val isSingleWallet: Boolean,
|
private val isSingleWallet: Boolean,
|
||||||
|
private val isAccountsMode: Boolean,
|
||||||
|
private val account: Account.CryptoPortfolio?,
|
||||||
) : Transformer<SwapAmountUM> {
|
) : Transformer<SwapAmountUM> {
|
||||||
|
|
||||||
private val amountFieldConverter = SwapAmountFieldConverter(
|
private val amountFieldConverter = SwapAmountFieldConverter(
|
||||||
|
|
@ -34,6 +37,8 @@ internal class SwapAmountPrimaryReadyStateTransformer(
|
||||||
appCurrency = appCurrency,
|
appCurrency = appCurrency,
|
||||||
clickIntents = clickIntents,
|
clickIntents = clickIntents,
|
||||||
isSingleWallet = isSingleWallet,
|
isSingleWallet = isSingleWallet,
|
||||||
|
isAccountsMode = isAccountsMode,
|
||||||
|
account = account,
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun transform(prevState: SwapAmountUM): SwapAmountUM {
|
override fun transform(prevState: SwapAmountUM): SwapAmountUM {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.tangem.features.swap.v2.impl.amount.model.transformers
|
||||||
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.express.models.ExpressRateType
|
import com.tangem.domain.express.models.ExpressRateType
|
||||||
|
import com.tangem.domain.models.account.Account
|
||||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.domain.swap.models.SwapCurrencies
|
import com.tangem.domain.swap.models.SwapCurrencies
|
||||||
|
|
@ -26,6 +27,8 @@ internal class SwapAmountSecondaryReadyStateTransformer(
|
||||||
private val isBalanceHidden: Boolean,
|
private val isBalanceHidden: Boolean,
|
||||||
private val showBestRateAnimation: Boolean,
|
private val showBestRateAnimation: Boolean,
|
||||||
private val isSingleWallet: Boolean,
|
private val isSingleWallet: Boolean,
|
||||||
|
private val isAccountsMode: Boolean,
|
||||||
|
private val account: Account.CryptoPortfolio?,
|
||||||
) : Transformer<SwapAmountUM> {
|
) : Transformer<SwapAmountUM> {
|
||||||
|
|
||||||
private val amountFieldConverter = SwapAmountFieldConverter(
|
private val amountFieldConverter = SwapAmountFieldConverter(
|
||||||
|
|
@ -35,6 +38,8 @@ internal class SwapAmountSecondaryReadyStateTransformer(
|
||||||
appCurrency = appCurrency,
|
appCurrency = appCurrency,
|
||||||
clickIntents = clickIntents,
|
clickIntents = clickIntents,
|
||||||
isSingleWallet = isSingleWallet,
|
isSingleWallet = isSingleWallet,
|
||||||
|
isAccountsMode = isAccountsMode,
|
||||||
|
account = account,
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun transform(prevState: SwapAmountUM): SwapAmountUM {
|
override fun transform(prevState: SwapAmountUM): SwapAmountUM {
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,8 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor(
|
||||||
userWallet = model.userWallet,
|
userWallet = model.userWallet,
|
||||||
filterProviderTypes = SEND_WITH_SWAP_PROVIDER_TYPES,
|
filterProviderTypes = SEND_WITH_SWAP_PROVIDER_TYPES,
|
||||||
analyticsSendSource = model.analyticsSendSource,
|
analyticsSendSource = model.analyticsSendSource,
|
||||||
|
accountFlow = model.accountFlow,
|
||||||
|
isAccountModeFlow = model.isAccountModeFlow,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -199,6 +201,8 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor(
|
||||||
analyticsCategoryName = model.analyticCategoryName,
|
analyticsCategoryName = model.analyticCategoryName,
|
||||||
primaryCryptoCurrencyStatusFlow = model.primaryCryptoCurrencyStatusFlow,
|
primaryCryptoCurrencyStatusFlow = model.primaryCryptoCurrencyStatusFlow,
|
||||||
primaryFeePaidCurrencyStatusFlow = model.primaryFeePaidCurrencyStatusFlow,
|
primaryFeePaidCurrencyStatusFlow = model.primaryFeePaidCurrencyStatusFlow,
|
||||||
|
accountFlow = model.accountFlow,
|
||||||
|
isAccountModeFlow = model.isAccountModeFlow,
|
||||||
analyticsSendSource = model.analyticsSendSource,
|
analyticsSendSource = model.analyticsSendSource,
|
||||||
swapDirection = SwapDirection.Direct,
|
swapDirection = SwapDirection.Direct,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import com.tangem.core.decompose.context.childByContext
|
||||||
import com.tangem.core.decompose.model.getOrCreateModel
|
import com.tangem.core.decompose.model.getOrCreateModel
|
||||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
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.CryptoCurrency
|
||||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
|
|
@ -62,6 +63,8 @@ internal class SendWithSwapConfirmComponent @AssistedInject constructor(
|
||||||
swapDirection = params.swapDirection,
|
swapDirection = params.swapDirection,
|
||||||
filterProviderTypes = SEND_WITH_SWAP_PROVIDER_TYPES,
|
filterProviderTypes = SEND_WITH_SWAP_PROVIDER_TYPES,
|
||||||
analyticsSendSource = params.analyticsSendSource,
|
analyticsSendSource = params.analyticsSendSource,
|
||||||
|
accountFlow = params.accountFlow,
|
||||||
|
isAccountModeFlow = params.isAccountModeFlow,
|
||||||
),
|
),
|
||||||
onResult = model::onAmountResult,
|
onResult = model::onAmountResult,
|
||||||
onClick = model::showEditAmount,
|
onClick = model::showEditAmount,
|
||||||
|
|
@ -175,6 +178,8 @@ internal class SendWithSwapConfirmComponent @AssistedInject constructor(
|
||||||
val isBalanceHidingFlow: StateFlow<Boolean>,
|
val isBalanceHidingFlow: StateFlow<Boolean>,
|
||||||
val primaryCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
val primaryCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
||||||
val primaryFeePaidCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
val primaryFeePaidCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
||||||
|
val accountFlow: StateFlow<Account.CryptoPortfolio?>,
|
||||||
|
val isAccountModeFlow: StateFlow<Boolean>,
|
||||||
val callback: ModelCallback,
|
val callback: ModelCallback,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,15 @@ import com.tangem.core.decompose.di.ModelScoped
|
||||||
import com.tangem.core.decompose.model.Model
|
import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.model.ParamsContainer
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
import com.tangem.core.decompose.navigation.Router
|
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.GetSelectedAppCurrencyUseCase
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||||
import com.tangem.domain.express.models.ExpressError
|
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.CryptoCurrency
|
||||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
|
|
@ -50,7 +54,10 @@ internal class SendWithSwapModel @Inject constructor(
|
||||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||||
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||||
|
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||||
|
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||||
private val swapAlertFactory: SwapAlertFactory,
|
private val swapAlertFactory: SwapAlertFactory,
|
||||||
|
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||||
paramsContainer: ParamsContainer,
|
paramsContainer: ParamsContainer,
|
||||||
) : Model(),
|
) : Model(),
|
||||||
SwapAmountComponent.ModelCallback,
|
SwapAmountComponent.ModelCallback,
|
||||||
|
|
@ -89,6 +96,12 @@ internal class SendWithSwapModel @Inject constructor(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val accountFlow: StateFlow<Account.CryptoPortfolio?>
|
||||||
|
field = MutableStateFlow(null)
|
||||||
|
|
||||||
|
val isAccountModeFlow: StateFlow<Boolean>
|
||||||
|
field = MutableStateFlow(false)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
initUserWallet()
|
initUserWallet()
|
||||||
initAppCurrency()
|
initAppCurrency()
|
||||||
|
|
@ -192,36 +205,54 @@ internal class SendWithSwapModel @Inject constructor(
|
||||||
val isSingleWalletWithToken = wallet is UserWallet.Cold &&
|
val isSingleWalletWithToken = wallet is UserWallet.Cold &&
|
||||||
wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
|
||||||
|
|
||||||
getCurrencyStatus(
|
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||||
cryptoCurrency = cryptoCurrency,
|
getAccountCurrencyStatusUseCase(
|
||||||
isSingleWalletWithToken = isSingleWalletWithToken,
|
userWalletId = params.userWalletId,
|
||||||
isMultiCurrency = isMultiCurrency,
|
currency = cryptoCurrency,
|
||||||
).onEach { maybeCryptoCurrency ->
|
).onEach { (account, cryptoCurrencyStatus) ->
|
||||||
maybeCryptoCurrency.fold(
|
accountFlow.value = account
|
||||||
ifRight = { cryptoCurrencyStatus ->
|
isAccountModeFlow.value = isAccountsModeEnabledUseCase.invokeSync()
|
||||||
primaryCryptoCurrencyStatusFlow.value = cryptoCurrencyStatus
|
|
||||||
primaryFeePaidCurrencyStatusFlow.value = getFeePaidCryptoCurrencyStatusSyncUseCase(
|
primaryCryptoCurrencyStatusFlow.value = cryptoCurrencyStatus
|
||||||
userWalletId = params.userWalletId,
|
primaryFeePaidCurrencyStatusFlow.value = getFeePaidCryptoCurrencyStatusSyncUseCase(
|
||||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
userWalletId = params.userWalletId,
|
||||||
).getOrNull() ?: cryptoCurrencyStatus
|
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||||
},
|
).getOrNull() ?: cryptoCurrencyStatus
|
||||||
ifLeft = { error ->
|
}.flowOn(dispatchers.default)
|
||||||
swapAlertFactory.getGenericErrorState(
|
.launchIn(modelScope)
|
||||||
expressError = ExpressError.UnknownError,
|
} else {
|
||||||
onFailedTxEmailClick = {
|
getCurrencyStatus(
|
||||||
modelScope.launch {
|
cryptoCurrency = cryptoCurrency,
|
||||||
swapAlertFactory.onFailedTxEmailClick(
|
isSingleWalletWithToken = isSingleWalletWithToken,
|
||||||
userWallet = userWallet,
|
isMultiCurrency = isMultiCurrency,
|
||||||
cryptoCurrency = params.currency,
|
).onEach { maybeCryptoCurrency ->
|
||||||
errorMessage = error.toString(),
|
maybeCryptoCurrency.fold(
|
||||||
)
|
ifRight = { cryptoCurrencyStatus ->
|
||||||
}
|
primaryCryptoCurrencyStatusFlow.value = cryptoCurrencyStatus
|
||||||
},
|
primaryFeePaidCurrencyStatusFlow.value = getFeePaidCryptoCurrencyStatusSyncUseCase(
|
||||||
popBack = ::onBackClick,
|
userWalletId = params.userWalletId,
|
||||||
)
|
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||||
},
|
).getOrNull() ?: cryptoCurrencyStatus
|
||||||
)
|
},
|
||||||
}.launchIn(modelScope)
|
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(
|
private fun getCurrencyStatus(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue