From c2ad62c94c6cc6d009682bb181237920ebc8359f Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 21 Apr 2025 11:50:08 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../send/v2/send/DefaultSendComponent.kt | 2 + .../v2/send/confirm/SendConfirmComponent.kt | 7 +- .../features/send/v2/send/model/SendModel.kt | 18 +++++ .../v2/sendnft/DefaultNFTSendComponent.kt | 2 + .../confirm/NFTSendConfirmComponent.kt | 5 ++ .../send/v2/sendnft/model/NFTSendModel.kt | 26 +++++- .../fee/SendFeeComponentParams.kt | 6 ++ .../subcomponents/fee/model/SendFeeModel.kt | 81 +++++++------------ 8 files changed, 91 insertions(+), 56 deletions(-) diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/DefaultSendComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/DefaultSendComponent.kt index 82168f4518..d94ae93e49 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/DefaultSendComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/DefaultSendComponent.kt @@ -201,6 +201,7 @@ internal class DefaultSendComponent @AssistedInject constructor( cryptoCurrencyStatus = model.cryptoCurrencyStatus, feeCryptoCurrencyStatus = model.feeCryptoCurrencyStatus, appCurrency = model.appCurrency, + onLoadFee = model::loadFee, sendAmount = sendAmount, destinationAddress = destinationAddress, callback = model, @@ -240,6 +241,7 @@ internal class DefaultSendComponent @AssistedInject constructor( appCurrency = model.appCurrency, callback = model, predefinedValues = predefinedValues, + onLoadFee = model::loadFee, ), ) } diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/SendConfirmComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/SendConfirmComponent.kt index 8b93d2cb71..a7145d5d6e 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/SendConfirmComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/SendConfirmComponent.kt @@ -4,18 +4,21 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.lifecycle.compose.collectAsStateWithLifecycle +import arrow.core.Either +import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.context.child import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.wallets.models.UserWallet import com.tangem.features.send.v2.common.CommonSendRoute import com.tangem.features.send.v2.common.PredefinedValues +import com.tangem.features.send.v2.common.ui.state.ConfirmUM import com.tangem.features.send.v2.send.confirm.model.SendConfirmModel import com.tangem.features.send.v2.send.confirm.ui.SendConfirmContent -import com.tangem.features.send.v2.common.ui.state.ConfirmUM import com.tangem.features.send.v2.send.ui.state.SendUM import com.tangem.features.send.v2.subcomponents.amount.SendAmountBlockComponent import com.tangem.features.send.v2.subcomponents.amount.SendAmountComponentParams @@ -79,6 +82,7 @@ internal class SendConfirmComponent( sendAmount = model.confirmData.enteredAmount.orZero(), destinationAddress = model.confirmData.enteredDestination.orEmpty(), blockClickEnableFlow = blockClickEnableFlow.asStateFlow(), + onLoadFee = params.onLoadFee, ), onResult = model::onFeeResult, onClick = model::showEditFee, @@ -144,6 +148,7 @@ internal class SendConfirmComponent( val currentRoute: Flow, val isBalanceHidingFlow: StateFlow, val predefinedValues: PredefinedValues, + val onLoadFee: suspend () -> Either, ) interface ModelCallback { diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/model/SendModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/model/SendModel.kt index 06a72af707..c153cbe90e 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/model/SendModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/model/SendModel.kt @@ -3,6 +3,7 @@ package com.tangem.features.send.v2.send.model import androidx.compose.runtime.Stable import arrow.core.Either import arrow.core.getOrElse +import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.common.ui.amountScreen.models.AmountState import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model @@ -26,6 +27,8 @@ import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.transaction.error.GetFeeError +import com.tangem.domain.transaction.usecase.GetTransferFeeUseCase import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.send.v2.api.SendComponent @@ -76,6 +79,7 @@ internal class SendModel @Inject constructor( private val getCardInfoUseCase: GetCardInfoUseCase, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, + private val getTransferFeeUseCase: GetTransferFeeUseCase, private val sendAmountUpdateQRTrigger: SendAmountUpdateQRTrigger, ) : Model(), SendComponentCallback { @@ -126,6 +130,20 @@ internal class SendModel @Inject constructor( _uiState.update { sendUM } } + suspend fun loadFee(): Either { + val destinationUM = uiState.value.destinationUM as? DestinationUM.Content ?: error("Invalid destination") + val amountUM = uiState.value.amountUM as? AmountState.Data ?: error("Invalid amount") + val enteredDestinationAddress = destinationUM.addressTextField.value + val enteredAmount = amountUM.amountTextField.cryptoAmount.value ?: error("Invalid amount") + + return getTransferFeeUseCase( + destination = enteredDestinationAddress, + amount = enteredAmount, + userWallet = userWallet, + cryptoCurrency = params.currency, + ) + } + private fun resetPredefinedAmount() { // reset predefined amount val internalPredefinedValues = predefinedValues diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/DefaultNFTSendComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/DefaultNFTSendComponent.kt index 095cb06ce3..4b65d6d5ae 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/DefaultNFTSendComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/DefaultNFTSendComponent.kt @@ -151,6 +151,7 @@ internal class DefaultNFTSendComponent @AssistedInject constructor( feeCryptoCurrencyStatus = model.feeCryptoCurrencyStatus, appCurrency = model.appCurrency, sendAmount = BigDecimal.ZERO, + onLoadFee = model::loadFee, destinationAddress = destinationAddress, callback = model, onNextClick = ::onChildBack, @@ -176,6 +177,7 @@ internal class DefaultNFTSendComponent @AssistedInject constructor( callback = model, currentRoute = currentRouteFlow.filterIsInstance(), isBalanceHidingFlow = model.isBalanceHiddenFlow, + onLoadFee = model::loadFee, ), ) diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/NFTSendConfirmComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/NFTSendConfirmComponent.kt index ead66f202b..486dd72606 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/NFTSendConfirmComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/confirm/NFTSendConfirmComponent.kt @@ -4,6 +4,8 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.lifecycle.compose.collectAsStateWithLifecycle +import arrow.core.Either +import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.context.child import com.tangem.core.decompose.model.getOrCreateModel @@ -11,6 +13,7 @@ import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.nft.models.NFTAsset import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.wallets.models.UserWallet import com.tangem.features.nft.component.NFTDetailsBlockComponent import com.tangem.features.send.v2.common.CommonSendRoute @@ -63,6 +66,7 @@ internal class NFTSendConfirmComponent( feeCryptoCurrencyStatus = params.feeCryptoCurrencyStatus, appCurrency = params.appCurrency, sendAmount = BigDecimal.ZERO, + onLoadFee = params.onLoadFee, destinationAddress = model.confirmData.enteredDestination.orEmpty(), blockClickEnableFlow = blockClickEnableFlow.asStateFlow(), ), @@ -139,6 +143,7 @@ internal class NFTSendConfirmComponent( val callback: ModelCallback, val currentRoute: Flow, val isBalanceHidingFlow: StateFlow, + val onLoadFee: suspend () -> Either, ) interface ModelCallback { diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt index 7b3be9e2b3..65d322cf3f 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/model/NFTSendModel.kt @@ -1,7 +1,9 @@ package com.tangem.features.send.v2.sendnft.model import androidx.compose.runtime.Stable +import arrow.core.Either import arrow.core.getOrElse +import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer @@ -14,12 +16,13 @@ import com.tangem.domain.tokens.GetCurrencyStatusUpdatesUseCase import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.send.v2.api.NFTSendComponent import com.tangem.features.send.v2.common.CommonSendRoute -import com.tangem.features.send.v2.common.ui.state.NavigationUM import com.tangem.features.send.v2.common.ui.state.ConfirmUM +import com.tangem.features.send.v2.common.ui.state.NavigationUM import com.tangem.features.send.v2.sendnft.confirm.NFTSendConfirmComponent import com.tangem.features.send.v2.sendnft.ui.state.NFTSendUM import com.tangem.features.send.v2.subcomponents.destination.SendDestinationComponent @@ -88,6 +91,23 @@ internal class NFTSendModel @Inject constructor( _uiState.update { it.copy(feeUM = feeUM) } } + suspend fun loadFee(): Either { + TODO() + // val destinationUM = uiState.value.destinationUM as? DestinationUM.Content ?: error("Invalid destination") + // val ownerAddress = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value + // ?: error("Invalid owner address") + // val enteredDestinationAddress = destinationUM.addressTextField.value + // val nftAsset = null // NFTSdkAssetConverter.convertBack(params.nftAsset).second + + // getNFTTransferFeeUseCase( + // ownerAddress = ownerAddress, + // destinationAddress = enteredDestinationAddress, + // nftAsset = nftAsset, + // userWallet = userWallet, + // cryptoCurrency = cryptoCurrency, + // ) + } + private fun initAppCurrency() { modelScope.launch { appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default } @@ -131,7 +151,9 @@ internal class NFTSendModel @Inject constructor( cryptoCurrencyStatus = cryptoStatus, ).getOrNull() ?: cryptoStatus - router.replaceAll(CommonSendRoute.Destination(isEditMode = false)) + if (uiState.value.destinationUM is DestinationUM.Empty) { + router.replaceAll(CommonSendRoute.Destination(isEditMode = false)) + } }, ifLeft = { // sendConfirmAlertFactory.getGenericErrorState { diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/fee/SendFeeComponentParams.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/fee/SendFeeComponentParams.kt index 20e3c94ded..60b98fffbf 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/fee/SendFeeComponentParams.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/fee/SendFeeComponentParams.kt @@ -1,7 +1,10 @@ package com.tangem.features.send.v2.subcomponents.fee +import arrow.core.Either +import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.wallets.models.UserWallet import com.tangem.features.send.v2.common.CommonSendRoute import com.tangem.features.send.v2.subcomponents.fee.ui.state.FeeUM @@ -19,6 +22,7 @@ internal sealed class SendFeeComponentParams { abstract val appCurrency: AppCurrency abstract val sendAmount: BigDecimal abstract val destinationAddress: String + abstract val onLoadFee: suspend () -> Either data class FeeParams( override val state: FeeUM, @@ -29,6 +33,7 @@ internal sealed class SendFeeComponentParams { override val appCurrency: AppCurrency, override val sendAmount: BigDecimal, override val destinationAddress: String, + override val onLoadFee: suspend () -> Either, val currentRoute: Flow, val callback: SendFeeComponent.ModelCallback, val onNextClick: () -> Unit, @@ -43,6 +48,7 @@ internal sealed class SendFeeComponentParams { override val appCurrency: AppCurrency, override val sendAmount: BigDecimal, override val destinationAddress: String, + override val onLoadFee: suspend () -> Either, val blockClickEnableFlow: StateFlow, ) : SendFeeComponentParams() } \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/fee/model/SendFeeModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/fee/model/SendFeeModel.kt index b2bd054e2a..5bc3264f89 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/fee/model/SendFeeModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/subcomponents/fee/model/SendFeeModel.kt @@ -8,7 +8,6 @@ import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.navigation.url.UrlOpener import com.tangem.core.ui.extensions.resourceReference -import com.tangem.domain.transaction.usecase.GetTransferFeeUseCase import com.tangem.domain.transaction.usecase.IsFeeApproximateUseCase import com.tangem.features.send.v2.common.ui.state.NavigationUM import com.tangem.features.send.v2.impl.R @@ -29,7 +28,6 @@ import com.tangem.utils.coroutines.saveIn import com.tangem.utils.transformer.update import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch -import java.math.BigDecimal import java.util.Locale import javax.inject.Inject @@ -40,7 +38,6 @@ internal class SendFeeModel @Inject constructor( paramsContainer: ParamsContainer, override val dispatchers: CoroutineDispatcherProvider, private val isFeeApproximateUseCase: IsFeeApproximateUseCase, - private val getTransferFeeUseCase: GetTransferFeeUseCase, private val urlOpener: UrlOpener, private val analyticsEventHandler: AnalyticsEventHandler, private val sendFeeAlertFactory: SendFeeAlertFactory, @@ -74,10 +71,32 @@ internal class SendFeeModel @Inject constructor( } override fun feeReload() { - loadFee( - amountValue = params.sendAmount, - destinationAddress = params.destinationAddress, - ) + modelScope.launch { + val isShowLoading = (uiState.value as? FeeUM.Content)?.feeSelectorUM !is FeeSelectorUM.Content + if (isShowLoading) { + _uiState.update(SendFeeLoadingTransformer) + } + params.onLoadFee().fold( + ifRight = { + _uiState.update( + SendFeeLoadedTransformer( + fees = it, + clickIntents = this@SendFeeModel, + appCurrency = appCurrency, + feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, + isFeeApproximate = isFeeApproximate(it.normal.amount.type), + ), + ) + updateFeeNotifications() + }, + ifLeft = { feeError -> + if (isShowLoading) { + _uiState.update(SendFeeFailedTransformer(feeError)) + } + updateFeeNotifications() + }, + ) + }.saveIn(feeJobHolder) } override fun onFeeSelectorClick(feeType: FeeType) { @@ -159,12 +178,7 @@ internal class SendFeeModel @Inject constructor( private fun subscribeOnFeeReloadTriggerUpdates() { feeReloadListener.reloadTriggerFlow - .onEach { (amount, destination) -> - loadFee( - amountValue = amount ?: params.sendAmount, - destinationAddress = destination ?: params.destinationAddress, - ) - } + .onEach { feeReload() } .launchIn(modelScope) } @@ -186,48 +200,9 @@ internal class SendFeeModel @Inject constructor( params.callback.onFeeResult(uiState.value) } - private fun loadFee(amountValue: BigDecimal, destinationAddress: String) { - modelScope.launch { - val isShowLoading = (uiState.value as? FeeUM.Content)?.feeSelectorUM !is FeeSelectorUM.Content - if (isShowLoading) { - _uiState.update(SendFeeLoadingTransformer) - } - getTransferFeeUseCase.invoke( - amount = amountValue, - destination = destinationAddress, - userWallet = params.userWallet, - cryptoCurrency = cryptoCurrencyStatus.currency, - ).fold( - ifRight = { - _uiState.update( - SendFeeLoadedTransformer( - fees = it, - clickIntents = this@SendFeeModel, - appCurrency = appCurrency, - feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, - isFeeApproximate = isFeeApproximate(it.normal.amount.type), - ), - ) - updateFeeNotifications() - }, - ifLeft = { feeError -> - if (isShowLoading) { - _uiState.update(SendFeeFailedTransformer(feeError)) - } - updateFeeNotifications() - }, - ) - }.saveIn(feeJobHolder) - } - private fun checkLoadFee() { modelScope.launch { - getTransferFeeUseCase.invoke( - amount = params.sendAmount, - destination = params.destinationAddress, - userWallet = params.userWallet, - cryptoCurrency = cryptoCurrencyStatus.currency, - ).fold( + params.onLoadFee().fold( ifRight = { sendFeeAlertFactory.getFeeUpdatedAlert( newFee = it,