From a61004a3c1d3e1f23a46714b6eeff0504dde1d4c Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 6 Jan 2026 13:44:56 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tangem/core/decompose/utils/Extensions.kt | 18 +++ features/send-v2/api/build.gradle.kts | 3 + .../send/v2/api/entity/FeeSelectorUM.kt | 2 + .../send/v2/api/params/FeeSelectorParams.kt | 4 + .../DefaultFeeSelectorComponent.kt | 19 ++- .../entity/SelectedTokenItemConverter.kt | 54 +++++++-- .../model/FeeExtendedSelectorModel.kt | 39 ++++--- .../extended/ui/FeeExtendedSelectorContent.kt | 33 ++++++ .../speed/ui/FeeSpeedSelectorContent.kt | 110 ++++++++++++------ .../model/FeeSelectorBlockModel.kt | 4 +- .../v2/feeselector/model/FeeSelectorLogic.kt | 83 ++++++++++--- .../v2/feeselector/model/FeeSelectorModel.kt | 58 ++++++++- .../FeeSelectorLoadedTransformer.kt | 15 ++- .../v2/feeselector/route/FeeSelectorRoute.kt | 2 +- .../feeselector/ui/FeeSelectorBlockContent.kt | 52 ++++++++- ...firmationNotificationsTransformerV2Test.kt | 34 ++++++ ...firmationNotificationsTransformerV2Test.kt | 34 ++++++ .../success/ui/SendWithSwapSuccessContent.kt | 1 + 18 files changed, 459 insertions(+), 106 deletions(-) create mode 100644 core/decompose/src/main/kotlin/com/tangem/core/decompose/utils/Extensions.kt diff --git a/core/decompose/src/main/kotlin/com/tangem/core/decompose/utils/Extensions.kt b/core/decompose/src/main/kotlin/com/tangem/core/decompose/utils/Extensions.kt new file mode 100644 index 0000000000..f21a549bec --- /dev/null +++ b/core/decompose/src/main/kotlin/com/tangem/core/decompose/utils/Extensions.kt @@ -0,0 +1,18 @@ +package com.tangem.core.decompose.utils + +import com.arkivanov.decompose.router.stack.StackNavigation +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlin.coroutines.resume + +/** + * Retrieves the current stack of items from the [com.arkivanov.decompose.router.stack.ChildStack] + * @return A list representing the current stack of items + */ +suspend fun StackNavigation.stack(): List { + return suspendCancellableCoroutine { continuation -> + this.navigate( + transformer = { stack -> stack }, + onComplete = { newStack, oldStack -> continuation.resume(newStack) }, + ) + } +} \ No newline at end of file diff --git a/features/send-v2/api/build.gradle.kts b/features/send-v2/api/build.gradle.kts index 454fcee782..a44ab7f1f9 100644 --- a/features/send-v2/api/build.gradle.kts +++ b/features/send-v2/api/build.gradle.kts @@ -21,6 +21,9 @@ dependencies { /** Common */ implementation(projects.common.ui) + /** Domain */ + implementation(projects.domain.transaction) + /** Domain models */ api(projects.domain.models) implementation(projects.domain.appCurrency.models) diff --git a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/entity/FeeSelectorUM.kt b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/entity/FeeSelectorUM.kt index 89ddb338b6..40c2047420 100644 --- a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/entity/FeeSelectorUM.kt +++ b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/entity/FeeSelectorUM.kt @@ -7,6 +7,7 @@ import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.transaction.error.GetFeeError import com.tangem.features.send.v2.api.R import com.tangem.features.send.v2.api.entity.FeeItem.* @@ -61,6 +62,7 @@ data class FeeExtraInfo( val isFeeApproximate: Boolean, val isFeeConvertibleToFiat: Boolean, val isTronToken: Boolean, + val feeCryptoCurrencyStatus: CryptoCurrencyStatus, ) sealed class FeeNonce { diff --git a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/params/FeeSelectorParams.kt b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/params/FeeSelectorParams.kt index 2c1ae24ec6..d45422c572 100644 --- a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/params/FeeSelectorParams.kt +++ b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/params/FeeSelectorParams.kt @@ -6,12 +6,14 @@ import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.core.ui.extensions.TextReference import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.transaction.error.GetFeeError +import com.tangem.domain.transaction.models.TransactionFeeExtended import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents import com.tangem.features.send.v2.api.callbacks.FeeSelectorModelCallback import com.tangem.features.send.v2.api.entity.FeeSelectorUM sealed class FeeSelectorParams { abstract val state: FeeSelectorUM + abstract val onLoadFeeExtended: (suspend () -> Either)? abstract val onLoadFee: suspend () -> Either abstract val cryptoCurrencyStatus: CryptoCurrencyStatus abstract val feeCryptoCurrencyStatus: CryptoCurrencyStatus @@ -22,6 +24,7 @@ sealed class FeeSelectorParams { data class FeeSelectorBlockParams( override val state: FeeSelectorUM, + override val onLoadFeeExtended: (suspend () -> Either)? = null, override val onLoadFee: suspend () -> Either, override val cryptoCurrencyStatus: CryptoCurrencyStatus, override val feeCryptoCurrencyStatus: CryptoCurrencyStatus, @@ -33,6 +36,7 @@ sealed class FeeSelectorParams { data class FeeSelectorDetailsParams( override val state: FeeSelectorUM, + override val onLoadFeeExtended: (suspend () -> Either)? = null, override val onLoadFee: suspend () -> Either, override val cryptoCurrencyStatus: CryptoCurrencyStatus, override val feeCryptoCurrencyStatus: CryptoCurrencyStatus, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorComponent.kt index 8ac294c931..5232daa424 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/DefaultFeeSelectorComponent.kt @@ -5,10 +5,8 @@ import androidx.compose.runtime.getValue import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.extensions.compose.subscribeAsState -import com.arkivanov.decompose.router.stack.StackNavigation import com.arkivanov.decompose.router.stack.childStack import com.arkivanov.decompose.router.stack.pop -import com.arkivanov.essenty.instancekeeper.getOrCreateSimple import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.context.childByContext import com.tangem.core.decompose.model.getOrCreateModel @@ -26,7 +24,6 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -@Suppress("PropertyUsedBeforeDeclaration") internal class DefaultFeeSelectorComponent @AssistedInject constructor( @Assisted appComponentContext: AppComponentContext, @Assisted private val params: FeeSelectorParams.FeeSelectorDetailsParams, @@ -35,22 +32,22 @@ internal class DefaultFeeSelectorComponent @AssistedInject constructor( private val feeSpeedSelectorComponentFactory: FeeSpeedSelectorComponent.Factory, ) : FeeSelectorComponent, AppComponentContext by appComponentContext { - private val stackNavigation = instanceKeeper.getOrCreateSimple { StackNavigation() } - private val innerRouter = InnerRouter( - stackNavigation = stackNavigation, + private val model: FeeSelectorModel = getOrCreateModel(params = params) + + val innerRouter = InnerRouter( + stackNavigation = model.stackNavigation, popCallback = { - stackNavigation.pop { success -> + model.stackNavigation.pop { success -> if (!success) { dismiss() } } }, ) - private val model: FeeSelectorModel = getOrCreateModel(params = params, router = innerRouter) private val contentStack = childStack( key = "FeeSelectorDetailsStack", - source = stackNavigation, + source = model.stackNavigation, serializer = FeeSelectorRoute.serializer(), initialConfiguration = model.getInitialRoute(), handleBackButton = false, @@ -69,7 +66,7 @@ internal class DefaultFeeSelectorComponent @AssistedInject constructor( FeeSelectorModalBottomSheet( childStack = contentStack, state = state, - feeSelectorIntents = model.intents, + feeSelectorIntents = model, feeDisplaySource = params.feeDisplaySource, onDismiss = onDismiss, onBack = innerRouter::pop, @@ -85,7 +82,7 @@ internal class DefaultFeeSelectorComponent @AssistedInject constructor( val componentParams = FeeSelectorComponentParams( parentParams = params, state = model.uiState, - intents = model.intents, + intents = model, ) return when (config) { diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/entity/SelectedTokenItemConverter.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/entity/SelectedTokenItemConverter.kt index 3652e62cc6..0959d98daf 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/entity/SelectedTokenItemConverter.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/entity/SelectedTokenItemConverter.kt @@ -1,23 +1,59 @@ package com.tangem.features.send.v2.feeselector.component.extended.entity import com.tangem.common.ui.tokens.TokenItemStateConverter +import com.tangem.core.ui.components.icons.IconTint import com.tangem.core.ui.components.token.state.TokenItemState +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.format.bigdecimal.fiat +import com.tangem.core.ui.format.bigdecimal.format import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.features.send.v2.impl.R +import com.tangem.utils.Provider import com.tangem.utils.converter.Converter internal class SelectedTokenItemConverter( - appCurrency: AppCurrency, - onTokenClick: () -> Unit, + private val appCurrencyProvider: Provider, + private val onTokenClick: () -> Unit, ) : Converter { - private val tokenItemConverter = TokenItemStateConverter( - appCurrency = appCurrency, - onItemClick = { _, _ -> onTokenClick() }, - ) - override fun convert(value: CryptoCurrencyStatus): TokenItemState { - // TODO - return tokenItemConverter.convert(value) + if (value.value !is CryptoCurrencyStatus.Loaded) { + return TokenItemState.Loading(id = value.currency.id.value) + } + + val appCurrency = appCurrencyProvider() + val tokenItemConverter = TokenItemStateConverter( + appCurrency = appCurrencyProvider(), + onItemClick = { _, _ -> onTokenClick() }, + ) + + val state = tokenItemConverter.convert(value) + + return when (state) { + is TokenItemState.Content -> { + val balance = value.value.fiatAmount.format { + fiat(fiatCurrencyCode = appCurrency.code, fiatCurrencySymbol = appCurrency.symbol) + } + + state.copy( + fiatAmountState = TokenItemState.FiatAmountState.Icon( + iconRes = R.drawable.ic_select_18_24, + tint = IconTint.Informative, + ), + subtitleState = TokenItemState.SubtitleState.TextContent( + value = resourceReference( + R.string.common_balance, + wrappedList(balance), + ), + isAvailable = false, + ), + subtitle2State = null, + + ) + } + else -> state + } } } \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/model/FeeExtendedSelectorModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/model/FeeExtendedSelectorModel.kt index 4f586f70f0..2a8728c552 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/model/FeeExtendedSelectorModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/model/FeeExtendedSelectorModel.kt @@ -13,6 +13,7 @@ import com.tangem.features.send.v2.feeselector.component.FeeSelectorComponentPar import com.tangem.features.send.v2.feeselector.component.extended.entity.FeeExtendedSelectorUM import com.tangem.features.send.v2.feeselector.component.extended.entity.SelectedTokenItemConverter import com.tangem.features.send.v2.feeselector.route.FeeSelectorRoute +import com.tangem.utils.Provider import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch @@ -29,44 +30,48 @@ class FeeExtendedSelectorModel @Inject constructor( private val params = paramsContainer.require() private var appCurrency: AppCurrency = AppCurrency.Default + private val tokenConverter = SelectedTokenItemConverter( + appCurrencyProvider = Provider { appCurrency }, + onTokenClick = { router.push(FeeSelectorRoute.ChooseToken) }, + ) + + init { + initAppCurrency() + } val uiState: StateFlow field = MutableStateFlow(getInitialState()) init { - modelScope.launch { - appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default } - uiState.value = getInitialState() - } - params.state + .filterIsInstance() .onEach(::onParentStateUpdated) .launchIn(modelScope) } private fun getInitialState(): FeeExtendedSelectorUM { - val status = params.parentParams.feeCryptoCurrencyStatus val parentContentState = params.state.value as FeeSelectorUM.Content return FeeExtendedSelectorUM( parent = parentContentState, - token = SelectedTokenItemConverter( - appCurrency = appCurrency, - onTokenClick = { - router.push(FeeSelectorRoute.ChooseToken) - }, - ).convert(status), + token = tokenConverter.convert(parentContentState.feeExtraInfo.feeCryptoCurrencyStatus), fee = parentContentState.selectedFeeItem, - onFeeClick = { - router.push(FeeSelectorRoute.ChooseSpeed) - }, + onFeeClick = { router.push(FeeSelectorRoute.ChooseSpeed) }, ) } - private fun onParentStateUpdated(state: FeeSelectorUM) { + private fun initAppCurrency() { + modelScope.launch { + appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default } + } + } + + private fun onParentStateUpdated(state: FeeSelectorUM.Content) { uiState.update { current -> current.copy( - parent = state as FeeSelectorUM.Content, + parent = state, + token = tokenConverter.convert(state.feeExtraInfo.feeCryptoCurrencyStatus), + fee = state.selectedFeeItem, ) } } diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/ui/FeeExtendedSelectorContent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/ui/FeeExtendedSelectorContent.kt index ff39f78cdd..a94b018eae 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/ui/FeeExtendedSelectorContent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/extended/ui/FeeExtendedSelectorContent.kt @@ -29,6 +29,9 @@ import com.tangem.core.ui.format.bigdecimal.format import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.models.network.Network import com.tangem.features.send.v2.api.entity.* import com.tangem.features.send.v2.feeselector.component.extended.entity.FeeExtendedSelectorUM import com.tangem.features.send.v2.feeselector.component.speed.ui.RegularFeeItemContent @@ -95,6 +98,7 @@ fun FeeExtendedSelectorContent(state: FeeExtendedSelectorUM, modifier: Modifier } } +@Suppress("LongMethod") @Preview @Composable private fun Preview() { @@ -115,6 +119,34 @@ private fun Preview() { onItemLongClick = {}, ) + val cryptoCurrencyStatus = CryptoCurrencyStatus( + currency = CryptoCurrency.Coin( + id = CryptoCurrency.ID.fromValue("coin⟨BITCOIN⟩bitcoin"), + network = Network( + id = Network.ID( + value = "bitcoin", + derivationPath = Network.DerivationPath.None, + ), + backendId = "bitcoin", + name = "Bitcoin", + currencySymbol = "BTC", + derivationPath = Network.DerivationPath.None, + isTestnet = false, + standardType = Network.StandardType.Unspecified("bitcoin"), + hasFiatFeeRate = false, + canHandleTokens = false, + transactionExtrasType = Network.TransactionExtrasType.NONE, + nameResolvingType = Network.NameResolvingType.NONE, + ), + name = "Bitcoin", + symbol = "BTC", + decimals = 8, + iconUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/medium/bitcoin.png", + isCustom = false, + ), + value = CryptoCurrencyStatus.Loading, + ) + val lowFeeItem = FeeItem.Market(Fee.Common(amount = Amount(value = BigDecimal("0.0002876"), blockchain = Blockchain.Ethereum))) @@ -130,6 +162,7 @@ private fun Preview() { isFeeApproximate = false, isFeeConvertibleToFiat = true, isTronToken = false, + feeCryptoCurrencyStatus = cryptoCurrencyStatus, ), feeNonce = FeeNonce.None, feeFiatRateUM = FeeFiatRateUM( diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/speed/ui/FeeSpeedSelectorContent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/speed/ui/FeeSpeedSelectorContent.kt index 2a4a9e6bd5..4f5034555d 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/speed/ui/FeeSpeedSelectorContent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/component/speed/ui/FeeSpeedSelectorContent.kt @@ -50,6 +50,9 @@ import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.test.SendSelectNetworkFeeBottomSheetTestTags import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.models.network.Network import com.tangem.features.send.v2.api.entity.* import com.tangem.features.send.v2.feeselector.component.speed.FeeSpeedSelectorIntents import com.tangem.features.send.v2.feeselector.component.speed.StubFeeSpeedSelectorIntents @@ -473,6 +476,7 @@ private class FeeSpeedSelectorUMContentProvider : CollectionPreviewParameterProv isFeeApproximate = true, isFeeConvertibleToFiat = true, isTronToken = false, + feeCryptoCurrencyStatus = cryptoCurrencyStatus, ), feeFiatRateUM = FeeFiatRateUM( rate = BigDecimal.TEN, @@ -484,44 +488,74 @@ private class FeeSpeedSelectorUMContentProvider : CollectionPreviewParameterProv ), ) -private val customFeeItem = FeeItem.Custom( - fee = Fee.Common(Amount(value = BigDecimal("0.05"), blockchain = Blockchain.Ethereum)), - customValues = persistentListOf( - CustomFeeFieldUM( - value = "0.119806", - onValueChange = {}, - keyboardOptions = KeyboardOptions(), - keyboardActions = KeyboardActions(), - symbol = "ETH", +private val cryptoCurrencyStatus + get() = CryptoCurrencyStatus( + currency = CryptoCurrency.Coin( + id = CryptoCurrency.ID.fromValue("coin⟨BITCOIN⟩bitcoin"), + network = Network( + id = Network.ID( + value = "bitcoin", + derivationPath = Network.DerivationPath.None, + ), + backendId = "bitcoin", + name = "Bitcoin", + currencySymbol = "BTC", + derivationPath = Network.DerivationPath.None, + isTestnet = false, + standardType = Network.StandardType.Unspecified("bitcoin"), + hasFiatFeeRate = false, + canHandleTokens = false, + transactionExtrasType = Network.TransactionExtrasType.NONE, + nameResolvingType = Network.NameResolvingType.NONE, + ), + name = "Bitcoin", + symbol = "BTC", decimals = 8, - title = resourceReference(R.string.send_max_fee), - footer = resourceReference(R.string.send_custom_amount_fee_footer), - label = stringReference("~ 0,03 \$"), - isReadonly = false, + iconUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/medium/bitcoin.png", + isCustom = false, ), - CustomFeeFieldUM( - value = "40000", - onValueChange = {}, - keyboardOptions = KeyboardOptions(), - keyboardActions = KeyboardActions(), - symbol = "GWEI", - decimals = 8, - title = resourceReference(R.string.send_gas_price), - footer = resourceReference(R.string.send_gas_price_footer), - label = null, - isReadonly = false, + value = CryptoCurrencyStatus.Loading, + ) + +private val customFeeItem + get() = FeeItem.Custom( + fee = Fee.Common(Amount(value = BigDecimal("0.05"), blockchain = Blockchain.Ethereum)), + customValues = persistentListOf( + CustomFeeFieldUM( + value = "0.119806", + onValueChange = {}, + keyboardOptions = KeyboardOptions(), + keyboardActions = KeyboardActions(), + symbol = "ETH", + decimals = 8, + title = resourceReference(R.string.send_max_fee), + footer = resourceReference(R.string.send_custom_amount_fee_footer), + label = stringReference("~ 0,03 \$"), + isReadonly = false, + ), + CustomFeeFieldUM( + value = "40000", + onValueChange = {}, + keyboardOptions = KeyboardOptions(), + keyboardActions = KeyboardActions(), + symbol = "GWEI", + decimals = 8, + title = resourceReference(R.string.send_gas_price), + footer = resourceReference(R.string.send_gas_price_footer), + label = null, + isReadonly = false, + ), + CustomFeeFieldUM( + value = "31400", + onValueChange = {}, + keyboardOptions = KeyboardOptions(), + keyboardActions = KeyboardActions(), + symbol = null, + decimals = 8, + title = resourceReference(R.string.send_gas_limit), + footer = resourceReference(R.string.send_gas_limit_footer), + label = null, + isReadonly = false, + ), ), - CustomFeeFieldUM( - value = "31400", - onValueChange = {}, - keyboardOptions = KeyboardOptions(), - keyboardActions = KeyboardActions(), - symbol = null, - decimals = 8, - title = resourceReference(R.string.send_gas_limit), - footer = resourceReference(R.string.send_gas_limit_footer), - label = null, - isReadonly = false, - ), - ), -) \ No newline at end of file + ) \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorBlockModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorBlockModel.kt index e8f6e511c9..36fdc82031 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorBlockModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorBlockModel.kt @@ -25,14 +25,14 @@ import javax.inject.Inject @ModelScoped internal class FeeSelectorBlockModel @Inject constructor( paramsContainer: ParamsContainer, + feeSelectorLogicFactory: FeeSelectorLogic.Factory, override val dispatchers: CoroutineDispatcherProvider, - private val feeSelectorLogicFactory: FeeSelectorLogic.Factory, private val analyticsEventHandler: AnalyticsEventHandler, private val neverShowTapHelpUseCase: NeverShowTapHelpUseCase, private val urlOpener: UrlOpener, ) : Model(), FeeSelectorModelCallback { - private val params = paramsContainer.require() + private val params = paramsContainer.require() private val feeSelectorLogic = feeSelectorLogicFactory.create( params = params, modelScope = modelScope, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt index fd8f950d3e..41ba48e249 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorLogic.kt @@ -1,11 +1,18 @@ package com.tangem.features.send.v2.feeselector.model +import arrow.core.Either import arrow.core.getOrElse import com.tangem.blockchain.common.AmountType +import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase +import com.tangem.domain.transaction.error.GetFeeError +import com.tangem.domain.transaction.models.TransactionFeeExtended import com.tangem.domain.transaction.usecase.IsFeeApproximateUseCase +import com.tangem.features.send.v2.api.SendFeatureToggles import com.tangem.features.send.v2.api.analytics.CommonSendAnalyticEvents.NonceInserted import com.tangem.features.send.v2.api.entity.FeeItem import com.tangem.features.send.v2.api.entity.FeeNonce @@ -38,6 +45,8 @@ internal class FeeSelectorLogic @AssistedInject constructor( private val feeSelectorCheckReloadTrigger: FeeSelectorCheckReloadTrigger, private val feeSelectorAlertFactory: FeeSelectorAlertFactory, private val analyticsEventHandler: AnalyticsEventHandler, + private val sendFeatureToggles: SendFeatureToggles, + private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, ) : FeeSelectorIntents { private var appCurrency: AppCurrency = AppCurrency.Default @@ -51,10 +60,6 @@ internal class FeeSelectorLogic @AssistedInject constructor( loadFee() } - fun updateState(feeSelectorUM: FeeSelectorUM) { - uiState.value = feeSelectorUM - } - private fun initAppCurrency() { modelScope.launch { appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default } @@ -66,18 +71,18 @@ internal class FeeSelectorLogic @AssistedInject constructor( uiState.update(FeeSelectorLoadingTransformer) } modelScope.launch { - params.onLoadFee() + callLoadFee() .fold( ifLeft = { error -> uiState.update(FeeSelectorErrorTransformer(error)) }, ifRight = { fee -> uiState.update( FeeSelectorLoadedTransformer( cryptoCurrencyStatus = params.cryptoCurrencyStatus, - feeCryptoCurrencyStatus = params.feeCryptoCurrencyStatus, + feeCryptoCurrencyStatus = fee.selectedTokenOrNull ?: params.feeCryptoCurrencyStatus, appCurrency = appCurrency, fees = fee, feeStateConfiguration = params.feeStateConfiguration, - isFeeApproximate = isFeeApproximate(fee.normal.amount.type), + isFeeApproximate = isFeeApproximate(fee.transactionFee.normal.amount.type), feeSelectorIntents = this@FeeSelectorLogic, ), ) @@ -98,9 +103,6 @@ internal class FeeSelectorLogic @AssistedInject constructor( ) } uiState.update(FeeItemSelectedTransformer(feeItem)) - if (feeItem !is FeeItem.Custom) { - onDoneClick() - } } override fun onCustomFeeValueChange(index: Int, value: String) { @@ -141,8 +143,6 @@ internal class FeeSelectorLogic @AssistedInject constructor( ), ) } - - (params as? FeeSelectorParams.FeeSelectorDetailsParams)?.callback?.onFeeResult(uiState.value) } private fun subscribeOnFeeReloadTriggerUpdates() { @@ -170,10 +170,10 @@ internal class FeeSelectorLogic @AssistedInject constructor( private fun checkLoadFee() { modelScope.launch { - params.onLoadFee().fold( + callLoadFee().fold( ifRight = { newFee -> feeSelectorAlertFactory.getFeeUpdatedAlert( - newTransactionFee = newFee, + newTransactionFee = newFee.transactionFee, feeSelectorUM = uiState.value, proceedAction = { modelScope.launch { @@ -195,6 +195,61 @@ internal class FeeSelectorLogic @AssistedInject constructor( } } + @Suppress("UnreachableCode") + private suspend fun callLoadFee(): Either { + val extended = params.onLoadFeeExtended + return if (extended != null && sendFeatureToggles.isGaslessTransactionsEnabled) { + extended().fold( + ifLeft = { error -> + if (error is GetFeeError.GaslessError) { + params.onLoadFee().map { LoadedFeeResult.Basic(it) } + } else { + Either.Left(error) + } + }, + ifRight = { fee -> + Either.Right( + LoadedFeeResult.Extended( + fee = fee, + selectedToken = if (params.feeCryptoCurrencyStatus.currency.id != fee.feeTokenId) { + getSingleCryptoCurrencyStatusUseCase + .invokeMultiWalletSync( + userWalletId = TODO(), + cryptoCurrencyId = fee.feeTokenId, + ).getOrNull() + } else { + params.feeCryptoCurrencyStatus + }, + ), + ) + }, + ) + } else { + params.onLoadFee().map { LoadedFeeResult.Basic(it) } + } + } + + sealed class LoadedFeeResult { + data class Extended( + val fee: TransactionFeeExtended, + val selectedToken: CryptoCurrencyStatus?, + ) : LoadedFeeResult() + + data class Basic(val fee: TransactionFee) : LoadedFeeResult() + + val selectedTokenOrNull: CryptoCurrencyStatus? + get() = when (this) { + is Extended -> selectedToken + is Basic -> null + } + + val transactionFee: TransactionFee + get() = when (this) { + is Extended -> fee.transactionFee + is Basic -> fee + } + } + @AssistedFactory interface Factory { fun create(params: FeeSelectorParams, modelScope: CoroutineScope): FeeSelectorLogic diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorModel.kt index 5f82459764..5bf01617b0 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/FeeSelectorModel.kt @@ -1,13 +1,20 @@ package com.tangem.features.send.v2.feeselector.model import androidx.compose.runtime.Stable +import com.arkivanov.decompose.router.stack.StackNavigation +import com.arkivanov.decompose.router.stack.pop 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.utils.stack import com.tangem.features.send.v2.api.SendFeatureToggles +import com.tangem.features.send.v2.api.entity.FeeItem +import com.tangem.features.send.v2.api.entity.FeeSelectorUM import com.tangem.features.send.v2.api.params.FeeSelectorParams import com.tangem.features.send.v2.feeselector.route.FeeSelectorRoute import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.extensions.isSingleItem +import kotlinx.coroutines.launch import javax.inject.Inject @Stable @@ -17,16 +24,61 @@ internal class FeeSelectorModel @Inject constructor( feeSelectorLogicFactory: FeeSelectorLogic.Factory, override val dispatchers: CoroutineDispatcherProvider, private val sendFeatureToggles: SendFeatureToggles, -) : Model() { +) : Model(), FeeSelectorIntents { - private val params = paramsContainer.require() + private val params = paramsContainer.require() private val feeSelectorLogic = feeSelectorLogicFactory.create( params = params, modelScope = modelScope, ) + val stackNavigation = StackNavigation() val uiState = feeSelectorLogic.uiState - val intents: FeeSelectorIntents = feeSelectorLogic + + override fun onFeeItemSelected(feeItem: FeeItem) { + feeSelectorLogic.onFeeItemSelected(feeItem) + + if (contentState().selectedFeeItem is FeeItem.Custom) { + return + } + + modelScope.launch { + val stack = stackNavigation.stack() + if (stack.isSingleItem() && stack[0] is FeeSelectorRoute.ChooseSpeed) { + // In case of only speed selection, we finish the flow immediately after selection + feeSelectorLogic.onDoneClick() + params.callback.onFeeResult(uiState.value) + } else { + stackNavigation.pop() + } + } + } + + override fun onCustomFeeValueChange(index: Int, value: String) { + feeSelectorLogic.onCustomFeeValueChange(index, value) + } + + override fun onNonceChange(value: String) { + feeSelectorLogic.onNonceChange(value) + } + + override fun onDoneClick() { + modelScope.launch { + val stack = stackNavigation.stack() + if (stack.isSingleItem()) { + feeSelectorLogic.onDoneClick() + params.callback.onFeeResult(uiState.value) + } else { + stackNavigation.pop() + } + } + } + + private fun contentState(): FeeSelectorUM.Content { + val currentState = uiState.value + require(currentState is FeeSelectorUM.Content) { "Current state must be FeeSelectorUM.Content" } + return currentState + } fun getInitialRoute(): FeeSelectorRoute { if (sendFeatureToggles.isGaslessTransactionsEnabled.not()) { diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorLoadedTransformer.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorLoadedTransformer.kt index 69a2e8ece2..4b0668785a 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorLoadedTransformer.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/model/transformers/FeeSelectorLoadedTransformer.kt @@ -1,13 +1,13 @@ package com.tangem.features.send.v2.feeselector.model.transformers import com.tangem.blockchain.common.transaction.Fee -import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.features.send.v2.api.entity.* import com.tangem.features.send.v2.api.params.FeeSelectorParams import com.tangem.features.send.v2.feeselector.model.FeeSelectorIntents +import com.tangem.features.send.v2.feeselector.model.FeeSelectorLogic.LoadedFeeResult import com.tangem.lib.crypto.BlockchainUtils.isTron import com.tangem.utils.transformer.Transformer import kotlinx.collections.immutable.ImmutableList @@ -17,7 +17,7 @@ internal class FeeSelectorLoadedTransformer( private val cryptoCurrencyStatus: CryptoCurrencyStatus, private val feeCryptoCurrencyStatus: CryptoCurrencyStatus, private val appCurrency: AppCurrency, - private val fees: TransactionFee, + private val fees: LoadedFeeResult, private val feeStateConfiguration: FeeSelectorParams.FeeStateConfiguration, private val isFeeApproximate: Boolean, private val feeSelectorIntents: FeeSelectorIntents, @@ -25,7 +25,7 @@ internal class FeeSelectorLoadedTransformer( private val feeItemsConverter = FeeItemConverter( feeStateConfiguration = feeStateConfiguration, - normalFee = fees.normal, + normalFee = fees.transactionFee.normal, feeSelectorIntents = feeSelectorIntents, appCurrency = appCurrency, cryptoCurrencyStatus = feeCryptoCurrencyStatus, @@ -37,7 +37,9 @@ internal class FeeSelectorLoadedTransformer( } else { null } - val feeItems: ImmutableList = feeItemsConverter.convert(FeeItemConverter.Input(fees, prevCustomFee)) + val feeItems: ImmutableList = feeItemsConverter.convert( + FeeItemConverter.Input(fees.transactionFee, prevCustomFee), + ) val selectedFee = when (prevState) { is FeeSelectorUM.Content -> feeItems.first { it.isSameClass(prevState.selectedFeeItem) } @@ -50,7 +52,7 @@ internal class FeeSelectorLoadedTransformer( return FeeSelectorUM.Content( isPrimaryButtonEnabled = true, - fees = fees, + fees = fees.transactionFee, feeItems = feeItems, selectedFeeItem = selectedFee, feeExtraInfo = FeeExtraInfo( @@ -58,6 +60,7 @@ internal class FeeSelectorLoadedTransformer( isFeeConvertibleToFiat = feeCryptoCurrencyStatus.currency.network.hasFiatFeeRate, isTronToken = cryptoCurrencyStatus.currency is CryptoCurrency.Token && isTron(cryptoCurrencyStatus.currency.network.rawId), + feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, ), feeFiatRateUM = feeCryptoCurrencyStatus.value.fiatRate?.let { rate -> FeeFiatRateUM( @@ -65,7 +68,7 @@ internal class FeeSelectorLoadedTransformer( appCurrency = appCurrency, ) }, - feeNonce = if (fees.normal is Fee.Ethereum) { + feeNonce = if (fees.transactionFee.normal is Fee.Ethereum) { FeeNonce.Nonce( nonce = nonce, onNonceChange = feeSelectorIntents::onNonceChange, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/route/FeeSelectorRoute.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/route/FeeSelectorRoute.kt index f122f8fed0..270230164d 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/route/FeeSelectorRoute.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/route/FeeSelectorRoute.kt @@ -15,7 +15,7 @@ internal sealed interface FeeSelectorRoute : Route { @Serializable data object NetworkFee : FeeSelectorRoute { - override val title: TextReference = resourceReference(R.string.common_fee_selector_title) + override val title: TextReference = resourceReference(R.string.common_network_fee_title) } @Serializable diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/ui/FeeSelectorBlockContent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/ui/FeeSelectorBlockContent.kt index 27b688a281..19a1c86d96 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/ui/FeeSelectorBlockContent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/feeselector/ui/FeeSelectorBlockContent.kt @@ -42,6 +42,9 @@ import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.test.FeeSelectorBlockTestTags import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.models.network.Network import com.tangem.domain.transaction.error.GetFeeError import com.tangem.features.send.v2.api.entity.* import com.tangem.features.send.v2.impl.R @@ -238,11 +241,48 @@ private fun FeeSelectorBlockContent_Preview(@PreviewParameter(FeeSelectorUMProvi } private class FeeSelectorUMProvider : PreviewParameterProvider { - private val maxFeeItem = FeeItem.Market( - fee = Fee.Common(amount = Amount(value = BigDecimal("100000000"), blockchain = Blockchain.Hedera)), - ) - private val lowFeeItem = - FeeItem.Market(Fee.Common(amount = Amount(value = BigDecimal("0.0002876"), blockchain = Blockchain.Ethereum))) + private val maxFeeItem + get() = FeeItem.Market( + fee = Fee.Common(amount = Amount(value = BigDecimal("100000000"), blockchain = Blockchain.Hedera)), + ) + private val lowFeeItem + get() = FeeItem.Market( + Fee.Common( + amount = Amount( + value = BigDecimal("0.0002876"), + blockchain = Blockchain.Ethereum, + ), + ), + ) + + val cryptoCurrencyStatus + get() = CryptoCurrencyStatus( + currency = CryptoCurrency.Coin( + id = CryptoCurrency.ID.fromValue("coin⟨BITCOIN⟩bitcoin"), + network = Network( + id = Network.ID( + value = "bitcoin", + derivationPath = Network.DerivationPath.None, + ), + backendId = "bitcoin", + name = "Bitcoin", + currencySymbol = "BTC", + derivationPath = Network.DerivationPath.None, + isTestnet = false, + standardType = Network.StandardType.Unspecified("bitcoin"), + hasFiatFeeRate = false, + canHandleTokens = false, + transactionExtrasType = Network.TransactionExtrasType.NONE, + nameResolvingType = Network.NameResolvingType.NONE, + ), + name = "Bitcoin", + symbol = "BTC", + decimals = 8, + iconUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/medium/bitcoin.png", + isCustom = false, + ), + value = CryptoCurrencyStatus.Loading, + ) override val values: Sequence = sequenceOf( FeeSelectorUM.Content( @@ -253,6 +293,7 @@ private class FeeSelectorUMProvider : PreviewParameterProvider { isFeeApproximate = false, isFeeConvertibleToFiat = true, isTronToken = false, + feeCryptoCurrencyStatus = cryptoCurrencyStatus, ), feeNonce = FeeNonce.None, feeFiatRateUM = FeeFiatRateUM( @@ -269,6 +310,7 @@ private class FeeSelectorUMProvider : PreviewParameterProvider { isFeeApproximate = false, isFeeConvertibleToFiat = true, isTronToken = false, + feeCryptoCurrencyStatus = cryptoCurrencyStatus, ), feeNonce = FeeNonce.None, feeFiatRateUM = FeeFiatRateUM( diff --git a/features/send-v2/impl/src/test/java/com/tangem/features/send/v2/send/confirm/model/transformers/NFTSendConfirmationNotificationsTransformerV2Test.kt b/features/send-v2/impl/src/test/java/com/tangem/features/send/v2/send/confirm/model/transformers/NFTSendConfirmationNotificationsTransformerV2Test.kt index b44e37a21d..92dc0a0d66 100644 --- a/features/send-v2/impl/src/test/java/com/tangem/features/send/v2/send/confirm/model/transformers/NFTSendConfirmationNotificationsTransformerV2Test.kt +++ b/features/send-v2/impl/src/test/java/com/tangem/features/send/v2/send/confirm/model/transformers/NFTSendConfirmationNotificationsTransformerV2Test.kt @@ -8,6 +8,8 @@ import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.models.network.Network import com.tangem.features.send.v2.api.entity.* import com.tangem.features.send.v2.common.ui.state.ConfirmUM import com.tangem.features.send.v2.sendnft.confirm.model.transformers.NFTSendConfirmationNotificationsTransformerV2 @@ -28,6 +30,34 @@ class NFTSendConfirmationNotificationsTransformerV2Test { private val appCurrency = AppCurrency(name = "US Dollar", code = "USD", symbol = "$") private val analyticsCategoryName = "test_category" + val cryptoCurrencyStatus = CryptoCurrencyStatus( + currency = CryptoCurrency.Coin( + id = CryptoCurrency.ID.fromValue("coin⟨BITCOIN⟩bitcoin"), + network = Network( + id = Network.ID( + value = "bitcoin", + derivationPath = Network.DerivationPath.None, + ), + backendId = "bitcoin", + name = "Bitcoin", + currencySymbol = "BTC", + derivationPath = Network.DerivationPath.None, + isTestnet = false, + standardType = Network.StandardType.Unspecified("bitcoin"), + hasFiatFeeRate = false, + canHandleTokens = false, + transactionExtrasType = Network.TransactionExtrasType.NONE, + nameResolvingType = Network.NameResolvingType.NONE, + ), + name = "Bitcoin", + symbol = "BTC", + decimals = 8, + iconUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/medium/bitcoin.png", + isCustom = false, + ), + value = CryptoCurrencyStatus.Loading, + ) + @Test fun `GIVEN non content state WHEN transform THEN returns original state`() = runTest { // GIVEN @@ -191,6 +221,7 @@ class NFTSendConfirmationNotificationsTransformerV2Test { isFeeApproximate = false, isFeeConvertibleToFiat = false, isTronToken = false, + feeCryptoCurrencyStatus = cryptoCurrencyStatus, ), feeFiatRateUM = FeeFiatRateUM( rate = BigDecimal("50000"), @@ -274,6 +305,7 @@ class NFTSendConfirmationNotificationsTransformerV2Test { isFeeApproximate = false, isFeeConvertibleToFiat = false, isTronToken = false, + feeCryptoCurrencyStatus = cryptoCurrencyStatus, ), feeFiatRateUM = FeeFiatRateUM( rate = BigDecimal("50000"), @@ -345,6 +377,7 @@ class NFTSendConfirmationNotificationsTransformerV2Test { isFeeApproximate = false, isFeeConvertibleToFiat = false, isTronToken = false, + feeCryptoCurrencyStatus = cryptoCurrencyStatus ), feeFiatRateUM = FeeFiatRateUM( rate = BigDecimal("50000"), @@ -428,6 +461,7 @@ class NFTSendConfirmationNotificationsTransformerV2Test { isFeeApproximate = false, isFeeConvertibleToFiat = false, isTronToken = false, + feeCryptoCurrencyStatus = cryptoCurrencyStatus, ), feeFiatRateUM = FeeFiatRateUM( rate = BigDecimal("50000"), diff --git a/features/send-v2/impl/src/test/java/com/tangem/features/send/v2/send/confirm/model/transformers/SendConfirmationNotificationsTransformerV2Test.kt b/features/send-v2/impl/src/test/java/com/tangem/features/send/v2/send/confirm/model/transformers/SendConfirmationNotificationsTransformerV2Test.kt index 4e3050ec47..ee1d34d98e 100644 --- a/features/send-v2/impl/src/test/java/com/tangem/features/send/v2/send/confirm/model/transformers/SendConfirmationNotificationsTransformerV2Test.kt +++ b/features/send-v2/impl/src/test/java/com/tangem/features/send/v2/send/confirm/model/transformers/SendConfirmationNotificationsTransformerV2Test.kt @@ -10,6 +10,8 @@ import com.tangem.common.ui.notifications.NotificationUM import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.models.network.Network import com.tangem.features.send.v2.api.entity.* import com.tangem.features.send.v2.common.ui.state.ConfirmUM import io.mockk.mockk @@ -30,6 +32,34 @@ class SendConfirmationNotificationsTransformerV2Test { private val appCurrency = AppCurrency(name = "US Dollar", code = "USD", symbol = "$") private val analyticsCategoryName = "test_category" + val cryptoCurrencyStatus = CryptoCurrencyStatus( + currency = CryptoCurrency.Coin( + id = CryptoCurrency.ID.fromValue("coin⟨BITCOIN⟩bitcoin"), + network = Network( + id = Network.ID( + value = "bitcoin", + derivationPath = Network.DerivationPath.None, + ), + backendId = "bitcoin", + name = "Bitcoin", + currencySymbol = "BTC", + derivationPath = Network.DerivationPath.None, + isTestnet = false, + standardType = Network.StandardType.Unspecified("bitcoin"), + hasFiatFeeRate = false, + canHandleTokens = false, + transactionExtrasType = Network.TransactionExtrasType.NONE, + nameResolvingType = Network.NameResolvingType.NONE, + ), + name = "Bitcoin", + symbol = "BTC", + decimals = 8, + iconUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/medium/bitcoin.png", + isCustom = false, + ), + value = CryptoCurrencyStatus.Loading, + ) + @Test fun `GIVEN non content state WHEN transform THEN returns original state`() = runTest { // GIVEN @@ -247,6 +277,7 @@ class SendConfirmationNotificationsTransformerV2Test { isFeeApproximate = false, isFeeConvertibleToFiat = false, isTronToken = false, + feeCryptoCurrencyStatus = cryptoCurrencyStatus, ), feeFiatRateUM = FeeFiatRateUM( rate = BigDecimal("50000"), @@ -330,6 +361,7 @@ class SendConfirmationNotificationsTransformerV2Test { isFeeApproximate = false, isFeeConvertibleToFiat = false, isTronToken = false, + feeCryptoCurrencyStatus = cryptoCurrencyStatus, ), feeFiatRateUM = FeeFiatRateUM( rate = BigDecimal("50000"), @@ -401,6 +433,7 @@ class SendConfirmationNotificationsTransformerV2Test { isFeeApproximate = false, isFeeConvertibleToFiat = false, isTronToken = false, + feeCryptoCurrencyStatus = cryptoCurrencyStatus, ), feeFiatRateUM = FeeFiatRateUM( rate = BigDecimal("50000"), @@ -484,6 +517,7 @@ class SendConfirmationNotificationsTransformerV2Test { isFeeApproximate = false, isFeeConvertibleToFiat = false, isTronToken = false, + feeCryptoCurrencyStatus = cryptoCurrencyStatus, ), feeFiatRateUM = FeeFiatRateUM( rate = BigDecimal("50000"), diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/ui/SendWithSwapSuccessContent.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/ui/SendWithSwapSuccessContent.kt index c106e29968..44ca767ac2 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/ui/SendWithSwapSuccessContent.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/ui/SendWithSwapSuccessContent.kt @@ -333,6 +333,7 @@ private fun SendWithSwapSuccessContent_Preview() { isFeeApproximate = false, isFeeConvertibleToFiat = false, isTronToken = false, + feeCryptoCurrencyStatus = SwapAmountContentPreview.cryptoCurrencyStatus, ), feeFiatRateUM = null, feeNonce = FeeNonce.None,