Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-22 17:28:37 +05:00
parent 6d3a1d6e89
commit f73a344ae2
16 changed files with 469 additions and 12 deletions

View file

@ -4,6 +4,7 @@ import com.tangem.domain.transaction.FeeRepository
import com.tangem.domain.transaction.error.FeeErrorResolver
import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository
import com.tangem.domain.yield.supply.usecase.YieldSupplyEstimateEnterFeeUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetContractAddressUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyStartEarningUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyStopEarningUseCase
import dagger.Module
@ -47,4 +48,15 @@ internal object YieldSupplyDomainModule {
feeErrorResolver = feeErrorResolver,
)
}
@Provides
@Singleton
fun provideYieldSupplyGetContractAddressUseCase(
yieldSupplyTransactionRepository: YieldSupplyTransactionRepository,
): YieldSupplyGetContractAddressUseCase {
return YieldSupplyGetContractAddressUseCase(
yieldSupplyTransactionRepository = yieldSupplyTransactionRepository,
)
}
}

View file

@ -138,7 +138,7 @@ internal class DefaultYieldSupplyTransactionRepository(
else -> Unit
}
if (yieldTokenStatus?.isAllowedToSpend == false) {
if (yieldTokenStatus?.isAllowedToSpend != true) {
enterTransactions.add(
createTransaction(
walletManager = walletManager,
@ -182,7 +182,7 @@ internal class DefaultYieldSupplyTransactionRepository(
.getOrNull()
}
private suspend fun getYieldContractAddress(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): String? =
override suspend fun getYieldContractAddress(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): String? =
withContext(dispatchers.io) {
require(cryptoCurrency is CryptoCurrency.Token)
runCatching {
@ -203,13 +203,18 @@ internal class DefaultYieldSupplyTransactionRepository(
require(cryptoCurrency is CryptoCurrency.Token)
runCatching {
val sdkSupplyStatus = walletManager.getYieldSupplyStatus(cryptoCurrency.contractAddress)
val isAllowedToSpend = walletManager.isAllowedToSpend(cryptoCurrency.contractAddress)
val isAllowedToSpend = walletManager.isAllowedToSpend(
Token(
symbol = cryptoCurrency.symbol,
contractAddress = cryptoCurrency.contractAddress,
decimals = cryptoCurrency.decimals,
),
)
YieldSupplyStatus(
isActive = sdkSupplyStatus?.isActive == true,
isInitialized = sdkSupplyStatus?.isInitialized == true,
isAllowedToSpend = isAllowedToSpend,
// maxNetworkFee = sdkSupplyStatus?.maxNetworkFee,
)
}.onFailure(Timber::e).getOrNull()
}

View file

@ -22,4 +22,6 @@ interface YieldSupplyTransactionRepository {
yieldSupplyStatus: YieldSupplyStatus,
fee: Fee?,
): TransactionData.Uncompiled
suspend fun getYieldContractAddress(userWalletId: UserWalletId, cryptoCurrency: CryptoCurrency): String?
}

View file

@ -0,0 +1,21 @@
package com.tangem.domain.yield.supply.usecase
import arrow.core.Either
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository
class YieldSupplyGetContractAddressUseCase(
private val yieldSupplyTransactionRepository: YieldSupplyTransactionRepository,
) {
suspend operator fun invoke(
userWalletId: UserWalletId,
cryptoCurrency: CryptoCurrency.Token,
): Either<Throwable, String?> = Either.catch {
yieldSupplyTransactionRepository.getYieldContractAddress(
userWalletId = userWalletId,
cryptoCurrency = cryptoCurrency,
)
}
}

View file

@ -141,7 +141,8 @@ sealed class WalletNotification(val config: NotificationConfig) {
data object YeildSupplyApprove : Warning(
title = resourceReference(R.string.yield_module_main_view_approve_notification_title),
subtitle = resourceReference(R.string.yield_module_main_view_approve_notification_description),
// todo yield supply lokalise
subtitle = resourceReference(R.string.yield_module_main_view_approve_notification_title),
)
}

View file

@ -59,5 +59,6 @@ internal class YieldSupplyActiveComponent(
interface ModelCallback {
fun onBackClick()
fun onStopEarning()
fun onApprove()
}
}

View file

@ -17,6 +17,7 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.features.yield.supply.impl.subcomponents.active.model.YieldSupplyActiveEntryModel
import com.tangem.features.yield.supply.impl.subcomponents.active.model.YieldSupplyActiveRoute
import com.tangem.features.yield.supply.impl.subcomponents.active.ui.YieldSupplyActiveEntryBottomSheet
import com.tangem.features.yield.supply.impl.subcomponents.approve.YieldSupplyApproveComponent
import com.tangem.features.yield.supply.impl.subcomponents.stopearning.YieldSupplyStopEarningComponent
import kotlinx.coroutines.flow.StateFlow
@ -77,7 +78,7 @@ internal class YieldSupplyActiveEntryComponent(
callback = model,
),
)
YieldSupplyActiveRoute.Action -> YieldSupplyStopEarningComponent(
YieldSupplyActiveRoute.Exit -> YieldSupplyStopEarningComponent(
appComponentContext = factoryContext,
params = YieldSupplyStopEarningComponent.Params(
userWallet = params.userWallet,
@ -85,6 +86,14 @@ internal class YieldSupplyActiveEntryComponent(
callback = model,
),
)
YieldSupplyActiveRoute.Approve -> YieldSupplyApproveComponent(
appComponentContext = factoryContext,
params = YieldSupplyApproveComponent.Params(
userWallet = params.userWallet,
cryptoCurrencyStatusFlow = params.cryptoCurrencyStatusFlow,
callback = model,
),
)
}
private fun onChildBack() {

View file

@ -1,5 +1,6 @@
package com.tangem.features.yield.supply.impl.subcomponents.active.entity
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.ui.extensions.TextReference
internal data class YieldSupplyActiveContentUM(
@ -8,4 +9,5 @@ internal data class YieldSupplyActiveContentUM(
val providerTitle: TextReference,
val subtitle: TextReference,
val subtitleLink: TextReference,
val notificationUM: NotificationUM?,
)

View file

@ -6,6 +6,7 @@ import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.navigation.Router
import com.tangem.features.yield.supply.impl.subcomponents.active.YieldSupplyActiveComponent
import com.tangem.features.yield.supply.impl.subcomponents.active.YieldSupplyActiveEntryComponent
import com.tangem.features.yield.supply.impl.subcomponents.approve.YieldSupplyApproveComponent
import com.tangem.features.yield.supply.impl.subcomponents.stopearning.YieldSupplyStopEarningComponent
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import javax.inject.Inject
@ -15,12 +16,14 @@ internal class YieldSupplyActiveEntryModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
paramsContainer: ParamsContainer,
private val router: Router,
) : Model(), YieldSupplyActiveComponent.ModelCallback, YieldSupplyStopEarningComponent.ModelCallback {
) : Model(), YieldSupplyActiveComponent.ModelCallback,
YieldSupplyStopEarningComponent.ModelCallback,
YieldSupplyApproveComponent.ModelCallback {
private val params = paramsContainer.require<YieldSupplyActiveEntryComponent.Params>()
override fun onStopEarning() {
router.push(YieldSupplyActiveRoute.Action)
router.push(YieldSupplyActiveRoute.Exit)
}
override fun onBackClick() {
@ -30,4 +33,8 @@ internal class YieldSupplyActiveEntryModel @Inject constructor(
override fun onTransactionSent() {
params.onDismiss()
}
override fun onApprove() {
router.push(YieldSupplyActiveRoute.Approve)
}
}

View file

@ -1,8 +1,10 @@
package com.tangem.features.yield.supply.impl.subcomponents.active.model
import com.tangem.common.ui.notifications.NotificationUM
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.notifications.NotificationConfig
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList
@ -12,8 +14,7 @@ import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.impl.subcomponents.active.YieldSupplyActiveComponent
import com.tangem.features.yield.supply.impl.subcomponents.active.entity.YieldSupplyActiveContentUM
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.*
import javax.inject.Inject
@ModelScoped
@ -42,6 +43,32 @@ internal class YieldSupplyActiveModel @Inject constructor(
formatArgs = wrappedList(cryptoCurrency.symbol, cryptoCurrency.symbol),
),
subtitleLink = resourceReference(R.string.common_read_more),
notificationUM = null,
),
)
init {
subscribeOnCurrencyUpdates()
}
private fun subscribeOnCurrencyUpdates() {
cryptoCurrencyStatusFlow.onEach { cryptoCurrencyStatus ->
val approvalNotification = if (cryptoCurrencyStatus.value.yieldSupplyStatus?.isAllowedToSpend != true) {
NotificationUM.Error(
title = resourceReference(R.string.yield_module_approve_needed_notification_title),
subtitle = resourceReference(R.string.yield_module_approve_needed_notification_description),
iconResId = R.drawable.ic_alert_triangle_20,
buttonState = NotificationConfig.ButtonsState.PrimaryButtonConfig(
text = resourceReference(R.string.yield_module_approve_needed_notification_cta),
onClick = params.callback::onApprove,
),
)
} else {
null
}
uiState.update { it.copy(notificationUM = approvalNotification) }
}.flowOn(dispatchers.default)
.launchIn(modelScope)
}
}

View file

@ -4,5 +4,6 @@ import com.tangem.core.decompose.navigation.Route
internal sealed class YieldSupplyActiveRoute : Route {
data object Info : YieldSupplyActiveRoute()
data object Action : YieldSupplyActiveRoute()
data object Exit : YieldSupplyActiveRoute()
data object Approve : YieldSupplyActiveRoute()
}

View file

@ -1,6 +1,7 @@
package com.tangem.features.yield.supply.impl.subcomponents.active.ui
import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
@ -8,6 +9,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@ -19,10 +21,12 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.ui.components.ResizableText
import com.tangem.core.ui.components.SpacerH4
import com.tangem.core.ui.components.SpacerH8
import com.tangem.core.ui.components.SpacerWMax
import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -58,6 +62,15 @@ internal fun YieldSupplyActiveContent(state: YieldSupplyActiveContentUM, modifie
)
}
YieldSupplyActiveMyFunds(state = state)
AnimatedVisibility(state.notificationUM != null) {
val wrappedNotification = remember(this) { requireNotNull(state.notificationUM) }
Notification(
config = wrappedNotification.config,
iconTint = null,
containerColor = TangemTheme.colors.background.action,
)
}
}
}
@ -182,6 +195,7 @@ private class YieldSupplyActiveBottomSheetPreviewProvider : PreviewParameterProv
wrappedList("USDT", "USDT"),
),
subtitleLink = resourceReference(R.string.common_read_more),
notificationUM = NotificationUM.Error.InvalidAmount,
),
)
}

View file

@ -0,0 +1,110 @@
package com.tangem.features.yield.supply.impl.subcomponents.approve
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
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
import com.tangem.core.ui.decompose.ComposableModularContentComponent
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
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.approve.model.YieldSupplyApproveModel
import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsComponent
import kotlinx.coroutines.flow.StateFlow
@Suppress("MagicNumber")
internal class YieldSupplyApproveComponent(
private val appComponentContext: AppComponentContext,
private val params: Params,
) : ComposableModularContentComponent, AppComponentContext by appComponentContext {
private val model: YieldSupplyApproveModel = getOrCreateModel(params = params)
private val yieldSupplyNotificationsComponent = YieldSupplyNotificationsComponent(
appComponentContext = child("yieldSupplyApproveNotifications"),
params = YieldSupplyNotificationsComponent.Params(
userWalletId = params.userWallet.walletId,
cryptoCurrencyStatusFlow = params.cryptoCurrencyStatusFlow,
feeCryptoCurrencyStatusFlow = model.feeCryptoCurrencyStatusFlow,
callback = model,
),
)
@Composable
override fun Title() {
TangemModalBottomSheetTitle(
startIconRes = R.drawable.ic_back_24,
onStartClick = params.callback::onBackClick,
)
}
@Composable
override fun Content(modifier: Modifier) {
val state by model.uiState.collectAsStateWithLifecycle()
YieldSupplyActionContent(
yieldSupplyActionUM = state,
onFooterClick = model::onReadMoreClick,
yieldSupplyNotificationsComponent = yieldSupplyNotificationsComponent,
modifier = modifier,
) {
Box(
modifier = Modifier
.size(56.dp)
.background(TangemTheme.colors.icon.accent.copy(0.1f), CircleShape),
) {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_check_circle_24),
contentDescription = null,
tint = TangemTheme.colors.icon.accent,
modifier = Modifier
.padding(12.dp)
.size(32.dp),
)
}
}
}
@Composable
override fun Footer() {
val state by model.uiState.collectAsStateWithLifecycle()
PrimaryButtonIconEnd(
text = stringResourceSafe(R.string.common_confirm),
onClick = model::onClick,
iconResId = R.drawable.ic_tangem_24,
enabled = state.isPrimaryButtonEnabled,
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
)
}
data class Params(
val userWallet: UserWallet,
val cryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>,
val callback: ModelCallback,
)
interface ModelCallback {
fun onBackClick()
fun onTransactionSent()
}
}

View file

@ -0,0 +1,20 @@
package com.tangem.features.yield.supply.impl.subcomponents.approve.di
import com.tangem.core.decompose.di.ModelComponent
import com.tangem.core.decompose.model.Model
import com.tangem.features.yield.supply.impl.subcomponents.approve.model.YieldSupplyApproveModel
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
@Module
@InstallIn(ModelComponent::class)
internal interface YieldSupplyApproveModule {
@Binds
@IntoMap
@ClassKey(YieldSupplyApproveModel::class)
fun provideYieldSupplyApproveModel(impl: YieldSupplyApproveModel): Model
}

View file

@ -0,0 +1,225 @@
package com.tangem.features.yield.supply.impl.subcomponents.approve.model
import arrow.core.getOrElse
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.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.domain.appcurrency.GetSelectedAppCurrencyUseCase
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.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
import com.tangem.domain.transaction.usecase.CreateApprovalTransactionUseCase
import com.tangem.domain.transaction.usecase.GetFeeUseCase
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetContractAddressUseCase
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.approve.YieldSupplyApproveComponent
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.utils.StringsSigns.DOT
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@Suppress("LongParameterList")
@ModelScoped
internal class YieldSupplyApproveModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
paramsContainer: ParamsContainer,
private val urlOpener: UrlOpener,
private val yieldSupplyNotificationsUpdateTrigger: YieldSupplyNotificationsUpdateTrigger,
private val createApprovalTransactionUseCase: CreateApprovalTransactionUseCase,
private val getFeeUseCase: GetFeeUseCase,
private val sendTransactionUseCase: SendTransactionUseCase,
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
private val yieldSupplyGetContractAddressUseCase: YieldSupplyGetContractAddressUseCase,
) : Model(), YieldSupplyNotificationsComponent.ModelCallback {
private val params: YieldSupplyApproveComponent.Params = paramsContainer.require()
private val cryptoCurrencyStatus
get() = params.cryptoCurrencyStatusFlow.value
private val cryptoCurrency = cryptoCurrencyStatus.currency
private var userWallet = params.userWallet
val feeCryptoCurrencyStatusFlow: StateFlow<CryptoCurrencyStatus>
field = MutableStateFlow(
CryptoCurrencyStatus(
cryptoCurrencyStatus.currency,
value = CryptoCurrencyStatus.Loading,
),
)
private val feeCryptoCurrencyStatus: CryptoCurrencyStatus
get() = feeCryptoCurrencyStatusFlow.value
private var appCurrency = AppCurrency.Default
val uiState: StateFlow<YieldSupplyActionUM>
field: MutableStateFlow<YieldSupplyActionUM> = MutableStateFlow(
YieldSupplyActionUM(
title = resourceReference(R.string.yield_module_approve_sheet_title),
subtitle = resourceReference(
id = R.string.yield_module_approve_sheet_subtitle,
formatArgs = wrappedList(cryptoCurrency.symbol),
),
footer = resourceReference(R.string.yield_module_approve_sheet_fee_note),
footerLink = resourceReference(R.string.common_read_more),
currencyIconState = CryptoCurrencyToIconStateConverter().convert(cryptoCurrency),
yieldSupplyFeeUM = YieldSupplyFeeUM.Loading,
isPrimaryButtonEnabled = false,
),
)
init {
modelScope.launch {
appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default }
subscribeOnCurrencyStatusUpdates()
subscribeOnNotificationsErrors()
}
}
fun onReadMoreClick() {
urlOpener.openUrl(READ_MORE_URL)
}
override fun onFeeReload() {
modelScope.launch {
onLoadFee()
}
}
fun onClick() {
val yieldSupplyFeeUM = uiState.value.yieldSupplyFeeUM as? YieldSupplyFeeUM.Content ?: return
uiState.update { it.copy(isPrimaryButtonEnabled = false) }
modelScope.launch(dispatchers.default) {
sendTransactionUseCase(
txData = yieldSupplyFeeUM.transactionDataList.first(),
userWallet = userWallet,
network = cryptoCurrency.network,
).fold(
ifLeft = {
Timber.e(it.toString())
},
ifRight = {
params.callback.onTransactionSent()
},
)
}
}
private fun subscribeOnCurrencyStatusUpdates() {
modelScope.launch {
feeCryptoCurrencyStatusFlow.update {
getFeePaidCryptoCurrencyStatusSyncUseCase(
userWalletId = userWallet.walletId,
cryptoCurrencyStatus = cryptoCurrencyStatus,
).getOrNull() ?: cryptoCurrencyStatus
}
onLoadFee()
}
}
private suspend fun onLoadFee() {
if (cryptoCurrency !is CryptoCurrency.Token) return
val contractAddress = yieldSupplyGetContractAddressUseCase.invoke(
userWalletId = userWallet.walletId,
cryptoCurrency = cryptoCurrency,
).getOrNull() ?: return
val approvalTransitionData = createApprovalTransactionUseCase(
cryptoCurrency = cryptoCurrency,
userWalletId = userWallet.walletId,
contractAddress = cryptoCurrency.contractAddress,
spenderAddress = contractAddress,
amount = null,
).getOrElse {
Timber.e(it)
return
}
uiState.update { it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading) }
getFeeUseCase(
transactionData = approvalTransitionData,
userWallet = userWallet,
network = cryptoCurrency.network,
).fold(
ifLeft = { feeError ->
yieldSupplyNotificationsUpdateTrigger.triggerUpdate(
data = YieldSupplyNotificationData(
feeValue = null,
feeError = feeError,
),
)
uiState.update {
it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Error)
}
},
ifRight = { fee ->
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(approvalTransitionData.copy(fee = fee.normal)),
feeValue = combinedReference(
stringReference(cryptoFee),
stringReference(" $DOT "),
stringReference(fiatFee),
),
currentNetworkFeeValue = TextReference.EMPTY,
maxNetworkFeeValue = TextReference.EMPTY,
),
)
}
}
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 {
const val READ_MORE_URL = "https://tangem.com" // todo yield supply replace with real link
}
}

View file

@ -5,7 +5,7 @@
# https://github.com/tangem/tangem-sdk-android/
# https://github.com/tangem/vico
tangemBlockchainSdk = "develop-1230"
tangemBlockchainSdk = "develop-1236"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
tangemCardSdk = "develop-564"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^