Updated on 2026-08-14
This commit is contained in:
commit
f6a9dd4fd5
17 changed files with 579 additions and 139 deletions
|
|
@ -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() {
|
||||
}
|
||||
}
|
||||
|
|
@ -9,9 +9,11 @@ fun interface ComposableContentComponent {
|
|||
|
||||
@Composable
|
||||
fun Content(modifier: Modifier)
|
||||
}
|
||||
|
||||
fun getEmptyComposableContentComponent() = EmptyComposableContentComponent
|
||||
companion object {
|
||||
val EMPTY = EmptyComposableContentComponent
|
||||
}
|
||||
}
|
||||
|
||||
object EmptyComposableContentComponent : ComposableContentComponent {
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -15,9 +15,11 @@ interface ComposableModularContentComponent {
|
|||
|
||||
@Composable
|
||||
fun Footer()
|
||||
}
|
||||
|
||||
fun getEmptyComposableModularContentComponent() = EmptyComposableModularContentComponent
|
||||
companion object {
|
||||
val EMPTY = EmptyComposableModularContentComponent
|
||||
}
|
||||
}
|
||||
|
||||
object EmptyComposableModularContentComponent : ComposableModularContentComponent {
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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<CryptoCurrencyStatus>,
|
||||
val feeCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
|
||||
val callback: ModelCallback,
|
||||
)
|
||||
|
||||
interface ModelCallback {
|
||||
fun onFeeReload()
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Boolean>
|
||||
|
||||
/** Trigger fee check reload */
|
||||
suspend fun triggerUpdate(data: YieldSupplyNotificationData)
|
||||
}
|
||||
|
||||
interface YieldSupplyNotificationsUpdateListener {
|
||||
/** Flow triggers notifications update */
|
||||
val updateTriggerFlow: Flow<YieldSupplyNotificationData>
|
||||
|
||||
/** Trigger return callback with check result */
|
||||
suspend fun callbackHasError(hasError: Boolean)
|
||||
}
|
||||
|
||||
@Singleton
|
||||
internal class DefaultYieldSupplyNotificationsUpdateTrigger @Inject constructor() :
|
||||
YieldSupplyNotificationsUpdateTrigger,
|
||||
YieldSupplyNotificationsUpdateListener {
|
||||
|
||||
override val hasErrorFlow: Flow<Boolean>
|
||||
field = MutableSharedFlow()
|
||||
|
||||
override val updateTriggerFlow: Flow<YieldSupplyNotificationData>
|
||||
field = MutableSharedFlow()
|
||||
|
||||
override suspend fun triggerUpdate(data: YieldSupplyNotificationData) {
|
||||
updateTriggerFlow.emit(data)
|
||||
}
|
||||
|
||||
override suspend fun callbackHasError(hasError: Boolean) {
|
||||
hasErrorFlow.emit(hasError)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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?,
|
||||
)
|
||||
|
|
@ -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<ImmutableList<NotificationUM>>
|
||||
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,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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<CryptoCurrencyStatus>
|
||||
val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
|
||||
field = MutableStateFlow(
|
||||
CryptoCurrencyStatus(
|
||||
currency = cryptoCurrency,
|
||||
value = CryptoCurrencyStatus.Loading,
|
||||
),
|
||||
)
|
||||
private val feeCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
|
||||
val feeCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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<TransactionData.Uncompiled>,
|
||||
private val feeValue: BigDecimal,
|
||||
private val maxNetworkFee: BigDecimal,
|
||||
) : Transformer<YieldSupplyActionUM> {
|
||||
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),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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<CryptoCurrencyStatus>
|
||||
val feeCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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<TransactionData.Uncompiled>,
|
||||
private val feeValue: BigDecimal,
|
||||
) : Transformer<YieldSupplyActionUM> {
|
||||
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,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue