diff --git a/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableBottomSheetComponent.kt b/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableBottomSheetComponent.kt index 6128a71c4a..d6f98918b8 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableBottomSheetComponent.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableBottomSheetComponent.kt @@ -10,13 +10,16 @@ interface ComposableBottomSheetComponent { @Composable fun BottomSheet() -} -fun getEmptyComposableBottomSheetComponent() = EmptyComposableBottomSheetComponent + companion object { + val EMPTY = EmptyComposableBottomSheetComponent + } +} object EmptyComposableBottomSheetComponent : ComposableBottomSheetComponent { override fun dismiss() {} @Composable - override fun BottomSheet() {} + override fun BottomSheet() { + } } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableContentComponent.kt b/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableContentComponent.kt index b242250e28..9e861ebc84 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableContentComponent.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableContentComponent.kt @@ -9,9 +9,11 @@ fun interface ComposableContentComponent { @Composable fun Content(modifier: Modifier) -} -fun getEmptyComposableContentComponent() = EmptyComposableContentComponent + companion object { + val EMPTY = EmptyComposableContentComponent + } +} object EmptyComposableContentComponent : ComposableContentComponent { @Composable diff --git a/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableModularContentComponent.kt b/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableModularContentComponent.kt index 15a24d2001..f6531b2720 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableModularContentComponent.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableModularContentComponent.kt @@ -15,9 +15,11 @@ interface ComposableModularContentComponent { @Composable fun Footer() -} -fun getEmptyComposableModularContentComponent() = EmptyComposableModularContentComponent + companion object { + val EMPTY = EmptyComposableModularContentComponent + } +} object EmptyComposableModularContentComponent : ComposableModularContentComponent { @Composable diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/DefaultSendWithSwapComponent.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/DefaultSendWithSwapComponent.kt index df40299e1b..99f038db3f 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/DefaultSendWithSwapComponent.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/DefaultSendWithSwapComponent.kt @@ -18,7 +18,6 @@ import com.tangem.core.decompose.context.childByContext import com.tangem.core.decompose.model.getOrCreateModel import com.tangem.core.decompose.navigation.inner.InnerRouter import com.tangem.core.ui.decompose.ComposableContentComponent -import com.tangem.core.ui.decompose.getEmptyComposableContentComponent import com.tangem.core.ui.extensions.resourceReference import com.tangem.domain.swap.models.R import com.tangem.domain.swap.models.SwapDirection @@ -152,9 +151,9 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor( private fun getDestinationComponent(factoryContext: AppComponentContext): ComposableContentComponent { val amountContentUM = model.uiState.value.amountUM as? SwapAmountUM.Content - ?: return getEmptyComposableContentComponent() + ?: return ComposableContentComponent.EMPTY val secondaryCryptoCurrency = amountContentUM.secondaryCryptoCurrencyStatus?.currency - ?: return getEmptyComposableContentComponent() + ?: return ComposableContentComponent.EMPTY return sendDestinationComponentFactory.create( context = factoryContext, diff --git a/features/yield-supply/impl/build.gradle.kts b/features/yield-supply/impl/build.gradle.kts index 0944ea2a33..5eeadd29a9 100644 --- a/features/yield-supply/impl/build.gradle.kts +++ b/features/yield-supply/impl/build.gradle.kts @@ -15,7 +15,6 @@ dependencies { /** Feature */ implementation(projects.features.yieldSupply.api) - implementation(projects.features.sendV2.api) /** Core */ implementation(projects.core.configToggles) @@ -43,6 +42,7 @@ dependencies { implementation(projects.domain.transaction.models) implementation(projects.domain.transaction) implementation(projects.domain.yieldSupply) + implementation(projects.libs.crypto) /** Compose */ implementation(deps.compose.foundation) diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyActionContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyActionContent.kt index ac82f7b925..abdd18d4dc 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyActionContent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/common/ui/YieldSupplyActionContent.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.key import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.LinkAnnotation @@ -19,6 +20,7 @@ import com.tangem.core.ui.components.SpacerH8 import com.tangem.core.ui.components.containers.FooterContainer import com.tangem.core.ui.components.currency.icon.CurrencyIcon import com.tangem.core.ui.components.currency.icon.CurrencyIconState +import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.core.ui.extensions.* import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview @@ -32,12 +34,14 @@ import kotlinx.collections.immutable.persistentListOf internal fun YieldSupplyActionContent( yieldSupplyActionUM: YieldSupplyActionUM, onFooterClick: () -> Unit, + yieldSupplyNotificationsComponent: ComposableContentComponent, modifier: Modifier = Modifier, + enableFooterClick: Boolean = true, iconContent: @Composable ColumnScope.() -> Unit, ) { Column( horizontalAlignment = Alignment.CenterHorizontally, - modifier = modifier.padding(bottom = 16.dp, start = 16.dp, end = 16.dp), + modifier = modifier.padding(bottom = 8.dp, start = 16.dp, end = 16.dp), ) { iconContent() SpacerH24() @@ -55,33 +59,43 @@ internal fun YieldSupplyActionContent( modifier = Modifier.padding(horizontal = 16.dp), ) SpacerH24() - FooterContainer( - footer = annotatedReference { - append(yieldSupplyActionUM.footer.resolveReference()) - appendSpace() - withLink(link = LinkAnnotation.Clickable("LINK_TAG") { onFooterClick() }) { - appendColored( - text = yieldSupplyActionUM.footerLink.resolveReference(), - color = TangemTheme.colors.icon.accent, - ) + key(enableFooterClick) { + FooterContainer( + footer = annotatedReference { + append(yieldSupplyActionUM.footer.resolveReference()) + appendSpace() + if (enableFooterClick) { + withLink(link = LinkAnnotation.Clickable("LINK_TAG") { onFooterClick() }) { + appendColored( + text = yieldSupplyActionUM.footerLink.resolveReference(), + color = TangemTheme.colors.icon.accent, + ) + } + } else { + appendColored( + text = yieldSupplyActionUM.footerLink.resolveReference(), + color = TangemTheme.colors.text.disabled, + ) + } + }, + paddingValues = PaddingValues( + start = 12.dp, + end = 12.dp, + top = 8.dp, + ), + ) { + val fee = when (val yieldSupplyFeeUM = yieldSupplyActionUM.yieldSupplyFeeUM) { + is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.feeValue + YieldSupplyFeeUM.Error -> stringReference(StringsSigns.DASH_SIGN) + YieldSupplyFeeUM.Loading -> null } - }, - paddingValues = PaddingValues( - start = 12.dp, - end = 12.dp, - top = 8.dp, - ), - ) { - val fee = when (val yieldSupplyFeeUM = yieldSupplyActionUM.yieldSupplyFeeUM) { - is YieldSupplyFeeUM.Content -> yieldSupplyFeeUM.feeValue - YieldSupplyFeeUM.Error -> stringReference(StringsSigns.DASH_SIGN) - YieldSupplyFeeUM.Loading -> null + YieldSupplyFeeRow( + title = resourceReference(R.string.common_network_fee_title), + value = fee, + ) } - YieldSupplyFeeRow( - title = resourceReference(R.string.common_network_fee_title), - value = fee, - ) } + yieldSupplyNotificationsComponent.Content(Modifier) } } @@ -96,6 +110,8 @@ private fun YieldSupplyActionContent_Preview( YieldSupplyActionContent( yieldSupplyActionUM = params, onFooterClick = {}, + yieldSupplyNotificationsComponent = ComposableContentComponent.EMPTY, + enableFooterClick = false, modifier = Modifier.background(TangemTheme.colors.background.tertiary), ) { CurrencyIcon( diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/YieldSupplyNotificationsComponent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/YieldSupplyNotificationsComponent.kt new file mode 100644 index 0000000000..366490ead7 --- /dev/null +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/YieldSupplyNotificationsComponent.kt @@ -0,0 +1,62 @@ +package com.tangem.features.yield.supply.impl.subcomponents.notifications + +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.core.ui.components.notifications.Notification +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.core.ui.extensions.conditional +import com.tangem.core.ui.res.TangemTheme +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.features.yield.supply.impl.subcomponents.notifications.model.YieldSupplyNotificationsModel +import kotlinx.coroutines.flow.StateFlow + +internal class YieldSupplyNotificationsComponent( + private val appComponentContext: AppComponentContext, + params: Params, +) : ComposableContentComponent, AppComponentContext by appComponentContext { + + private val model: YieldSupplyNotificationsModel = getOrCreateModel(params = params) + + @Composable + override fun Content(modifier: Modifier) { + val state by model.uiState.collectAsStateWithLifecycle() + + Column( + modifier = modifier + .fillMaxWidth() + .animateContentSize(), + ) { + state.forEachIndexed { index, item -> + Notification( + config = item.config, + modifier = Modifier.conditional(index == 0) { + Modifier.padding(top = 16.dp) + }, + containerColor = TangemTheme.colors.background.action, + iconTint = null, + ) + } + } + } + + data class Params( + val userWalletId: UserWalletId, + val cryptoCurrencyStatusFlow: StateFlow, + val feeCryptoCurrencyStatusFlow: StateFlow, + val callback: ModelCallback, + ) + + interface ModelCallback { + fun onFeeReload() + } +} \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/YieldSupplyNotificationsUpdateTrigger.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/YieldSupplyNotificationsUpdateTrigger.kt new file mode 100644 index 0000000000..d1d1c929ee --- /dev/null +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/YieldSupplyNotificationsUpdateTrigger.kt @@ -0,0 +1,44 @@ +package com.tangem.features.yield.supply.impl.subcomponents.notifications + +import com.tangem.features.yield.supply.impl.subcomponents.notifications.entity.YieldSupplyNotificationData +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import javax.inject.Inject +import javax.inject.Singleton + +interface YieldSupplyNotificationsUpdateTrigger { + + /** Flow returns whether there is error notifications */ + val hasErrorFlow: Flow + + /** Trigger fee check reload */ + suspend fun triggerUpdate(data: YieldSupplyNotificationData) +} + +interface YieldSupplyNotificationsUpdateListener { + /** Flow triggers notifications update */ + val updateTriggerFlow: Flow + + /** Trigger return callback with check result */ + suspend fun callbackHasError(hasError: Boolean) +} + +@Singleton +internal class DefaultYieldSupplyNotificationsUpdateTrigger @Inject constructor() : + YieldSupplyNotificationsUpdateTrigger, + YieldSupplyNotificationsUpdateListener { + + override val hasErrorFlow: Flow + field = MutableSharedFlow() + + override val updateTriggerFlow: Flow + field = MutableSharedFlow() + + override suspend fun triggerUpdate(data: YieldSupplyNotificationData) { + updateTriggerFlow.emit(data) + } + + override suspend fun callbackHasError(hasError: Boolean) { + hasErrorFlow.emit(hasError) + } +} \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/di/YieldSupplyNotificationsModule.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/di/YieldSupplyNotificationsModule.kt new file mode 100644 index 0000000000..315f972093 --- /dev/null +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/di/YieldSupplyNotificationsModule.kt @@ -0,0 +1,33 @@ +package com.tangem.features.yield.supply.impl.subcomponents.notifications.di + +import com.tangem.core.decompose.di.ModelComponent +import com.tangem.core.decompose.model.Model +import com.tangem.features.yield.supply.impl.subcomponents.notifications.DefaultYieldSupplyNotificationsUpdateTrigger +import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsUpdateListener +import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsUpdateTrigger +import com.tangem.features.yield.supply.impl.subcomponents.notifications.model.YieldSupplyNotificationsModel +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(ModelComponent::class) +internal interface YieldSupplyNotificationsModule { + + @Binds + @IntoMap + @ClassKey(YieldSupplyNotificationsModel::class) + fun provideYieldSupplyNotificationsModel(impl: YieldSupplyNotificationsModel): Model + + @Binds + fun provideYieldSupplyNotificationsUpdateListener( + impl: DefaultYieldSupplyNotificationsUpdateTrigger, + ): YieldSupplyNotificationsUpdateListener + + @Binds + fun provideYieldSupplyNotificationsUpdateTrigger( + impl: DefaultYieldSupplyNotificationsUpdateTrigger, + ): YieldSupplyNotificationsUpdateTrigger +} \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/entity/YieldSupplyNotificationData.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/entity/YieldSupplyNotificationData.kt new file mode 100644 index 0000000000..7b9a1e53ef --- /dev/null +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/entity/YieldSupplyNotificationData.kt @@ -0,0 +1,9 @@ +package com.tangem.features.yield.supply.impl.subcomponents.notifications.entity + +import com.tangem.domain.transaction.error.GetFeeError +import java.math.BigDecimal + +data class YieldSupplyNotificationData( + val feeValue: BigDecimal?, + val feeError: GetFeeError?, +) \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/model/YieldSupplyNotificationsModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/model/YieldSupplyNotificationsModel.kt new file mode 100644 index 0000000000..be0223b21d --- /dev/null +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/notifications/model/YieldSupplyNotificationsModel.kt @@ -0,0 +1,89 @@ +package com.tangem.features.yield.supply.impl.subcomponents.notifications.model + +import com.tangem.common.routing.AppRoute +import com.tangem.common.routing.AppRouter +import com.tangem.common.ui.notifications.NotificationUM +import com.tangem.common.ui.notifications.NotificationsFactory.addExceedsBalanceNotification +import com.tangem.common.ui.notifications.NotificationsFactory.addFeeUnreachableNotification +import com.tangem.core.decompose.di.ModelScoped +import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.tokens.GetBalanceNotEnoughForFeeWarningUseCase +import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsComponent +import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsUpdateListener +import com.tangem.lib.crypto.BlockchainUtils +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import com.tangem.utils.extensions.orZero +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList +import kotlinx.coroutines.flow.* +import javax.inject.Inject + +@ModelScoped +internal class YieldSupplyNotificationsModel @Inject constructor( + paramsContainer: ParamsContainer, + override val dispatchers: CoroutineDispatcherProvider, + private val appRouter: AppRouter, + private val getBalanceNotEnoughForFeeWarningUseCase: GetBalanceNotEnoughForFeeWarningUseCase, + private val yieldSupplyNotificationsUpdateListener: YieldSupplyNotificationsUpdateListener, +) : Model() { + + private val params: YieldSupplyNotificationsComponent.Params = paramsContainer.require() + + val uiState: StateFlow> + field = MutableStateFlow(persistentListOf()) + + init { + subscribeToNotificationTrigger() + } + + private fun subscribeToNotificationTrigger() { + yieldSupplyNotificationsUpdateListener.updateTriggerFlow + .onEach { data -> + val cryptoCurrencyStatus = params.cryptoCurrencyStatusFlow.value + val feeCryptoCurrencyStatus = params.feeCryptoCurrencyStatusFlow.value + + val notifications = buildList { + val cryptoCurrencyWarning = getBalanceNotEnoughForFeeWarningUseCase( + fee = data.feeValue.orZero(), + userWalletId = params.userWalletId, + tokenStatus = cryptoCurrencyStatus, + coinStatus = feeCryptoCurrencyStatus, + ).getOrNull() + + addExceedsBalanceNotification( + cryptoCurrencyWarning = cryptoCurrencyWarning, + cryptoCurrencyStatus = cryptoCurrencyStatus, + shouldMergeFeeNetworkName = BlockchainUtils.isArbitrum( + blockchainId = cryptoCurrencyStatus.currency.network.backendId, + ), + onClick = ::openTokenDetails, + onAnalyticsEvent = { }, + ) + + addFeeUnreachableNotification( + tokenStatus = cryptoCurrencyStatus, + coinStatus = feeCryptoCurrencyStatus, + feeError = data.feeError, + onClick = ::openTokenDetails, + onReload = params.callback::onFeeReload, + ) + } + + uiState.update { notifications.toPersistentList() } + + yieldSupplyNotificationsUpdateListener.callbackHasError(notifications.any()) + }.launchIn(modelScope) + } + + private fun openTokenDetails(cryptoCurrency: CryptoCurrency) { + appRouter.push( + AppRoute.CurrencyDetails( + userWalletId = params.userWalletId, + currency = cryptoCurrency, + ), + ) + } +} \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/YieldSupplyStartEarningComponent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/YieldSupplyStartEarningComponent.kt index 30fa2d47fe..2d6f3c615e 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/YieldSupplyStartEarningComponent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/YieldSupplyStartEarningComponent.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle 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.components.PrimaryButtonIconEnd import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle @@ -25,7 +26,9 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.wallet.UserWalletId import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM +import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM import com.tangem.features.yield.supply.impl.common.ui.YieldSupplyActionContent +import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsComponent import com.tangem.features.yield.supply.impl.subcomponents.startearning.model.YieldSupplyStartEarningModel import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -37,6 +40,16 @@ internal class YieldSupplyStartEarningComponent( private val model: YieldSupplyStartEarningModel = getOrCreateModel(params = params) + private val yieldSupplyNotificationsComponent = YieldSupplyNotificationsComponent( + appComponentContext = child("yieldSupplyEnterNotifications"), + params = YieldSupplyNotificationsComponent.Params( + userWalletId = params.userWalletId, + cryptoCurrencyStatusFlow = model.cryptoCurrencyStatusFlow, + feeCryptoCurrencyStatusFlow = model.feeCryptoCurrencyStatusFlow, + callback = model, + ), + ) + init { model.uiState.onEach(params.callback::onResult).launchIn(componentScope) } @@ -57,6 +70,8 @@ internal class YieldSupplyStartEarningComponent( YieldSupplyActionContent( yieldSupplyActionUM = state, onFooterClick = params.callback::onFeePolicyClick, + enableFooterClick = state.yieldSupplyFeeUM is YieldSupplyFeeUM.Content, + yieldSupplyNotificationsComponent = yieldSupplyNotificationsComponent, modifier = modifier, ) { Box( diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt index 12b32f131f..b32de495c6 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/YieldSupplyStartEarningModel.kt @@ -6,13 +6,8 @@ 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.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter -import com.tangem.core.ui.extensions.combinedReference import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.wrappedList -import com.tangem.core.ui.format.bigdecimal.crypto -import com.tangem.core.ui.format.bigdecimal.fiat -import com.tangem.core.ui.format.bigdecimal.format import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus @@ -26,15 +21,18 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyStartEarningUseCase import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM +import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsComponent +import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsUpdateTrigger +import com.tangem.features.yield.supply.impl.subcomponents.notifications.entity.YieldSupplyNotificationData import com.tangem.features.yield.supply.impl.subcomponents.startearning.YieldSupplyStartEarningComponent -import com.tangem.utils.StringsSigns.DOT +import com.tangem.features.yield.supply.impl.subcomponents.startearning.model.transformers.YieldSupplyStartEarningFeeContentTransformer import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.collections.immutable.toPersistentList +import com.tangem.utils.extensions.orZero +import com.tangem.utils.transformer.update import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import timber.log.Timber import java.math.BigDecimal -import java.math.RoundingMode import javax.inject.Inject import kotlin.properties.Delegates @@ -50,21 +48,22 @@ internal class YieldSupplyStartEarningModel @Inject constructor( private val yieldSupplyStartEarningUseCase: YieldSupplyStartEarningUseCase, private val yieldSupplyEstimateEnterFeeUseCase: YieldSupplyEstimateEnterFeeUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, -) : Model() { + private val yieldSupplyNotificationsUpdateTrigger: YieldSupplyNotificationsUpdateTrigger, +) : Model(), YieldSupplyNotificationsComponent.ModelCallback { private val params: YieldSupplyStartEarningComponent.Params = paramsContainer.require() private val cryptoCurrency = params.cryptoCurrency private var userWallet: UserWallet by Delegates.notNull() - private val cryptoCurrencyStatusFlow: StateFlow + val cryptoCurrencyStatusFlow: StateFlow field = MutableStateFlow( CryptoCurrencyStatus( currency = cryptoCurrency, value = CryptoCurrencyStatus.Loading, ), ) - private val feeCryptoCurrencyStatusFlow: StateFlow + val feeCryptoCurrencyStatusFlow: StateFlow field = MutableStateFlow( CryptoCurrencyStatus( currency = cryptoCurrency, @@ -96,6 +95,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor( modelScope.launch { appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default } subscribeOnCurrencyStatusUpdates() + subscribeOnNotificationsErrors() } } @@ -108,61 +108,48 @@ internal class YieldSupplyStartEarningModel @Inject constructor( maxNetworkFee = MAX_NETWORK_FEE, ).getOrNull() ?: return - val updatedTransactionList = yieldSupplyEstimateEnterFeeUseCase.invoke( - userWallet = userWallet, - cryptoCurrency = cryptoCurrency, - transactionDataList = transactionListData, - ).getOrNull() ?: return - - val feeSum = updatedTransactionList.sumOf { - it.fee?.amount?.value ?: BigDecimal.ZERO - } - - val crypto = feeSum.format { crypto(feeCryptoCurrencyStatusFlow.value.currency) } - val fiatFeeValue = feeCryptoCurrencyStatusFlow.value.value.fiatRate?.let { rate -> - feeSum.multiply(rate) - } - - val fiat = fiatFeeValue.format { fiat(appCurrency.code, appCurrency.symbol) } - - val tokenCryptoFeeValue = cryptoCurrencyStatus.value.fiatRate?.let { rate -> - fiatFeeValue?.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) - } - val tokenCryptoFee = tokenCryptoFeeValue.format { crypto(cryptoCurrency) } - - val maxCryptoFee = MAX_NETWORK_FEE.format { crypto(cryptoCurrency) } - val maxFiatFeeValue = cryptoCurrencyStatus.value.fiatRate?.let { rate -> - MAX_NETWORK_FEE.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) - } - val maxFiatFee = maxFiatFeeValue.format { fiat(appCurrency.code, appCurrency.symbol) } - uiState.update { - if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.Loading) { - it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading) - } else { - it.copy( - isPrimaryButtonEnabled = true, // todo yield supply check for notifications - yieldSupplyFeeUM = YieldSupplyFeeUM.Content( - transactionDataList = updatedTransactionList.toPersistentList(), - feeValue = combinedReference( - stringReference(crypto), - stringReference(" $DOT "), - stringReference(fiat), - ), - currentNetworkFeeValue = combinedReference( - stringReference(tokenCryptoFee), - stringReference(" $DOT "), - stringReference(fiat), - ), - maxNetworkFeeValue = combinedReference( - stringReference(maxCryptoFee), - stringReference(" $DOT "), - stringReference(maxFiatFee), - ), + it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading) + } + + yieldSupplyEstimateEnterFeeUseCase.invoke( + userWallet = userWallet, + cryptoCurrency = feeCryptoCurrencyStatusFlow.value.currency, + transactionDataList = transactionListData, + ).fold( + ifLeft = { feeError -> + yieldSupplyNotificationsUpdateTrigger.triggerUpdate( + data = YieldSupplyNotificationData( + feeValue = null, + feeError = feeError, ), ) - } - } + uiState.update { + it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Error) + } + }, + ifRight = { updatedTransactionList -> + val feeSum = updatedTransactionList.sumOf { + it.fee?.amount?.value.orZero() + } + uiState.update( + YieldSupplyStartEarningFeeContentTransformer( + cryptoCurrencyStatus = cryptoCurrencyStatusFlow.value, + feeCryptoCurrencyStatus = feeCryptoCurrencyStatusFlow.value, + appCurrency = appCurrency, + updatedTransactionList = updatedTransactionList, + feeValue = feeSum, + maxNetworkFee = MAX_NETWORK_FEE, + ), + ) + yieldSupplyNotificationsUpdateTrigger.triggerUpdate( + data = YieldSupplyNotificationData( + feeValue = feeSum, + feeError = null, + ), + ) + }, + ) } fun onClick() { @@ -205,6 +192,21 @@ internal class YieldSupplyStartEarningModel @Inject constructor( } } + private fun subscribeOnNotificationsErrors() { + yieldSupplyNotificationsUpdateTrigger.hasErrorFlow + .onEach { hasError -> + uiState.update { + it.copy(isPrimaryButtonEnabled = !hasError) + } + }.launchIn(modelScope) + } + + override fun onFeeReload() { + modelScope.launch { + onLoadFee() + } + } + private fun getCurrenciesStatusUpdates() { getSingleCryptoCurrencyStatusUseCase.invokeMultiWallet( userWalletId = params.userWalletId, diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt new file mode 100644 index 0000000000..0e792d8529 --- /dev/null +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/startearning/model/transformers/YieldSupplyStartEarningFeeContentTransformer.kt @@ -0,0 +1,74 @@ +package com.tangem.features.yield.supply.impl.subcomponents.startearning.model.transformers + +import com.tangem.blockchain.common.TransactionData +import com.tangem.core.ui.extensions.combinedReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.format.bigdecimal.crypto +import com.tangem.core.ui.format.bigdecimal.fiat +import com.tangem.core.ui.format.bigdecimal.format +import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM +import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM +import com.tangem.utils.StringsSigns.DOT +import com.tangem.utils.transformer.Transformer +import kotlinx.collections.immutable.toPersistentList +import java.math.BigDecimal +import java.math.RoundingMode + +internal class YieldSupplyStartEarningFeeContentTransformer( + private val cryptoCurrencyStatus: CryptoCurrencyStatus, + private val feeCryptoCurrencyStatus: CryptoCurrencyStatus, + private val appCurrency: AppCurrency, + private val updatedTransactionList: List, + private val feeValue: BigDecimal, + private val maxNetworkFee: BigDecimal, +) : Transformer { + override fun transform(prevState: YieldSupplyActionUM): YieldSupplyActionUM { + val cryptoCurrency = cryptoCurrencyStatus.currency + val fiatRate = cryptoCurrencyStatus.value.fiatRate + val feeFiatRate = feeCryptoCurrencyStatus.value.fiatRate + + val crypto = feeValue.format { crypto(feeCryptoCurrencyStatus.currency) } + val fiatFeeValue = feeFiatRate?.let(feeValue::multiply) + + val fiat = fiatFeeValue.format { fiat(appCurrency.code, appCurrency.symbol) } + + val tokenCryptoFeeValue = fiatRate?.let { rate -> + fiatFeeValue?.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) + } + + val tokenCryptoFee = tokenCryptoFeeValue.format { crypto(cryptoCurrency) } + + val maxCryptoFee = maxNetworkFee.format { crypto(cryptoCurrency) } + val maxFiatFeeValue = fiatRate?.let { rate -> + maxNetworkFee.divide(rate, cryptoCurrency.decimals, RoundingMode.HALF_UP) + } + val maxFiatFee = maxFiatFeeValue.format { fiat(appCurrency.code, appCurrency.symbol) } + + return if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.Loading) { + prevState.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading) + } else { + prevState.copy( + yieldSupplyFeeUM = YieldSupplyFeeUM.Content( + transactionDataList = updatedTransactionList.toPersistentList(), + feeValue = combinedReference( + stringReference(crypto), + stringReference(" $DOT "), + stringReference(fiat), + ), + currentNetworkFeeValue = combinedReference( + stringReference(tokenCryptoFee), + stringReference(" $DOT "), + stringReference(fiat), + ), + maxNetworkFeeValue = combinedReference( + stringReference(maxCryptoFee), + stringReference(" $DOT "), + stringReference(maxFiatFee), + ), + ), + ) + } + } +} \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/YieldSupplyStopEarningComponent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/YieldSupplyStopEarningComponent.kt index ccf5447946..278f40bf52 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/YieldSupplyStopEarningComponent.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/YieldSupplyStopEarningComponent.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle 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.components.PrimaryButtonIconEnd import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle @@ -25,6 +26,7 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.impl.common.ui.YieldSupplyActionContent +import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsComponent import com.tangem.features.yield.supply.impl.subcomponents.stopearning.model.YieldSupplyStopEarningModel import kotlinx.coroutines.flow.StateFlow @@ -35,6 +37,16 @@ internal class YieldSupplyStopEarningComponent( private val model: YieldSupplyStopEarningModel = getOrCreateModel(params = params) + private val yieldSupplyNotificationsComponent = YieldSupplyNotificationsComponent( + appComponentContext = child("yieldSupplyExitNotifications"), + params = YieldSupplyNotificationsComponent.Params( + userWalletId = params.userWallet.walletId, + cryptoCurrencyStatusFlow = params.cryptoCurrencyStatusFlow, + feeCryptoCurrencyStatusFlow = model.feeCryptoCurrencyStatusFlow, + callback = model, + ), + ) + @Composable override fun Title() { TangemModalBottomSheetTitle( @@ -50,6 +62,7 @@ internal class YieldSupplyStopEarningComponent( YieldSupplyActionContent( yieldSupplyActionUM = state, onFooterClick = model::onReadMoreClick, + yieldSupplyNotificationsComponent = yieldSupplyNotificationsComponent, modifier = modifier, ) { Box( diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt index b24eabaf2e..28e269b07e 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/YieldSupplyStopEarningModel.kt @@ -6,10 +6,8 @@ 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.components.currency.icon.converter.CryptoCurrencyToIconStateConverter -import com.tangem.core.ui.extensions.* -import com.tangem.core.ui.format.bigdecimal.crypto -import com.tangem.core.ui.format.bigdecimal.fiat -import com.tangem.core.ui.format.bigdecimal.format +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.wrappedList import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus @@ -20,13 +18,15 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyStopEarningUseCase import com.tangem.features.yield.supply.impl.R import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM +import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsComponent +import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsUpdateTrigger +import com.tangem.features.yield.supply.impl.subcomponents.notifications.entity.YieldSupplyNotificationData import com.tangem.features.yield.supply.impl.subcomponents.stopearning.YieldSupplyStopEarningComponent -import com.tangem.utils.StringsSigns.DOT +import com.tangem.features.yield.supply.impl.subcomponents.stopearning.model.transformer.YieldSupplyStopEarningFeeContentTransformer import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.collections.immutable.persistentListOf -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.update +import com.tangem.utils.extensions.orZero +import com.tangem.utils.transformer.update +import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject @@ -42,7 +42,8 @@ internal class YieldSupplyStopEarningModel @Inject constructor( private val sendTransactionUseCase: SendTransactionUseCase, private val yieldSupplyStopEarningUseCase: YieldSupplyStopEarningUseCase, private val urlOpener: UrlOpener, -) : Model() { + private val yieldSupplyNotificationsUpdateTrigger: YieldSupplyNotificationsUpdateTrigger, +) : Model(), YieldSupplyNotificationsComponent.ModelCallback { private val params: YieldSupplyStopEarningComponent.Params = paramsContainer.require() @@ -51,10 +52,10 @@ internal class YieldSupplyStopEarningModel @Inject constructor( private val cryptoCurrency = cryptoCurrencyStatus.currency private var userWallet = params.userWallet - private val feeCryptoCurrencyStatusFlow: StateFlow + val feeCryptoCurrencyStatusFlow: StateFlow field = MutableStateFlow( CryptoCurrencyStatus( - cryptoCurrencyStatus.currency, + currency = cryptoCurrencyStatus.currency, value = CryptoCurrencyStatus.Loading, ), ) @@ -84,6 +85,13 @@ internal class YieldSupplyStopEarningModel @Inject constructor( modelScope.launch { appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default } subscribeOnCurrencyStatusUpdates() + subscribeOnNotificationsErrors() + } + } + + override fun onFeeReload() { + modelScope.launch { + onLoadFee() } } @@ -130,39 +138,57 @@ internal class YieldSupplyStopEarningModel @Inject constructor( fee = null, ).getOrNull() ?: return - val fee = getFeeUseCase( + uiState.update { + it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading) + } + + getFeeUseCase( transactionData = exitTransitionData, userWallet = userWallet, network = cryptoCurrency.network, - ).getOrNull() ?: return - - val feeCryptoValue = fee.normal.amount.value - - val feeFiatValue = feeCryptoCurrencyStatus.value.fiatRate?.let { rate -> - feeCryptoValue?.multiply(rate) - } - val cryptoFee = feeCryptoValue.format { crypto(feeCryptoCurrencyStatus.currency) } - val fiatFee = feeFiatValue.format { fiat(appCurrency.code, appCurrency.symbol) } - - uiState.update { - if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.Loading) { - it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading) - } else { - it.copy( - isPrimaryButtonEnabled = true, - yieldSupplyFeeUM = YieldSupplyFeeUM.Content( - transactionDataList = persistentListOf(exitTransitionData.copy(fee = fee.normal)), - feeValue = combinedReference( - stringReference(cryptoFee), - stringReference(" $DOT "), - stringReference(fiatFee), - ), - currentNetworkFeeValue = TextReference.EMPTY, - maxNetworkFeeValue = TextReference.EMPTY, + ).fold( + ifLeft = { feeError -> + yieldSupplyNotificationsUpdateTrigger.triggerUpdate( + data = YieldSupplyNotificationData( + feeValue = null, + feeError = feeError, ), ) - } - } + uiState.update { + it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Error) + } + }, + ifRight = { fee -> + val fee = fee.normal + val feeCryptoValue = fee.amount.value.orZero() + + uiState.update( + YieldSupplyStopEarningFeeContentTransformer( + cryptoCurrencyStatus = cryptoCurrencyStatus, + feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, + appCurrency = appCurrency, + transactions = listOf(exitTransitionData.copy(fee = fee)), + feeValue = feeCryptoValue, + ), + ) + + yieldSupplyNotificationsUpdateTrigger.triggerUpdate( + data = YieldSupplyNotificationData( + feeValue = feeCryptoValue, + feeError = null, + ), + ) + }, + ) + } + + private fun subscribeOnNotificationsErrors() { + yieldSupplyNotificationsUpdateTrigger.hasErrorFlow + .onEach { hasError -> + uiState.update { + it.copy(isPrimaryButtonEnabled = !hasError) + } + }.launchIn(modelScope) } private companion object { diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/transformer/YieldSupplyStopEarningFeeContentTransformer.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/transformer/YieldSupplyStopEarningFeeContentTransformer.kt new file mode 100644 index 0000000000..0e3dbcac3d --- /dev/null +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/subcomponents/stopearning/model/transformer/YieldSupplyStopEarningFeeContentTransformer.kt @@ -0,0 +1,51 @@ +package com.tangem.features.yield.supply.impl.subcomponents.stopearning.model.transformer + +import com.tangem.blockchain.common.TransactionData +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.combinedReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.format.bigdecimal.crypto +import com.tangem.core.ui.format.bigdecimal.fiat +import com.tangem.core.ui.format.bigdecimal.format +import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM +import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM +import com.tangem.utils.StringsSigns.DOT +import com.tangem.utils.transformer.Transformer +import kotlinx.collections.immutable.toPersistentList +import java.math.BigDecimal + +internal class YieldSupplyStopEarningFeeContentTransformer( + private val cryptoCurrencyStatus: CryptoCurrencyStatus, + private val feeCryptoCurrencyStatus: CryptoCurrencyStatus, + private val appCurrency: AppCurrency, + private val transactions: List, + private val feeValue: BigDecimal, +) : Transformer { + override fun transform(prevState: YieldSupplyActionUM): YieldSupplyActionUM { + val feeFiatValue = feeCryptoCurrencyStatus.value.fiatRate?.let { rate -> + feeValue.multiply(rate) + } + val cryptoFee = feeValue.format { crypto(feeCryptoCurrencyStatus.currency) } + val fiatFee = feeFiatValue.format { fiat(appCurrency.code, appCurrency.symbol) } + + return if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.Loading) { + prevState.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading) + } else { + prevState.copy( + isPrimaryButtonEnabled = true, + yieldSupplyFeeUM = YieldSupplyFeeUM.Content( + transactionDataList = transactions.toPersistentList(), + feeValue = combinedReference( + stringReference(cryptoFee), + stringReference(" $DOT "), + stringReference(fiatFee), + ), + currentNetworkFeeValue = TextReference.EMPTY, + maxNetworkFeeValue = TextReference.EMPTY, + ), + ) + } + } +} \ No newline at end of file