Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-26 19:10:22 +05:00
parent 3fd8b110ef
commit 1d06981060
19 changed files with 190 additions and 42 deletions

View file

@ -1,6 +1,10 @@
package com.tangem.data.walletmanager.utils
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
import com.tangem.blockchain.common.*
import com.tangem.blockchain.yieldsupply.providers.ethereum.factory.EthereumYieldSupplyDeployCallData
import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyEnterCallData
import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyExitCallData
import com.tangem.blockchainsdk.models.UpdateWalletManagerResult.Address
import com.tangem.domain.models.network.TxInfo
import com.tangem.utils.converter.Converter
@ -40,7 +44,18 @@ internal class TransactionDataToTxHistoryItemConverter(
TransactionStatus.Confirmed -> TxInfo.TransactionStatus.Confirmed
TransactionStatus.Unconfirmed -> TxInfo.TransactionStatus.Unconfirmed
},
type = TxInfo.TransactionType.Transfer,
type = when (val extras = value.extras) {
is EthereumTransactionExtras -> {
when (extras.callData) {
is EthereumYieldSupplyDeployCallData,
is EthereumYieldSupplyEnterCallData,
-> TxInfo.TransactionType.YieldSupply.Enter
is EthereumYieldSupplyExitCallData -> TxInfo.TransactionType.YieldSupply.Exit
else -> TxInfo.TransactionType.Transfer
}
}
else -> TxInfo.TransactionType.Transfer
},
amount = amount,
)
}

View file

@ -12,6 +12,7 @@ import com.tangem.blockchainsdk.utils.toBlockchain
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.yield.supply.YieldSupplyStatus
import com.tangem.domain.utils.convertToSdkAmount
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.yield.supply.YieldSupplyTransactionRepository
@ -56,7 +57,7 @@ internal class DefaultYieldSupplyTransactionRepository(
return buildEnterTransactions(
walletManager = walletManager,
cryptoCurrencyStatus = cryptoCurrencyStatus,
existingYieldContractAddress = existingYieldContractAddress,
existingYieldAddress = existingYieldContractAddress,
calculatedYieldContractAddress = calculatedYieldContractAddress,
maxNetworkFee = maxNetworkFee,
)
@ -109,21 +110,23 @@ internal class DefaultYieldSupplyTransactionRepository(
}
@Suppress("LongParameterList")
private fun buildEnterTransactions(
private suspend fun buildEnterTransactions(
walletManager: WalletManager,
cryptoCurrencyStatus: CryptoCurrencyStatus,
existingYieldContractAddress: String?,
existingYieldAddress: String?,
calculatedYieldContractAddress: String,
maxNetworkFee: Amount,
): MutableList<TransactionData.Uncompiled> {
val enterTransactions = mutableListOf<TransactionData.Uncompiled>()
val cryptoCurrency = cryptoCurrencyStatus.currency as CryptoCurrency.Token
val yieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus
val yieldSupplyStatus = getYieldTokenStatus(walletManager, cryptoCurrency)
val amount = BigDecimal.ZERO.convertToSdkAmount(cryptoCurrencyStatus)
val amount = getEnterAmount(cryptoCurrency, yieldSupplyStatus)
val emptyContractAddress = existingYieldAddress == null || existingYieldAddress == EthereumUtils.ZERO_ADDRESS
when {
existingYieldContractAddress == null || existingYieldContractAddress == EthereumUtils.ZERO_ADDRESS -> {
yieldSupplyStatus == null || emptyContractAddress -> {
enterTransactions.add(
createDeployTransaction(
walletManager = walletManager,
@ -133,7 +136,6 @@ internal class DefaultYieldSupplyTransactionRepository(
),
)
}
yieldSupplyStatus == null -> error("Yield token status is null")
!yieldSupplyStatus.isInitialized -> enterTransactions.add(
createInitTokenTransaction(
walletManager = walletManager,
@ -211,6 +213,28 @@ internal class DefaultYieldSupplyTransactionRepository(
}.onFailure(Timber::e).getOrNull()
}
private suspend fun getYieldTokenStatus(
walletManager: WalletManager,
cryptoCurrency: CryptoCurrency.Token,
): YieldSupplyStatus? = withContext(dispatchers.io) {
runCatching {
val sdkSupplyStatus = walletManager.getYieldSupplyStatus(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,
)
}.onFailure(Timber::e).getOrNull()
}
private fun createDeployTransaction(
walletManager: WalletManager,
cryptoCurrency: CryptoCurrency.Token,
@ -356,4 +380,20 @@ internal class DefaultYieldSupplyTransactionRepository(
else -> error("Data extras not supported for $blockchain")
}
}
private fun getEnterAmount(cryptoCurrency: CryptoCurrency.Token, yieldSupplyStatus: YieldSupplyStatus?) = Amount(
currencySymbol = cryptoCurrency.symbol,
value = BigDecimal.ZERO,
decimals = cryptoCurrency.decimals,
type = AmountType.TokenYieldSupply(
token = Token(
symbol = cryptoCurrency.symbol,
contractAddress = cryptoCurrency.contractAddress,
decimals = cryptoCurrency.decimals,
),
isActive = yieldSupplyStatus?.isActive ?: false,
isInitialized = yieldSupplyStatus?.isInitialized ?: false,
isAllowedToSpend = yieldSupplyStatus?.isAllowedToSpend ?: false,
),
)
}

View file

@ -12,7 +12,6 @@ import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.yield.supply.YieldSupplyStatus
import com.tangem.domain.utils.convertToSdkAmount
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
@ -69,10 +68,10 @@ class DefaultYieldSupplyTransactionRepositoryTest {
@Test
fun `createEnterTransactions returns deploy-approve-enter transactions`() = runTest {
coEvery { walletManager.getYieldContract() } returns EthereumUtils.ZERO_ADDRESS
coEvery { walletManager.getYieldModuleAddress() } returns EthereumUtils.ZERO_ADDRESS
coEvery { walletManager.getYieldSupplyStatus(any()) } returns null
coEvery { walletManager.isAllowedToSpend(any()) } returns false
coEvery { walletManager.calculateYieldContract() } returns yieldContractAddress
coEvery { walletManager.calculateYieldModuleAddress() } returns yieldContractAddress
val result = repository.createEnterTransactions(
userWalletId = userWalletId,
@ -119,8 +118,8 @@ class DefaultYieldSupplyTransactionRepositoryTest {
@Test
fun `createEnterTransactions returns init-approve-enter transactions`() = runTest {
coEvery { walletManager.getYieldContract() } returns yieldContractAddress
coEvery { walletManager.calculateYieldContract() } returns yieldContractAddress
coEvery { walletManager.getYieldModuleAddress() } returns yieldContractAddress
coEvery { walletManager.calculateYieldModuleAddress() } returns yieldContractAddress
coEvery { walletManager.isAllowedToSpend(any()) } returns false
coEvery { walletManager.getYieldSupplyStatus(any()) } returns SDKYieldSupplyStatus(
isActive = false,
@ -172,8 +171,8 @@ class DefaultYieldSupplyTransactionRepositoryTest {
@Test
fun `createEnterTransactions returns reactivate-approve-enter transactions`() = runTest {
coEvery { walletManager.getYieldContract() } returns yieldContractAddress
coEvery { walletManager.calculateYieldContract() } returns yieldContractAddress
coEvery { walletManager.getYieldModuleAddress() } returns yieldContractAddress
coEvery { walletManager.calculateYieldModuleAddress() } returns yieldContractAddress
coEvery { walletManager.isAllowedToSpend(any()) } returns false
coEvery { walletManager.getYieldSupplyStatus(any()) } returns SDKYieldSupplyStatus(
isActive = false,
@ -225,8 +224,8 @@ class DefaultYieldSupplyTransactionRepositoryTest {
@Test
fun `createEnterTransactions returns reactivate-enter transactions`() = runTest {
coEvery { walletManager.getYieldContract() } returns yieldContractAddress
coEvery { walletManager.calculateYieldContract() } returns yieldContractAddress
coEvery { walletManager.getYieldModuleAddress() } returns yieldContractAddress
coEvery { walletManager.calculateYieldModuleAddress() } returns yieldContractAddress
coEvery { walletManager.getYieldSupplyStatus(any()) } returns SDKYieldSupplyStatus(
isActive = false,
isInitialized = true,
@ -266,8 +265,8 @@ class DefaultYieldSupplyTransactionRepositoryTest {
@Test
fun `createEnterTransactions returns enter transactions`() = runTest {
coEvery { walletManager.getYieldContract() } returns yieldContractAddress
coEvery { walletManager.calculateYieldContract() } returns yieldContractAddress
coEvery { walletManager.getYieldModuleAddress() } returns yieldContractAddress
coEvery { walletManager.calculateYieldModuleAddress() } returns yieldContractAddress
coEvery { walletManager.getYieldSupplyStatus(any()) } returns SDKYieldSupplyStatus(
isActive = true,
isInitialized = true,
@ -299,9 +298,7 @@ class DefaultYieldSupplyTransactionRepositoryTest {
val expectedCallData =
YieldSupplyContractCallDataProviderFactory.getExitCallData(mockedContractAddress)
val yieldSupplyStatus = mockk<YieldSupplyStatus>(relaxed = true)
val result = repository.createExitTransaction(userWalletId, cryptoCurrency, yieldSupplyStatus, null)
val result = repository.createExitTransaction(userWalletId, cryptoCurrencyStatus, null)
Truth.assertThat(result).isNotNull()
Truth.assertThat(result.extras).isInstanceOf(EthereumTransactionExtras::class.java)

View file

@ -107,6 +107,16 @@ data class TxInfo(
@Serializable
data class Operation(val name: String) : TransactionType
@Serializable
sealed interface YieldSupply : TransactionType {
@Serializable
data object Enter : YieldSupply
@Serializable
data object Exit : YieldSupply
}
@Serializable
sealed interface Staking : TransactionType {

View file

@ -1,11 +1,11 @@
package com.tangem.features.kyc
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.tangem.core.decompose.context.AppComponentContext
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import androidx.compose.ui.Modifier
/**
* Mocking it for release/external builds to exclude SumSub dependency

View file

@ -53,6 +53,7 @@ internal class TxHistoryItemToTransactionStateConverter(
is TxInfo.TransactionType.Operation,
is TxInfo.TransactionType.Swap,
is TxInfo.TransactionType.Transfer,
is TxInfo.TransactionType.YieldSupply,
is TxInfo.TransactionType.UnknownOperation,
-> if (isOutgoing) R.drawable.ic_arrow_up_24 else R.drawable.ic_arrow_down_24
}
@ -62,7 +63,9 @@ internal class TxHistoryItemToTransactionStateConverter(
is TxInfo.TransactionType.Approve -> resourceReference(R.string.common_approval)
is TxInfo.TransactionType.Operation -> stringReference(type.name)
is TxInfo.TransactionType.Swap -> resourceReference(R.string.common_swap)
is TxInfo.TransactionType.Transfer -> resourceReference(R.string.common_transfer)
is TxInfo.TransactionType.YieldSupply,
is TxInfo.TransactionType.Transfer,
-> resourceReference(R.string.common_transfer)
is TxInfo.TransactionType.Staking.Stake -> resourceReference(R.string.common_stake)
is TxInfo.TransactionType.Staking.Unstake -> resourceReference(R.string.common_unstake)
is TxInfo.TransactionType.Staking.Vote -> resourceReference(R.string.staking_vote)

View file

@ -61,6 +61,7 @@ internal class TxHistoryItemStateConverter(
is TransactionType.Operation,
is TransactionType.Swap,
is TransactionType.Transfer,
is TransactionType.YieldSupply,
is TransactionType.UnknownOperation,
-> if (isOutgoing) R.drawable.ic_arrow_up_24 else R.drawable.ic_arrow_down_24
}
@ -70,7 +71,9 @@ internal class TxHistoryItemStateConverter(
is TransactionType.Approve -> resourceReference(R.string.common_approval)
is TransactionType.Operation -> stringReference(type.name)
is TransactionType.Swap -> resourceReference(R.string.common_swap)
is TransactionType.Transfer -> resourceReference(R.string.common_transfer)
is TransactionType.YieldSupply,
is TransactionType.Transfer,
-> resourceReference(R.string.common_transfer)
is TransactionType.Staking.Stake -> resourceReference(R.string.common_stake)
is TransactionType.Staking.Unstake -> resourceReference(R.string.common_unstake)
is TransactionType.Staking.Vote -> resourceReference(R.string.staking_vote)

View file

@ -26,4 +26,5 @@ internal data class YieldSupplyActionUM(
val currencyIconState: CurrencyIconState,
val yieldSupplyFeeUM: YieldSupplyFeeUM,
val isPrimaryButtonEnabled: Boolean,
val isTransactionSending: Boolean,
)

View file

@ -0,0 +1,13 @@
package com.tangem.features.yield.supply.impl.common.entity.transformer
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM
import com.tangem.utils.transformer.Transformer
internal object YieldSupplyTransactionInProgressTransformer : Transformer<YieldSupplyActionUM> {
override fun transform(prevState: YieldSupplyActionUM): YieldSupplyActionUM {
return prevState.copy(
isPrimaryButtonEnabled = false,
isTransactionSending = true,
)
}
}

View file

@ -0,0 +1,13 @@
package com.tangem.features.yield.supply.impl.common.entity.transformer
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM
import com.tangem.utils.transformer.Transformer
internal object YieldSupplyTransactionReadyTransformer : Transformer<YieldSupplyActionUM> {
override fun transform(prevState: YieldSupplyActionUM): YieldSupplyActionUM {
return prevState.copy(
isPrimaryButtonEnabled = true,
isTransactionSending = false,
)
}
}

View file

@ -143,6 +143,7 @@ private class YieldSupplyActionContentPreviewProvider : PreviewParameterProvider
maxNetworkFeeValue = stringReference("8.50 USDT • \$8.50"),
),
isPrimaryButtonEnabled = false,
isTransactionSending = false,
),
)
}

View file

@ -20,5 +20,9 @@ internal sealed class YieldSupplyUM {
val isAllowedToSpend: Boolean,
) : YieldSupplyUM()
data object Processing : YieldSupplyUM()
@Immutable
sealed class Processing : YieldSupplyUM() {
data object Enter : Processing()
data object Exit : Processing()
}
}

View file

@ -11,19 +11,25 @@ import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.TxInfo
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.features.yield.supply.api.YieldSupplyComponent
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.DelayedWork
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
import kotlin.properties.Delegates
@Suppress("LongParameterList")
@ModelScoped
internal class YieldSupplyModel @Inject constructor(
paramsContainer: ParamsContainer,
@ -31,6 +37,8 @@ internal class YieldSupplyModel @Inject constructor(
private val appRouter: AppRouter,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
@DelayedWork private val coroutineScope: CoroutineScope,
) : Model(), YieldSupplyClickIntents {
private val params = paramsContainer.require<YieldSupplyComponent.Params>()
@ -100,9 +108,22 @@ internal class YieldSupplyModel @Inject constructor(
private fun onDataLoaded(cryptoCurrencyStatus: CryptoCurrencyStatus) {
val yieldSupplyStatus = cryptoCurrencyStatus.value.yieldSupplyStatus
val hasActiveTransaction = cryptoCurrencyStatus.value.hasCurrentNetworkTransactions
val yieldTransaction = cryptoCurrencyStatus.value.pendingTransactions.firstOrNull {
it.type is TxInfo.TransactionType.YieldSupply
}?.type as? TxInfo.TransactionType.YieldSupply
// todo yield supply add processing state
val yieldSupplyUM = when {
hasActiveTransaction && yieldTransaction != null -> {
coroutineScope.launch(dispatchers.io) {
delay(PROCESSING_UPDATE_DELAY)
fetchCurrencyStatusUseCase(userWalletId = userWallet.walletId, cryptoCurrency.id)
}
when (yieldTransaction) {
TxInfo.TransactionType.YieldSupply.Enter -> YieldSupplyUM.Processing.Enter
TxInfo.TransactionType.YieldSupply.Exit -> YieldSupplyUM.Processing.Exit
}
}
yieldSupplyStatus?.isActive == true ->
YieldSupplyUM.Content(
rewardsBalance = TextReference.EMPTY,
@ -121,4 +142,8 @@ internal class YieldSupplyModel @Inject constructor(
uiState.update { yieldSupplyUM }
}
private companion object {
const val PROCESSING_UPDATE_DELAY = 10_000L
}
}

View file

@ -42,7 +42,12 @@ internal fun YieldSupplyBlockContent(yieldSupplyUM: YieldSupplyUM, modifier: Mod
is YieldSupplyUM.Initial -> SupplyInitial(supplyUM)
YieldSupplyUM.Loading -> SupplyLoading()
is YieldSupplyUM.Content -> SupplyContent(supplyUM)
YieldSupplyUM.Processing -> SupplyProcessing()
YieldSupplyUM.Processing.Enter -> SupplyProcessing(
resourceReference(R.string.yield_module_token_details_earn_notification_processing),
)
YieldSupplyUM.Processing.Exit -> SupplyProcessing(
resourceReference(R.string.yield_module_stop_earning),
)
}
}
}
@ -153,7 +158,7 @@ private fun SupplyContent(supplyUM: YieldSupplyUM.Content) {
}
@Composable
private fun SupplyProcessing() {
private fun SupplyProcessing(text: TextReference) {
Column(
verticalArrangement = Arrangement.spacedBy(4.dp),
modifier = Modifier
@ -174,9 +179,7 @@ private fun SupplyProcessing() {
horizontalArrangement = Arrangement.spacedBy(4.dp),
) {
Text(
text = stringResourceSafe(
R.string.yield_module_token_details_earn_notification_processing,
),
text = text.resolveReference(),
style = TangemTheme.typography.body1,
color = TangemTheme.colors.text.tertiary,
)
@ -248,7 +251,8 @@ private class PreviewProvider : PreviewParameterProvider<YieldSupplyUM> {
isAllowedToSpend = true,
),
YieldSupplyUM.Loading,
YieldSupplyUM.Processing,
YieldSupplyUM.Processing.Enter,
YieldSupplyUM.Processing.Exit,
)
}
// endregion

View file

@ -22,12 +22,15 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyGetContractAddressUseCa
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.entity.transformer.YieldSupplyTransactionInProgressTransformer
import com.tangem.features.yield.supply.impl.common.entity.transformer.YieldSupplyTransactionReadyTransformer
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 com.tangem.utils.transformer.update
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
@ -82,6 +85,7 @@ internal class YieldSupplyApproveModel @Inject constructor(
currencyIconState = CryptoCurrencyToIconStateConverter().convert(cryptoCurrency),
yieldSupplyFeeUM = YieldSupplyFeeUM.Loading,
isPrimaryButtonEnabled = false,
isTransactionSending = false,
),
)
@ -105,7 +109,7 @@ internal class YieldSupplyApproveModel @Inject constructor(
fun onClick() {
val yieldSupplyFeeUM = uiState.value.yieldSupplyFeeUM as? YieldSupplyFeeUM.Content ?: return
uiState.update { it.copy(isPrimaryButtonEnabled = false) }
uiState.update(YieldSupplyTransactionInProgressTransformer)
modelScope.launch(dispatchers.default) {
sendTransactionUseCase(
@ -115,6 +119,7 @@ internal class YieldSupplyApproveModel @Inject constructor(
).fold(
ifLeft = {
Timber.e(it.toString())
uiState.update(YieldSupplyTransactionReadyTransformer)
},
ifRight = {
params.callback.onTransactionSent()
@ -136,7 +141,7 @@ internal class YieldSupplyApproveModel @Inject constructor(
}
private suspend fun onLoadFee() {
if (cryptoCurrency !is CryptoCurrency.Token) return
if (cryptoCurrency !is CryptoCurrency.Token || uiState.value.isTransactionSending) return
val contractAddress = yieldSupplyGetContractAddressUseCase.invoke(
userWalletId = userWallet.walletId,

View file

@ -42,6 +42,7 @@ internal class YieldSupplyStartEarningEntryModel @Inject constructor(
currencyIconState = CryptoCurrencyToIconStateConverter().convert(params.cryptoCurrency),
yieldSupplyFeeUM = YieldSupplyFeeUM.Loading,
isPrimaryButtonEnabled = false,
isTransactionSending = false,
),
)

View file

@ -12,6 +12,7 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
@ -21,6 +22,8 @@ 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.common.entity.transformer.YieldSupplyTransactionInProgressTransformer
import com.tangem.features.yield.supply.impl.common.entity.transformer.YieldSupplyTransactionReadyTransformer
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
@ -49,6 +52,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
private val yieldSupplyEstimateEnterFeeUseCase: YieldSupplyEstimateEnterFeeUseCase,
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val yieldSupplyNotificationsUpdateTrigger: YieldSupplyNotificationsUpdateTrigger,
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
) : Model(), YieldSupplyNotificationsComponent.ModelCallback {
private val params: YieldSupplyStartEarningComponent.Params = paramsContainer.require()
@ -84,6 +88,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
currencyIconState = CryptoCurrencyToIconStateConverter().convert(params.cryptoCurrency),
yieldSupplyFeeUM = YieldSupplyFeeUM.Loading,
isPrimaryButtonEnabled = false,
isTransactionSending = false,
),
)
@ -100,7 +105,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
}
private suspend fun onLoadFee() {
if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.Loading) return
if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.Loading || uiState.value.isTransactionSending) return
val transactionListData = yieldSupplyStartEarningUseCase(
userWalletId = userWallet.walletId,
@ -155,7 +160,7 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
fun onClick() {
val yieldSupplyFeeUM = uiState.value.yieldSupplyFeeUM as? YieldSupplyFeeUM.Content ?: return
uiState.update { it.copy(isPrimaryButtonEnabled = false) }
uiState.update(YieldSupplyTransactionInProgressTransformer)
modelScope.launch(dispatchers.default) {
sendTransactionUseCase.invoke(
txsData = yieldSupplyFeeUM.transactionDataList,
@ -163,11 +168,12 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
network = cryptoCurrency.network,
sendMode = TransactionSender.MultipleTransactionSendMode.DEFAULT,
).fold(
ifLeft = {
Timber.e(it.toString())
uiState.update { it.copy(isPrimaryButtonEnabled = true) }
ifLeft = { error ->
Timber.e(error.toString())
uiState.update(YieldSupplyTransactionReadyTransformer)
},
ifRight = {
fetchCurrencyStatusUseCase(userWalletId = userWallet.walletId, cryptoCurrency.id)
modelScope.launch {
params.callback.onTransactionSent()
}

View file

@ -10,6 +10,7 @@ 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.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
import com.tangem.domain.transaction.usecase.GetFeeUseCase
@ -18,6 +19,8 @@ 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.common.entity.transformer.YieldSupplyTransactionInProgressTransformer
import com.tangem.features.yield.supply.impl.common.entity.transformer.YieldSupplyTransactionReadyTransformer
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
@ -78,6 +81,7 @@ internal class YieldSupplyStopEarningModel @Inject constructor(
currencyIconState = CryptoCurrencyToIconStateConverter().convert(cryptoCurrency),
yieldSupplyFeeUM = YieldSupplyFeeUM.Loading,
isPrimaryButtonEnabled = false,
isTransactionSending = false,
),
)
@ -101,7 +105,7 @@ internal class YieldSupplyStopEarningModel @Inject constructor(
fun onClick() {
val yieldSupplyFeeUM = uiState.value.yieldSupplyFeeUM as? YieldSupplyFeeUM.Content ?: return
uiState.update { it.copy(isPrimaryButtonEnabled = false) }
uiState.update(YieldSupplyTransactionInProgressTransformer)
modelScope.launch(dispatchers.default) {
sendTransactionUseCase(
@ -111,6 +115,7 @@ internal class YieldSupplyStopEarningModel @Inject constructor(
).fold(
ifLeft = {
Timber.e(it.toString())
uiState.update(YieldSupplyTransactionReadyTransformer)
},
ifRight = {
params.callback.onTransactionSent()
@ -132,6 +137,8 @@ internal class YieldSupplyStopEarningModel @Inject constructor(
}
private suspend fun onLoadFee() {
if (cryptoCurrency !is CryptoCurrency.Token || uiState.value.isTransactionSending) return
val exitTransitionData = yieldSupplyStopEarningUseCase(
userWalletId = userWallet.walletId,
cryptoCurrencyStatus = cryptoCurrencyStatus,

View file

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